Rinor Maloku

Hide sensitive data in ACS-Engine templates

Posts are in reverse order. The solution at the top. Introduction at the bottom 😉

Problem

ACS-Engine generates ARM Templates for setting up docker enabled clusters. Those ARM Templates contain sensitive information which can be abused when ending up in the wrong hands.

Solution

The Azure service **KeyVault **can be used to save the sensitive information and reference them from the template. The references would be useful to the Azure Resource Manager though wouldn’t provide the privileges for any other user to gain the information.

Storing the data in the KeyVault

Follow script to:

  1. Create a KeyVault.
  2. Store Password and Certificates in the KeyVault.

 

# Create KeyVault to store the secrets
$kv_name = 'kvnamecv1'
$keyvault_rg = 'keyvaultrg1'
$keyvault_rg_location = 'westeurope'

az group create --name $keyvault_rg --location $keyvault_rg_location
az keyvault create --name $kv_name --resource-group $keyvault_rg --enabled-for-template-deployment --enabled-for-deployment
###END

# Save Service Principal password 
$sp_pass_secret_name = 'sppasswordsecret'     # Any name works
$sp_pass = 'Client Secret'
az keyvault secret set -n $sp_pass_secret_name --vault-name $kv_name --description sp_password_secret --value $sp_pass 

# Push the certificates to the KeyVault (Be sure to be in the right folder _output/[dnsprefix])
az keyvault secret set --vault-name $kv_name --name ca-crt --value "$([Convert]::ToBase64String((Get-content -path .\ca.crt -Encoding byte)))"
az keyvault secret set --vault-name $kv_name --name ca-key --value "$([Convert]::ToBase64String((Get-content -path .\ca.key -Encoding byte)))"
az keyvault secret set --vault-name $kv_name --name kubernetes-api-crt --value "$([Convert]::ToBase64String((Get-content -path .\apiserver.crt -Encoding byte)))"
az keyvault secret set --vault-name $kv_name --name kubernetes-api-key --value "$([Convert]::ToBase64String((Get-content -path .\apiserver.key -Encoding byte)))"
az keyvault secret set --vault-name $kv_name --name kubernetes-client-crt --value "$([Convert]::ToBase64String((Get-content -path .\client.crt -Encoding byte)))"
az keyvault secret set --vault-name $kv_name --name kubernetes-client-key --value "$([Convert]::ToBase64String((Get-content -path .\client.key -Encoding byte)))"
az keyvault secret set --vault-name $kv_name --name kubeconfig-crt --value "$([Convert]::ToBase64String((Get-content -path .\kubectlClient.crt -Encoding byte)))"
az keyvault secret set --vault-name $kv_name --name kubeconfig-key --value "$([Convert]::ToBase64String((Get-content -path .\kubectlClient.key -Encoding byte)))"

Updating ARM Template to reference keyvault secrets

Follow instructions on the script.

# Update for e.g. caCertificate from
"caCertificate": {
    "value": "[CERTIFICATE THAT CAN BE SEEN]"
},
# to
"caCertificate": {
    "reference": {
        "keyVault": {
            "id": "[KEY_VAULT_ID]"
        },
        "secretName": "[SECRET_NAME]"
    }
},
# Do so for all values on the table

#    VALUES TO UPDATE     |         SECRET_NAME  
#-----------------------------------------------------
# caCertificate           | ca-crt
# caPrivateKey            | ca-key
# apiServerCertificate    | kubernetes-api-crt
# apiServerPrivateKey     | kubernetes-api-key
# clientCertificate       | kubernetes-client-crt
# clientPrivateKey        | kubernetes-client-key
# kubeConfigCertificate   | kubeconfig-crt
# kubeConfigPrivateKey    | kubeconfig-key

After updating all fields your azuredeploy.parameters.json should go from:

The differences can best be seen using a diff tool. [How to in VS Code]

Introduction to ARM

ARM Templates provide a simple solution to regenerate a whole infrastructure on the Azure Cloud. For a company, this means that they have an automatable, quickly reproducible infrastructures, that will work each time. ✌

Though that said, we need to keep in mind that the ARM Templates will require sensitive data like certificates, azure active directory creds (clientID, clientSecret) and other information needed for the infrastructure setup. To solve this problem Azure provides the KeyVault service, in which you can store the sensitive data and refer them from the ARM Templates.

Sensitive data in ACS Engine generated Templates

The templates generated from acs-engine generate command contain the sensitive information listed below:

  • secret
  • caCertificate
  • caPrivateKey
  • apiServerCertificate
  • apiServerPrivateKey
  • clientCertificate
  • clientPrivateKey
  • kubeConfigCertificate
  • kubeConfigPrivateKey

These data will be present in the file azuredeploy.parameters.json. The certificates and keys will be generated in the same folder.

To securely store the azuredeploy.parameters.json file in a repository we need to store this information in the KeyVault and refer them from the templates.