Azure / azure-powershell

Microsoft Azure PowerShell
Other
4.18k stars 3.79k forks source link

Breaking changes with Get-AzAccessToken Token property changed from String to SecureString #25533

Closed dadthiele closed 1 month ago

dadthiele commented 1 month ago

Description

https://learn.microsoft.com/en-us/powershell/azure/upcoming-breaking-changes?view=azps-12.1.0#get-azaccesstoken

With the change my understanding is that there will not be a way to get the plaintext Token? How do we work around this with other PS commands that dont have a securestring option eg: Invoke-Sqlcmd (and many others)

https://learn.microsoft.com/en-us/powershell/module/sqlserver/invoke-sqlcmd?view=sqlserver-ps $access_token = (Get-AzAccessToken -ResourceUrl https://database.windows.net).token/

Script or Debug output

No response

Environment data

No response

Module versions

No response

Error output

No response

ITJoeSchmo commented 1 month ago

There are a number of options to decrypting a SecureString in PowerShell.

My favorite way is to simply cast it as a PSCredential and then reference the .Password property under the .GetNetworkCredential() method. Let's say you have a SecureString token in the var $encryptedToken

$encryptedToken = (Get-AzAccessToken -ResourceUrl 'https://api.loganalytics.io' -AsSecureString).token
$tokenCredential = [PSCredential]::new("token", $encryptedToken)

Note "token" is just a placeholder since a credential object expects a username. Then you can simply reference/decrypt the password when/where needed with: $tokenCredential.GetNetworkCredential().Password

Herre is another method that may make more sense / be more readable: $AccessToken = New-Object System.Management.Automation.PSCredential("token", (Get-AzAccessToken -ResourceUrl 'https://api.loganalytics.io' -AsSecureString).token) then decrypt/reference for plaintext: $AccessToken.GetNetworkCredential().Password

It is better security poster to not just store the plaintext password in the RAM; if something managed to get a dump of the RAM they'd have the password. I try to only store passwords as SecureStrings and then decrypt them in functions, so they are removed from RAM quickly. If they end up getting decrypted in the main script and stored in a var, I will $null it out after it isn't needed. Usually in the Finally {} block after a Try {} where the var is used.

dadthiele commented 1 month ago

Thanks @ITJoeSchmo . We are using managed identity for a lot use the use-cases where a token is needed to execute sql on an azure database. I think I have worked out a way forward for us (see below) but it would be good to understand why the default will be securestring and the option is still only -assecurestring. I would expect a -asplaintext option instead if the default is secure string.

$access_token = (ConvertFrom-SecureString (Get-AzAccessToken -ResourceUrl https://database.windows.net -AsSecureString).Token -AsPlainText)

ITJoeSchmo commented 1 month ago

Thanks for mentioning that cmdlet ConvertFrom-SecureString. For some reason I thought it wasn't available in 5.1 but it looks like maybe it is. I can't speak officially, but I believe it is simply to follow best practices with security. As I had said the password would be stored in plaintext in the RAM (memory) of the execution environment while the process is running when stored as a normal string.

It's the same reason any PSCredential object in PowerShell has its password stored as a SecureString, and why if you're updating someone's password in Active Directory via PowerShell, the new password must also be a SecureString object.

On Mon, Jul 15, 2024, 6:56 PM dadthiele @.***> wrote:

Thanks @ITJoeSchmo https://github.com/ITJoeSchmo . We are using managed identity for a lot use the use-cases where a token is needed to execute sql on an azure database. I think I have worked out a way forward for us (see below) but it would be good to understand why the default will be securestring and the option is still only -assecurestring. I would expect a -asplaintext option instead if the default is secure string.

$access_token = (ConvertFrom-SecureString (Get-AzAccessToken -ResourceUrl https://database.windows.net -AsSecureString).Token -AsPlainText)

— Reply to this email directly, view it on GitHub https://github.com/Azure/azure-powershell/issues/25533#issuecomment-2229577613, or unsubscribe https://github.com/notifications/unsubscribe-auth/BF7G77XYYBYYORSFECW5G53ZMRHQRAVCNFSM6AAAAABK3VKADCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMRZGU3TONRRGM . You are receiving this because you were mentioned.Message ID: @.***>