Tuesday 5 December 2017

Enhancing Sitecore ARM templates to be production-ready

The Sitecore ARM templates are great for most environments, and better yet they are extensible, however in a production environment you're probably going to need a few more things in your environment; things like staging slots, your own hostname(s), and maybe some storage / networking / traffic manager.

As I mentioned, Sitecore has made the their templates in a fairly modular fashion: you have your base deployment which takes all parameters, and runs a sub-deployment for '-infrastructure' (your Azure resources), '-application' (Sitecore package installation), and a sub-deployment for each Sitecore module.
This gives us the option of just running a separate template after running the base Sitecore templates, or we can integrate our additional deployment as another sub-deployment in the base template in the same way.  Obviously we want to keep our enhancements as separate as possible so that when there is an update to Sitecore or their templates it doesn't mean a massive and painful re-write of our enhancements.

I've uploaded an ARM template as a gist, and included the extra Powershell code below. They do the following:
  • Change your CM + CD hosting plan to Standard
  • Add staging slots to CM + CD
  • Copy files from your CM + CD to the staging slot
  • Add custom hostnames
  • Add an SSL certificate and enable HTTPS for all your hostnames
  • Add connection strings to your Rep / Prc web apps so you can swap them
  • Add custom firewall rules
See the gist of the ARM template which you can run on its own, or as a sub-deployment, in which case you should place this in the "nested" folder, along with the infrastructure.json file. You can then include this into your primary ARM template by duplicating the "-infrastructure" (deployment) resource and changing the name to "-infrastructure-prod" and the reference to this new json file.

You can upload your SSL cert through the ARM template, by providing the binary like in the provided gist; alternatively you can upload the certificate to a key vault (which also creates a secret in the vault). If you choose to use the vault, you must give the ARM deployment service access to your key vault by running the following Powershell command (the service principal ID is an Azure Guid, so the same for everyone):
Set-AzureRmKeyVaultAccessPolicy -VaultName your-keyvault-name -ServicePrincipalName abfa0a7c-a6b6-4736-8310-5855508787cd -PermissionsToSecrets get

You can then substitute the certificate section in the gist with the following, which uses the key vault ID and secret name:
{
  "apiVersion": "[variables('certificateApiVersion')]",
  "location": "[parameters('location')]",
  "name": "[variables('sslCertificateNameTidy')]",
  "type": "Microsoft.Web/certificates",
  "properties": {
    "keyVaultId": "[parameters('keyVaultId')]",
    "keyVaultSecretName": "[parameters('sslKeyVaultCertificateName')]"
  } 
}

In your Powershell script, after the part which does the deployment, add the following to copy the app settings and files to your staging slots:

function copyAppSettings($rg, $webApp, $slot) {
 $props = (Invoke-AzureRmResourceAction -ResourceGroupName $rg `
    -ResourceType Microsoft.Web/sites/Config -Name $webApp/appsettings `
    -Action list -ApiVersion 2015-08-01 -Force).Properties

 $hash = @{}
 $props | Get-Member -MemberType NoteProperty | % { $hash[$_.Name] = $props.($_.Name) }

 Set-AzureRMWebAppSlot -ResourceGroupName $rg -Name $webApp -Slot $slot -AppSettings $hash
}

# Copy app settings to staging slot
Write-Host "Copying app settings to staging slots";
copyAppSettings $ResourceGroupName "$($DeploymentId)-cd" "cd-staging"
copyAppSettings $ResourceGroupName "$($DeploymentId)-cm" "cm-staging"
Write-Host "Done copying app settings";
  
# Copy files to staging slot
Write-Host "Copying files to staging CD";
..\sync_slots -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName -WebAppName "$($DeploymentId)-cd" -SlotName "cd-staging"
Write-Host "Copying files to staging CM";
..\sync_slots -SubscriptionId $SubscriptionId -ResourceGroupName $ResourceGroupName -WebAppName "$($DeploymentId)-cm" -SlotName "cm-staging"
Write-Host "Done copying files to staging";

No comments:

Post a Comment