The client I was developing for was using Bicep, however after much trial and error and then internet searching I realised deploying a multi-line secret using Bicep is currently not supported 😒
The options open to us at the time of writing is back to Azure CLI or Azure Powershell: https://github.com/MicrosoftDocs/azure-security-docs/blob/main/articles/key-vault/secrets/multiline-secrets.md
On medium.com this post was found: Uploading Multi-Line Secrets to Azure Key-Vault
Here is my example implementation of adding a SFTP private key (ppk) to a Key Vault secret. The key has to be loaded from file, therefore my private keys are added to the DevOps repos:
1. Add the private keys to the repos
2. Add the private key for specific environment to key vault
parameters: - name: azureServiceConnection type: string - name: resourceGroupName type: string - name: keyVaultName type: string - name: secretName type: string steps: - task: AzureCLI@2 name: AddMulitlineSecret displayName: 'Create $(keyVaultPrefix) Secret : ${{ parameters.secretName }}' inputs: azureSubscription: ${{ parameters.azureServiceConnection }} scriptType: bash scriptLocation: inlineScript inlineScript: | # Variables TAGS="ApplicationName=$(projectName) Environment=$(environment) System=AIS" az keyvault secret set \ --vault-name "${{ parameters.keyVaultName }}" \ --name "${{ parameters.secretName }}" \ --file "$(Pipeline.Workspace)/sourceArtifact/resources/keyvaults/resources/Example_$(environment).ppk" \ --tags $TAGS \ --content-type "text/plain"
However
Ideally I would have liked to have deployed by adding the key to a DevOps Library variable and pulled it in from there, but this is not supported as I write this:
1. Format private key
In Notepad++, Copy/Replace the end of lines with /n
2. Create a DevOps library variable for the private key, and copy in the Copy/Replaced private key now with /n characters i.e. flattened
3. Import into pipeline variables
4. Deploy the multi line private key, yaml > yaml > bicep
a. Deploy secrets yaml
parameters: - name: azureServiceConnection type: string steps: - template: ../keyvaults/cli/keyvault.AddSecret.yaml parameters: azureServiceConnection: ${{ parameters.azureServiceConnection }} resourceGroupName: '$(coreResourceGroupName)' keyVaultName: '$(coreKeyvaultName)' secretName: 'ExampleSFTPPrivateKey' secretValue: '$(exampleSFTPPrivateKey)'
b. Call bicep
parameters: - name: azureServiceConnection type: string - name: resourceGroupName type: string - name: keyVaultName type: string - name: secretName type: string - name: secretValue type: string steps: - task: AzureCLI@2 displayName: 'Create $(keyVaultPrefix) Secret : ${{ parameters.secretName }}' inputs: azureSubscription: ${{ parameters.azureServiceConnection }} scriptType: bash scriptLocation: inlineScript inlineScript: | az deployment group create \ --resource-group '${{ parameters.resourceGroupName }}' \ --name 'iac.${{ parameters.keyVaultName }}' \ --template-file '../sourceArtifact/resources/keyvaults/cli/keyvault.AddSecret.bicep' \ --parameters 'keyVaultName=${{ parameters.keyVaultName }}' \ --parameters 'secretName=${{ parameters.secretName }}' \ --parameters 'secretValue=${{ parameters.secretValue }}' \ --parameters "tags={'ApplicationName' : '$(projectName)', 'Environment' : '$(environment)', 'System' : 'AIS'}"
c. Add secret bicep
@description('The name of this Key Vault.') @minLength(3) @maxLength(24) param keyVaultName string @description('The name of the secret') param secretName string @description('The value of the secret') @secure() param secretValue string @description('The tags of this resource.') param tags object resource keyVaultNameResource 'Microsoft.KeyVault/Vaults@2021-11-01-preview' existing = { name: keyVaultName } resource secretResource 'Microsoft.KeyVault/vaults/secrets@2022-07-01' = { name: secretName tags: tags parent: keyVaultNameResource properties: { contentType: 'text/plain' attributes: { enabled: true } value: secretValue } }