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
}
}







