Deploying a Multi-Line Key Vault Secret

Deploying a Multi-Line Key Vault Secret

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
Private keys in 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
SFTP Private Key

In Notepad++, Copy/Replace the end of lines with /n

Copy Replace End Of Line Characters

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
DevOps Library Variables

3. Import into pipeline variables

Yaml pipeline imported 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
  }
}

Leave a Reply

Your email address will not be published. Required fields are marked *