Continuing the Azure Image Builder Series, we take a closer look at performing image network security customizations using an externally hosted Shell script, enforcing a password policy, installing a specific docker version and finally deploying the image to a Azure Shared Images Gallery.

This is a multi part series for Azure Image Builder with the following articles:

Table of Contents

  1. Introduction
  2. Azure Shared Image Gallery
  3. Preparing permissions
  4. Create the template
  5. Building the image
  6. Summary

Introduction

As mentioned in the first post of this series we will take a real-world scenario where we will perform basic security and service configurations on a CentOS 7.8 image. You can take this example and modify it, to fit your specific needs. Although taken from a real-world scenario, the customizations made in this blog post are straight forward to help you to get started with Azure Image Builder, especially if you are new to VM image customization.

The scenario were covering comprises the need for developers to easily deploy their own docker hosts since company policy forbids to run docker locally. Company policy also dictates the security configurations that have to be performed.
To ensure the developers easily can deploy a docker enabled virtual machine, which also allignes to company standards, we will provide them with customized VM images using the Azure Shared Image Gallery.

Azure Shared Image Galleries have been introduced by Microsoft to provide Azure customers with the possibility to streamline the custom image provisioning process. The core features comprises the following:

  • Sharing across subscriptions
  • Global replication of images
  • Versioning and grouping of images

In our scenario we use a Azure Shared Image Gallery to provide our developers with a simple way to deploy CentOS pre-configured virtual machines. Although not part of this blog post series, with Azure RBAC and Azure policies its possible to enforce the usage of the Shared Image Galleries for Deployment.

To create a new Azure Shared Image Gallery we need to run the following command(s):

1
2
3
4
rg="aibSeriesRg"
sigName=CentOSGallery

az sig create --resource-group $rg --gallery-name $sigName

After creating the Shared Image Gallery we need to create an image definition which holds the information and requirements for using it. As the name suggests, it basically defines the image we are going to create. We specify the following parameters:

  • Image definition name: The Name for the image definition.
  • Publisher: Usually your Company or Department name.
  • Offer: Name of the offer. Can be freely set, usually points to the operating system.
  • SKU: Stock keeping unit. If youre offering different specializations of your image you use the SKU parameter to separate them.
1
2
3
imgDefName=centosDockerDefault

az sig image-definition create -g $rg --gallery-name $sigName --gallery-image-definition $imgDefName --publisher ITInsights --offer CentOS --sku 7.8-Docker --os-type Linux

The Azure Shared Image Gallery and permissions prepared in this blog post assume everything is created in a single resource group. If you need to use an existing Azure Shared Image Gallery make sure you extend the scope of the Azure role definition to ensure sufficient permissions for your image builder identity that was created in the introductory post.

Preparing permissions

The Azure role definition for our image builder identity has to be updated to enable distributing the image to a shared gallery. Therefore we update our role definition with the following actions:

  • “Microsoft.Compute/galleries/read”
  • “Microsoft.Compute/galleries/images/read”
  • “Microsoft.Compute/galleries/images/versions/read”
  • “Microsoft.Compute/galleries/images/versions/write”

Since we want to update our currently existing role definition we need to get the name of it:

1
2
# Get your role definition name from previous setup 
az role definition list --custom-role-only | grep '"roleName": "Azure Image Builder'

After retrieving the value we need to write it to a variable:

1
2
# Fill in your role definition name
imageRoleDefName="Azure Image Builder Basic Role - 1596638916"

With this step, all prerequisites are met to update the role defintion in Azure. To get a quick look at the role definiton click here. Run the following commands in order to complete the role definition update:

1
2
3
4
5
6
7
8
9
10
11
12
13
# Update the role definition for publishing images to Azure Shared Image gallery
subscriptionId="8ee61158-0fe6-4c8f-8968-a811fa118a76"

# Download updated aib role definition
curl https://gist.githubusercontent.com/rooftop90/de6125995df80745675fbb61e4778f7d/raw/7843fb0857fb81bfee484ebc5a176b126123d40a/aibSigRole.json -o aibSigRole.json

# Apply custom values in the role definition
sed -i -e "s/<subscriptionId>/$subscriptionId/g" aibSigRole.json
sed -i -e "s/<rg>/$rg/g" aibSigRole.json
sed -i -e "s/AIB Custom Role/$imageRoleDefName/g" aibSigRole.json

# Submit the updated role definition to azure
az role definition update --role-definition ./aibSigRole.json

Create the template

The template that has been pre-created for this post can be found here. Since this blog post aims towards highlighting features of Azure Image Builder the operating system configurations made wont be explained in detail. A short summary of the custom CentOS configurations made in this template:

  • Enhance basic network security with kernel settings
  • Enforce a password policy
  • Install and enable a specific docker version

Running the following commands in order creates a local copy of the template on your computer ready for submission to the Azure Image Builder service:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Create new template for deploying image to Shared Image Gallery
subscriptionId="8ee61158-0fe6-4c8f-8968-a811fa118a76"
rg="aibSeriesRg"
identityName=aibSeriesIdentity
imgDefName=centosDockerDefault
sigName=CentOSGallery
location=westeurope
outputName=centosLinuxSigImg

# build image builder uri
imgBuilderUri=/subscriptions/$subscriptionId/resourcegroups/$rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/$identityName

# download pre-configured template
curl https://gist.githubusercontent.com/rooftop90/4da48f8e5c35f6c94e43342e14815afd/raw/910b6e24abf2f87a88a6662c2582e5cab2484746/sigImgLinux.json -o sigImgLinux.json

# replace common values
sed -i -e "s/<subscriptionId>/$subscriptionId/g" sigImgLinux.json
sed -i -e "s/<rg>/$rg/g" sigImgLinux.json
sed -i -e "s/<imgDefName>/$imgDefName/g" sigImgLinux.json
sed -i -e "s/<sigName>/$sigName/g" sigImgLinux.json
sed -i -e "s/<location>/$location/g" sigImgLinux.json
sed -i -e "s/<outputName>/$outputName/g" sigImgLinux.json
sed -i -e "s%<imgBuilderUri>%$imgBuilderUri%g" sigImgLinux.json

There are various ways to apply certain configurations to virtual machines. Find the ones that works best for you. A set of configurations that achieve a common goal are often grouped in scripts and executed together while a single configuration often can be applied using a simple oneliner. In our example we created two Shell scripts and one inline customizer to perform the required configurations. They scripts can be found here:

Take a good look at the template before moving on to the next section. It will help you to understand how Azure Image Builder templates are constructed. Follow this Link to get a detailed description about the sections of a template.

Building the image

With the template created we can submit it to the Azure Image Builder service:

1
az resource create --resource-group $rg --properties @sigImgLinux.json --is-full-object --resource-type Microsoft.VirtualMachineImages/imageTemplates -n cosDockerDefaultSig

and finally, start the image build:

1
az resource invoke-action --resource-group $rg --resource-type  Microsoft.VirtualMachineImages/imageTemplates -n cosDockerDefaultSig --action Run

The image build can take up to 20 minutes!

Dont forget, that Azure Image Builder creates a resource group where it stores the template and template-relevant resources. This storage usage occurs small costs so make you delete the resource group if you dont want to persist this data.

Summary

Deploying an image to an Shared Image Gallery is just as easy as deploying as managed image or as vhd. Azure Image Builder in combination with Azure Shared Image Galleries allow Azure customers fine-grained control which images are deployed in their Azure environments and which configurations are made beforehand to support company policies.