We are creating an Azure SQL Server and the database using ARM templates. We have set a AAD group as AAD admin on the SQL Server. That group contains a service principal which we have created under Application registrations.
The deployment succeeds and I can see the AAD admin set correctly for the SQL Server. However when I try to run scripts from the deployment pipeline from that service principal, like create user, it fails.
e.g. this powershell scripts successfully fetches the token and opens the connection, but fails with an error.
$tenant = "xxxx-xxxx-xxxxxx"
$applicationId = $(Get-AzADServicePrincipal -DisplayName "MyServicePrincipal").ApplicationId
$clientSecret = "yyyy-yyyyy-yyyy"
$subscriptionId = "xyxy-xyxy-xyxy-xyxy"
$secstr = New-Object -TypeName System.Security.SecureString
$clientSecret.ToCharArray() | ForEach-Object {$secstr.AppendChar($_)}
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $applicationId, $secstr
Connect-AzAccount -Tenant $tenant -SubscriptionId $subscriptionId -ServicePrincipal -Credential $cred
$resourceAppIdURI = 'https://database.windows.net/'
$authority = ('https://login.windows.net/{0}' -f $tenant)
$ClientCred = [Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential]::new($applicationId, $clientSecret)
$authContext = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext]::new($authority)
$authResult = $authContext.AcquireTokenAsync($resourceAppIdURI, $ClientCred)
$Token = $authResult.Result.AccessToken
$conn = New-Object System.Data.SqlClient.SQLConnection
$SQLServerName = "sql-myApplicationDbServer-dev.database.windows.net"
$DatabaseName = 'sqldb-myApplicationDb-dev'
$conn.ConnectionString = "Data Source=$SQLServerName;Initial Catalog=$DatabaseName;Connect Timeout=30"
$conn.AccessToken = $($Token)
$conn.Open()
$query = @"
IF NOT EXISTS (
SELECT [name]
FROM sys.database_principals
WHERE [name] = 'myAppServiceName'
)
BEGIN
CREATE USER [myAppServiceName] FROM EXTERNAL PROVIDER;
ALTER ROLE db_datareader ADD MEMBER [myAppServiceName];
ALTER ROLE db_datawriter ADD MEMBER [myAppServiceName];
ALTER ROLE db_ddladmin ADD MEMBER [myAppServiceName];
END
"@
$command = $conn.CreateCommand()
$command.CommandText = $query
$result = $command.ExecuteNonQuery()
$result
$conn.Close()
the error
...
PS C:\Users\TJ> $conn.Open()
PS C:\Users\TJ> $command = $conn.CreateCommand()
PS C:\Users\TJ> $command.CommandText = $query
PS C:\Users\TJ> $result = $command.ExecuteNonQuery()
MethodInvocationException: Exception calling "ExecuteNonQuery" with "0" argument(s): "Principal 'myAppServiceName' could not be resolved. Error message: ''
Cannot add the principal 'myAppServiceName', because it does not exist or you do not have permission.
Cannot add the principal 'myAppServiceName', because it does not exist or you do not have permission.
Cannot add the principal 'myAppServiceName', because it does not exist or you do not have permission."
But, if I add my own AAD user in the SQL Server AAD Administrator group, which the Service principal is part of, I can successfully run the script.
I think service principal needs an associated user and proper rights before i run any create user scripts. how to do that from the service principal login(remember its an admin as its a member of the SQL Server AAD admin group). This would be part of a pipeline so I don't want to run any script with manual intervention.