Validation Key in Azure Chef Extension

Setting the validation key in the Azure Chef Extension

Chef has an extension in Azure that enables the bootstrapping of chef-client onto new or existing machines. This can be done though the Azure portal or using an Azure Resource Manager (ARM) template.

All of the options that the extension supports are documented on the Chef Documentation Website. However, there are often issues with the validation key that can upset the formatting JSON when using an ARM template.

The validation key is set in the protected settings of the resource, e.g.:

 {
   "name": "[concat(parameters('vmName'),'/ChefExtension')]",
   "type": "Microsoft.Compute/virtualMachines/extensions",
   "location": "[resourceGroup().location]",
   "apiVersion": "2015-06-15",
   "properties": {
   "publisher": "Chef.Bootstrap.WindowsAzure",
   "type": "LinuxChefClient",
   "typeHandlerVersion": "1210.12",
   "settings": {
     "validation_key_format": "base64encoded",
     "bootstrap_options": {
       "chef_node_name": "[parameters('computerName')]",
       "chef_server_url": "[parameters('chefData').serverUrl]",
       "validation_client_name": "[parameters('chefData').validator.name]",
       "node_ssl_verify_mode": "[parameters('chefData').node.sslVerifyMode]",
       "environment": "[parameters('chefData').node.environment]"
     },
     "runlist": "[parameters('chefData').runlist]",
     "client_rb": "[parameters('chefData').node.configuration]",
     "validation_key_format": "base64encoded"
   },
   "protectedSettings": {
     "validation_key": "[parameters('chefData').validator.key]"
   }
 }

NOTE: In the above example the individual settings are defined in a JSON object that is set as a secureObject.

The issue with the formatting is that JSON does not allow carriage returns as a value so they have to be encoded with \n however when dealing with an RSA Private Key this can be daunting and lead to mistakes which means that the JSON is invalid or the key is not written to disk on the node properly.

In the example there is a setting called validation_key_format which can be set to plaintext (default) or base64encoded. It is recommended to use the base64 format as this is one continuous string that can be easily pasted into the template or parameters file. This is also the case when adding the extension to a machine using the portal.

Creating the Base64 encoded key

Creating a base64 encoded string varies on different platforms. The following shows how to do it on Mac OS X, Linux and Windows.

NOTE: The commands used for Mac OS X and Linux are very similar but there are slight variances in the commands on each platform.

Mac OS X

Assuming the validator key is in ~/chef-repo/org-validator.pem the following command will output the encoding to the command line:

 cat ~/chef-repo/org-validator | base64

To save time it is possible to get the command to add this to the clipboard so it is easy to paste into the ARM template:

 cat ~/chef-repo/org-validator | base64 | pbcopy

Linux

Again the validator key is assumed to be in ~/chef-repo/org-validator.pem:

 cat ~/chef-repo/org-validator | base64 -w 0

The base64 command is different here because by default it will add line breaks to the output but this is what is being avoided. To make it output as one string the wrap parameter is set to 0.

NOTE: There is no default program in Linux that would copy this to the clipboard.

Windows

There are two methods to generating the encoded format on Windows. The first depends on having chefdk installed the second is a pure PowerShell version.

As before the key is in ~/chef-repo/org-validator.pem.

NOTE: PowerShell understands the ~ as the home directory as well as being able to use the / as a directory separator.

Method 1 – Using Chef DK

The following uses an mixture of PowerShell and the commands in ChefDK to get the base64 encoded version of the key into the clipboard:

 chef exec cat ~/chef-repo/org-validator.pem | chef exec base64 -w 0 | Set-Clipboard

In this case the path has to be passed to the cat command as a Unix style path with / as the directory separator. The output of the commands is then piped to Set-Clipboard which adds the encoded key to the clipoard.

Method 2 – Using PowerShell

If ChefDK is not installed then the following can be used to generate the encoded key in PowerShell

 cd chef-repo
 $path = "~/chef-repo/org-validation.pem"
 $Text = Get-Content -Path $path -Raw
 $Bytes = [System.Text.Encoding]::Unicode.GetBytes($Text)
 [Convert]::ToBase64String($Bytes) | Set-Clipboard

Russell Seymour

I am a Partner Engineer for Chef and much of my focus is on Azure. I have worked with many clients over the years and helped them along their DevOps journey. I started as a support engineer and then found my way into consulting and found my place bridging the gap between Developers and Operations. I enjoy tinkering with computers and drive my family crazy with endless ideas for what a Raspberry PI can be used for.