I have a script executed as bicep DeploymentScript in Azure DevOps. It executes Azure SQL Server commands and has worked up until the breaking changes made by Microsoft 5th June this year.
TLDR: The scripts below use the new MS Graph syntax for the June 5th breaking changes.
(Get-AzAccessToken -ResourceTypeName MSGraph).Token
?Invoke-Sqlcmd
and returning the token from the bicep DeploymentScript?NOTE: I've tried both $token
and $secureToken
and neither worked.
The DeploymentScript commands is:
resource identity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' existing = {
name: sqlAdminUmiName
}
var sqlServerHostname = environment().suffixes.sqlServerHostname
var tokenResourceUrl = 'https://${substring(sqlServerHostname, 1)}'
resource deploymentScriptServerGroupAssignment 'Microsoft.Resources/deploymentScripts@2020-10-01' = {
name: name
location: location
kind: 'AzurePowerShell'
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${identity.id}': {}
}
}
properties: {
azPowerShellVersion: '8.3'
arguments: '-dbHost "${dbHost}" -tokenResourceUrl "${tokenResourceUrl}" -dbName "${dbName}" -fxaName "${fxaName}" '
scriptContent: '''
param(
[string] $dbHost,
[string] $tokenResourceUrl,
[string] $dbName,
[string] $fxaName,
[string] $dbRoleNames
)
echo "Step 0: about to Install-Module Microsoft.Graph -Force"
Install-Module -Name SqlServer -Force
Import-Module -Name SqlServer
$token = (Get-AzAccessToken -ResourceTypeName MSGraph).Token
echo "Step 1: token - $token"
$secureToken = ConvertTo-SecureString $token -AsPlainText -Force
echo "Step 2: secureToken - $secureToken"
$query = @()
$query += "DROP USER IF EXISTS `"$fxaName`""
$query += "CREATE USER `"$fxaName`" FROM external provider"
$query += "ALTER ROLE db_owner ADD MEMBER `"$fxaName`""
$query += "ALTER ROLE db_datareader ADD MEMBER `"$fxaName`""
$query += "ALTER ROLE db_datawriter ADD MEMBER `"$fxaName`""
$query += "ALTER ROLE db_ddladmin ADD MEMBER `"$fxaName`""
$query = $query -join ";"
Invoke-Sqlcmd -ServerInstance $dbHost -Database $dbName -AccessToken "$secureToken" -Query $query
'''
retentionInterval: 'PT1H'
cleanupPreference: 'OnSuccess'
forceUpdateTag: currentTime
}
}
The Error in the Deployment plan in Azure portal is:
Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user '<token-identified principal>'.
and
Microsoft.SqlTools.ServiceLayer.BatchParser.BatchParserException: Incorrect syntax was encountered while parsing
I asked a similar question this week for PowerShell execution and the recent MS Graph breaking changes per here
The both the older version of my code with the breaking change, and the syntax that worked for the previous question both still given the same errors. For reference, the new syntax I'm using is:
$token = (Get-AzAccessToken -ResourceTypeName MSGraph).Token
I have another script which has the same line and is not working (same type of Bicep DeploymentScript wrapper as the one above - sub snippet for conciseness):
$token = (Get-AzAccessToken -ResourceTypeName MSGraph).Token
echo "Step 1: token - $token"
$secureToken = ConvertTo-SecureString $token -AsPlainText -Force
echo "Step 2: secureToken - $secureToken"
Write-Host "##vso[task.setvariable variable=dbToken;isOutput=true]$secureToken"
$DeploymentScriptOutputs = @{}
$DeploymentScriptOutputs['dbAccess'] = $secureToken
It returns the error:
The template output 'dbToken' is not valid: The provided value for the template output 'dbToken' is not valid. Expected a value of type 'String, Uri', but received a value of type 'Object'.
I found a very helpful article that discusses the inability of Invoke-SqlCmd
to accept a SecureString
object.
https://github.com/Azure/azure-powershell/issues/25533
One contributor (dadthiele) share the magic code that solves the question about returned object error not being a string (half points to me!):
$accessToken = (ConvertFrom-SecureString $token -AsPlainText)
Note the Convert**From**SecureString
instead of Convert**To**SecureString
However, this still does not solve the error on authenticating to Invoke-SqlCmd
.
Microsoft.Data.SqlClient.SqlException (0x80131904): Login failed for user ''.
To solve that I read the full article and there was the answer already in the above post.
Instead of getting the token with:
$token = (Get-AzAccessToken -ResourceTypeName MSGraph).Token
it needed this:
$token = (Get-AzAccessToken -ResourceUrl https://database.windows.net -AsSecureString).Token