Through the Azure Chef VM Extension, you can easily bootstrap the Chef client on to the VM operating system. This allows you to apply Chef-driven configuration management, compliance scanning and automation quickly and easily.
In order to securely authenticate a new node against the Chef server (or hosted Chef), the bootstrap process must use the private key of the organization to which it will be joined. Each Chef organization has a separate private key, which is usually called <ORGNAME>-validator.pem.
Naturally, you don’t want to expose this private key in plain text, so in order to protect the key during the deployment of the Chef VM Extension resource, we can make use of Azure Key Vault. During the deployment of the VM Extension resource, Azure accesses the private key within the Key Vault and passes it (in an encrypted format) as a deployment parameter. The Chef client can then present the key to the Chef server and authenticate successfully.
You can perform these steps using the Azure Portal, but in this scenario I’m using Azure PowerShell.
To create a new Azure Key Vault, authenticate against your Azure Subscription:
## Log in to Azure Resource Manager | |
Add-AzureRmAccount | |
Next, create a a Resource Group which will house the new Key Vault:
## Create Resource Group | |
$resourceGroupName = 'keyvault' | |
$location = 'Australia Southeast' | |
$resourceGroup = New-AzureRmResourceGroup ` | |
-Name $resourceGroupName ` | |
-Location $location -Force | |
$resourceGroup |
Now we can create the Key Vault. Because the name assigned to the resource has to be globally unique, we’ll make use of a function written by Jon Gurgul which takes a string (which in this case will be the resource ID of the Azure Resource Group we just created) and converts it in to a hashed string. We’ll use this hash to generate a unique name for the Key Vault.
## Create Azure KeyVault | |
Function Get-StringHash([String] $String,$HashName = "MD5") | |
{ | |
$StringBuilder = New-Object System.Text.StringBuilder | |
[System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String))|%{ | |
[Void]$StringBuilder.Append($_.ToString("x2")) | |
} | |
$StringBuilder.ToString() | |
} | |
$vaultName = 'myVault' | |
$uniqueString = (Get-StringHash -String $resourceGroup.ResourceId).substring(0,10) | |
$vaultName = $vaultName + $uniqueString | |
$vault = New-AzureRmKeyVault ` | |
-VaultName $vaultName ` | |
-ResourceGroupName $resourceGroup.ResourceGroupName ` | |
-Location $resourceGroup.Location ` | |
-EnabledForTemplateDeployment -Verbose | |
$vault |
Note that we chose to enable this Key Vault for template deployment. This means that an Azure Resource Manager deployment can query the Key Vault.
Next we read the contents of the Chef organization validation certificate (the private key) and convert it to a secure string:
## Get Certificate details | |
$certPath = "$env:USERPROFILE\Documents\git\chef-hosted\.chef" | |
$certName = 'chef-org-validator.pem' | |
$cert = $certPath + '\' + $certName | |
$secretName = 'chef-org-validator' | |
$secretValue = Get-Content $cert -Raw | ConvertTo-SecureString -AsPlainText -Force |
If you built your own instance of Chef Server, then you should have access to the organization validation certificate. If you’re using Hosted Chef (//api.chef.io) then you can access the validation key by resetting it from the management portal: Administration –> Organizations –> Reset Validation Key.
Finally we can create a new secret within the Key Vault using the stored value:
## Create Key Vault secret | |
$vaultSecret = Set-AzureKeyVaultSecret ` | |
-VaultName $vault.VaultName ` | |
-Name $secretName ` | |
-SecretValue $secretValue ` | |
-Verbose | |
$vaultSecret |
We can then call the Key Vault secret during an ARM template deployment in the parameters file (e.g. azuredeploy.parameters.json):
"chefValidationKey": { | |
"reference": { | |
"keyVault": { | |
"id": "/subscriptions/<SUBSCRIPTIONID>/resourceGroups/<RESOURCEGROUPNAME>/providers/Microsoft.KeyVault/vaults/<VAULTNAME>" | |
}, | |
"secretName": "chef-org-validator" | |
} | |
} |
This process works for other, non-Chef certificates as well. All we are doing is reading the private key as a string using PowerShell and storing it as a secure variable, then creating a new Key Vault secret using the encrypted value.
And here’s the entire PowerShell script:
## Log in to Azure Resource Manager | |
Add-AzureRmAccount | |
## Create Resource Group | |
$resourceGroupName = 'keyvault' | |
$location = 'Australia Southeast' | |
$resourceGroup = New-AzureRmResourceGroup ` | |
-Name $resourceGroupName ` | |
-Location $location -Force | |
$resourceGroup | |
## Create Azure KeyVault | |
Function Get-StringHash([String] $String,$HashName = "MD5") | |
{ | |
$StringBuilder = New-Object System.Text.StringBuilder | |
[System.Security.Cryptography.HashAlgorithm]::Create($HashName).ComputeHash([System.Text.Encoding]::UTF8.GetBytes($String))|%{ | |
[Void]$StringBuilder.Append($_.ToString("x2")) | |
} | |
$StringBuilder.ToString() | |
} | |
$vaultName = 'myVault' | |
$uniqueString = (Get-StringHash -String $resourceGroup.ResourceId).substring(0,10) | |
$vaultName = $vaultName + $uniqueString | |
$vault = New-AzureRmKeyVault ` | |
-VaultName $vaultName ` | |
-ResourceGroupName $resourceGroup.ResourceGroupName ` | |
-Location $resourceGroup.Location ` | |
-EnabledForTemplateDeployment -Verbose | |
$vault | |
## Get Certificate details | |
$certPath = "$env:USERPROFILE\Documents\git\chef-hosted\.chef" | |
$certName = 'chef-org-validator.pem' | |
$cert = $certPath + '\' + $certName | |
$secretName = 'chef-org-validator' | |
$secretValue = Get-Content $cert -Raw | ConvertTo-SecureString -AsPlainText -Force | |
## Create Key Vault secret | |
$vaultSecret = Set-AzureKeyVaultSecret ` | |
-VaultName $vault.VaultName ` | |
-Name $secretName ` | |
-SecretValue $secretValue ` | |
-Verbose | |
$vaultSecret |
Started watching your course about automating deployments using ARM at pluralsite
//app.pluralsight.com/player?course=microsoft-azure-resource-manager-mastering&author=james-bannan&name=microsoft-azure-resource-manager-mastering-m2&clip=2&mode=live
Overall very useful, however, the voice appears very unnatural ?
Is it either recorder to save space (bandwidth) where all the times between the words are removed , or is it read by a bot ?