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