I need to use a certificate in a keyvault to sign my DLL after its built.
The cproj
contains the post build task
<Target Name="AzureSignTool" AfterTargets="Build">
<Message Importance="High" Text="Running azuresigntool." />
<Exec Command="azuresigntool sign --azure-key-vault-tenant-id "$(AzureSignTool_TenantId)" -kvu $(AzureSignTool_KeyVaultUrl) -kvi $(AzureSignTool_ClientId) -kvs $(AzureSignTool_ClientSecret) -kvc CodeSigningCert "$(ProjectDir)$(OutDir)$(TargetFileName)"" />
<!-- Parameters provided from pipeline 'library'. -->
</Target>
which is working locally where the parameter values are environment variables.
The next step is to get it to work in the Azure DevOps build pipeline.
The variables are set in a pipeline library and added using
variables:
- group: azuresigntool
Now in the pipeline the azuresigntool
runs with the parameter values but fails because Client address is not authorized and caller is not a trusted service. The solution (from https://luke.geek.nz/azure/accessing-keyvault-azure-devops/) is to add the IP address of the build server to the keyvault's firewall.
This is how far I've got
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'custom'
custom: 'tool'
arguments: 'install --global azuresigntool'
displayName: Install AzureSignTool
# https://luke.geek.nz/azure/accessing-keyvault-azure-devops/
# This task uses Azure CLI to add the IP address of the Azure DevOps agent to the firewall of an Azure Key Vault.
- task: AzureCLI@2
displayName: Add Agent IP From Key Vault
condition: succeededOrFailed() # This task will run regardless of whether previous tasks have succeeded or failed.
inputs:
azureSubscription: 'Libraries-335d6548-abdc-4fd4-b313-e8c7ab8357c6' #${{ parameters.keyVaultArmSvcConnectionName }} # The Azure subscription that the task should use. The value is taken from the keyVaultArmSvcConnectionName parameter.
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
agentIP=$(curl -s https://checkip.amazonaws.com)
echo "Agent IP: $agentIP"
az keyvault network-rule add --name "prestwoodsoftware" --ip-address "$agentIP" --only-show-errors
- template: BuildTestPack.yml@AzurePipelineTemplates
parameters:
solution: 'Libraries.DllThatNeedsToBeSigned.sln'
# This task uses Azure CLI to remove the IP address of the Azure DevOps agent from the firewall of an Azure Key Vault.
- task: AzureCLI@2
displayName: Remove Agent IP From Key Vault
condition: succeededOrFailed()
inputs:
azureSubscription: 'Libraries-335d6548-abdc-4fd4-b313-e8c7ab8357c6' #${{ parameters.keyVaultArmSvcConnectionName }} # The Azure subscription that the task should use. The value is taken from the keyVaultArmSvcConnectionName parameter.
scriptType: bash
scriptLocation: inlineScript
inlineScript: |
agentIP=$(curl -s https://checkip.amazonaws.com)
echo "Agent IP: $agentIP"
az keyvault network-rule remove --name "prestwoodsoftware" --ip-address "$agentIP" --only-show-errors
I think the problem is getting the Azure agent to authorise for az
. How is that supposed to work?
There is no such thing as ${{ parameters.keyVaultArmSvcConnectionName }}
and it's unclear what it's supposed to be. I have tried
In each case the build fails saying
There was a resource authorization issue: "The pipeline is not valid. Job Job: Step AzureCLI1 input connectedServiceNameARM references service connection
whatever-I-put-for-azureSubscription
which could not be found. The service connection does not exist, has been disabled or has not been authorized for use. For authorization details, refer to https://aka.ms/yamlauthz.
Is it possible to run azuresigntool
in an Azure DevOps pipeline? How?
The ${{ parameters.keyVaultArmSvcConnectionName }}
is the Azure Resource Manager type service connection(ARM service connection) in your DevOps project.
If you follow the same format ${{ parameters.XXX}}
, you need to define the service connection name as parameter
at the top of your pipeline YAML.
parameters:
- name: keyVaultArmSvcConnectionName
value:YourARMConnservice # your ARM service connection name.
But you can also directly type the service connection name in yaml AzureCLI task as you do now, which means not using parameter.
The last error indicates the ARM service connection is not created, or you are not authorized to use it.
Please follow below steps:
Go to project settings -> Pipelines -> Service connections, check if the ARM service connection exists, and confirm the name is same within pipeline. Create the connection if it doesn't exist.
If it exists, go to the failed build result, you could see an option to authorize the resources. You can select this option and authorize the resource on the failed build. Once the resource is authorized, you can start a new build. Check the doc for the details.
The two AzureCLi tasks automatically detect the DevOps agent IP and add/remove it to key vault whitelist, ensure agent can access the key vault.
In addition, you are defining secret type variables
in Variable group group: azuresigntool
, please note they are not mapped as environment variables in your pipeline, only non-secret type variables will be automatically mapped as environment. You can consider to use script/powershell task directly with AzureSignTool
command instead of post build task:
- powershell: '& AzureSignTool sign --azure-key-vault-tenant-id $(AzureSignTool_TenantId) -kvu $(AzureSignTool_KeyVaultUrl) -kvi $(AzureSignTool_ClientId) -kvs $(AzureSignTool_ClientSecret) -kvc CodeSigningCert "$(ProjectDir)$(OutDir)$(TargetFileName)'
displayName: 'Sign the file'