You can easily store your environment related secrets in the Azure Pipelines releases as variables and mark them as secrets which will encrypt and hide them. So anyone having access to the release definition would be not able to view them. Most of the times, it suffices as once set, they become encrypted and can not be viewed in text form.
However, sometimes it may happen that the person who keeps the secret would not be the same person as who is creating the release definition. Think of that as a way of segregating the responsibilities between the two. Also, it may be possible that the person who has provisioned the environment is not comfortable to share the secrets with anyone in plain text. After all, the best way to keep a secret is not to tell anyone about it. This is where the Azure Key Vault fits in very nicely. It can be used to store and transfer the secrets/certificates needed for your environment in a secure way.
So, instead of storing secrets in the build and release definitions, we can choose them to store in the Azure Key Vault. Not only this, by storing them in this way, we can use them across multiple definitions.
Create An Azure Resource Group
This is where the things always start in Azure. Every resource must reside in what is known as resource group. Unfortunately, when I was trying to create a resource group using Azure CLI, it kept failing with below error:
Well, you know what they say about regex!! Nonetheless, we will fall back to PowerShell for this task:
New-AzureRMResourceGroup -Name appSecrets-rg -Location eastus
where appSecrets-rg is the name of the resource group and location is East US.
Create a Key Vault
Next we will create a Key Vault in the resource group created in the previous step. For this, we can use below PowerShell command (Azure CLI disappointed again):
New-AzureRmKeyVault -Name app-KeyVault -ResourceGroupName appSecrets-rg -Location eastus
The output of this command will show the properties of the newly created Key Vault. Take note of the two properties listed below:
Vault Name: In the example, this is app-keyvault.
Vault URI: In the example, this is https://app-keyvault.vault.azure.net/.
Applications that need to use this vault must use this URI it.
Add Secrets to Azure Key Vault
Let’s add few secrets to the Azure Key Vault. To add a secret to the vault, which is a password named SqlPass and has the value of Pa$$w0rd to Azure Key Vault, first convert the value of Pa$$w0rd to a secure string by typing:
$secretvalue = ConvertTo-SecureString ‘Pa$$w0rd’ -AsPlainText -Force
$secret = Set-AzureKeyVaultSecret -VaultName app-KeyVault -Name SqlPass -SecretValue $secretvalue
You can now reference this password that you added to Azure Key Vault, by using its URI. Use https://ContosoVault.vault.azure.net/secrets/SqlPass to always get the current version, and use https://app-keyvault.vault.azure.net/secrets/SqlPass/ac6e677dd96844d4b84534ff790a032a to get this specific version.
To display the URI for this secret, type:
$secret.Id
which is how we got the specific URI mentioned above.
View Secrets stored in Azure Key Vault
Now, to view the list of secrets that are stored in the Azure Key Vault, we can type:
Get-AzureKeyVaultSecret –VaultName app-keyvault
To view the value contained in the secret as plain text:
(Get-AzureKeyVaultSecret -VaultName app-KeyVault -Name SqlPass).SecretValueText
Or alternatively you may view the secret on the portal:
Now, our key vault and keys or secrets are ready for applications to use.
Authorize the Azure Pipelines to use the key or secret
Now we need to authorize an app or a client to fetch the secrets. For this, we can use the below command:
Set-AzureRmKeyVaultAccessPolicy -VaultName app-KeyVault -ObjectId 8f8c4bbd-485b-45fd-98f7-ec6300b7b4ed -PermissionsToSecrets get,list
where, -ObjectId is the Id of the Service Principal Client.
For steps to create SPN and link it to Azure Pipelines, read here.
Fetch secrets during build/release definition
For this, we need to add a task for Azure Key Vault:
And provide it will relevant values:
Secrets filter allows you to fetch all secrets using wilcard (*) or a selected few.
Alternatively, you can use below YAML code:
# Azure Key Vault # Download Azure Key Vault Secrets - task: AzureKeyVault@1 inputs: azureSubscription: keyVaultName: #secretsFilter: '*' # Options: editableOptions
You can add other tasks as per the need. For demo purpose, we’ll just leave it alone and run the pipelines. Once we run the pipeline, it will be available as part of the variables.
The secret variables are not decrypted into environment variables, so scripts and programs run by the build steps are not given access by default.
For example: a secret (Name: SqlPass) in Key vault, then you can access the value like $(SqlPass), but can’t access it like $env:SqlPass inside PowerShell task.
The workaround is that you can replace the token value with the value of key vault secret in a file through Token Replace task or other way.
Hi Mohit,
Very informative read!
Can you help me with setting/ updating a secret from yaml (azure pipeline)
LikeLike
Hi Aditya, In YAML code shared, secretsFilter is the list of comma-separated secrets that needs to be fetched. ‘*’ denotes all secrets.
LikeLike
Hi Thanks for the information,My question , i am updating the appsettings.json file in release through JSON variable substitution notes. But i can’t updated the json variable appsetting.connectionstring ,Bcoz keyvault not accepting secret name as “appsetting.connectionstring”,
LikeLike
Hi,
The article is really informative but can you please elaborate a little on tokenreplace? That was exactly what I was looking for and as soon as I started to find the article helpful it ended 😦
Thanks
LikeLike
Dear Mohit,
maybe a bit late, but thanks for this article, it helped me a lot 🙂
LikeLike