I have an Azure Pipeline that needs to invoke a Console application (.exe) which connects to multiple databases to perform EF core migrations. The databases can only be accessed via Azure AD/Entra (i.e. having Authentication=Active Directory Default;
in the connection string)
A service principal exists in Azure AD for the DevOps project, and is configured with the "Contributor" role against the subscription. I'm confident the permissions are correct as I have previously used the SqlAzureDacpacDeployment@1
task against a database with no issue.
The task looks like:
- script: |
cd $(Pipeline.Workspace)/ef-migrator-exe
echo "Connection string: ${{ parameters.masterConnectionString }}"
EfMigrator.exe -c "${{ parameters.masterConnectionString }}"
displayName: 'Execute EF Migrations'
However, when running the .exe from the pipeline I'm getting:
Microsoft.Data.SqlClient.SqlException (0x80131904): DefaultAzureCredential failed to retrieve a token from the included credentials. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/defaultazurecredential/troubleshoot
- EnvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/environmentcredential/troubleshoot
- WorkloadIdentityCredential authentication unavailable. The workload options are not fully configured. See the troubleshooting guide for more information. https://aka.ms/azsdk/net/identity/workloadidentitycredential/troubleshoot
- ManagedIdentityCredential authentication unavailable. The requested identity has not been assigned to this resource.
Status: 400 (Bad Request)
From what I've read, the .exe should inherit the same permissions as the pipeline itself, but it seems like that isn't happening?
I just needed to run the script using the AzureCLI@2 task, specifying the service connection:
- task: AzureCLI@2
inputs:
azureSubscription: '${{ parameters.serviceConnection }}'
scriptType: 'batch'
useGlobalConfig: true
scriptLocation: 'inlineScript'
inlineScript: |
cd $(Pipeline.Workspace)/ef-migrator-exe
EfMigrator.exe -c "${{ parameters.masterConnectionString }}"
This I assume creates a token for the service connection, which is then picked up when connecting to the DB.