How to Create a hardened Ubuntu Pro 20.04 LTS shared image with Azure Image Builder
Setup your Shared Image Gallery
We will be using some pieces of information repeatedly, so we will create some variables to store that information. Then we will create the identity, image definition and gallery that we will need for the image.
Set variables for use throughout the tutorial
We will create the resource group below, so the name should be one you are not already using. We will delete the resource groups that we have created at the end of the tutorial.
# Resource group name - we are using ibUbuntuProGalleryRG in this example
sigResourceGroup=ibUbuntuProGalleryRG
# Datacenter location - we are using North Europe in this example
location=northeurope
# Additional region to replicate the image to - we are using West Europe in this
example
additionalregion=westeurope
Now we will set variables for the Gallery Name and Image Definition Name. The image will be displayed in the Azure Portal as sigName/imageDefName
.
# name of the shared image gallery - in this example we are using myGallery
sigName=myUbuntuProGallery
# name of the image definition to be created
imageDefName=UbuntuPro1804CIS
# image distribution metadata reference name
runOutputName=aibLinuxSIG
Create a variable for your subscription ID. If you only have one, this will be the output of:
az account show -o json | grep id
If you have more than one, you can use
az account list -o table
and take the value from the SubscriptionId
column for the subscription you would like to use
for this tutorial.
Then set this to the variable as follows:
subscriptionID=<Subscription ID>
Now we are going to set variables for the Ubuntu Pro
plan we are going to use in the tutorial. If you have an Ubuntu Pro
private offer with Canonical, for example including 24x7 Technical
Support with SLAs, you will have a custom Offer
and Sku
we can enter these here instead. If not, we will use the plan name and
product for the public Ubuntu Pro from the Azure Marketplace.
# ProPlanPublisher the 'Publisher' field for the Marketplace VM Offer we
want to start from
ProPlanPublisher=canonical
# ProPlanOffer the 'Offer' field for the Marketplace VM Offer we want to
start from
ProPlanOffer=0001-com-ubuntu-pro-bionic
# ProPlanSku the 'Sku' field for the Marketplace VM Offer we want to start from
ProPlanSku=pro-18_04-lts
Create required resources, identities and permissions
Create the resource group:
az group create -n $sigResourceGroup -l $location --subscription $subscriptionID
Image Builder will use the user-identity provided to inject the image into the Azure Shared Image Gallery (SIG). In this example, you will create an Azure role definition that has the granular actions to perform distributing the image to the SIG. The role definition will then be assigned to the user-identity.
# create user assigned identity for image builder to access the storage account
where the script is located
identityName=aibBuiUserId$(date +'%s')
az identity create -g $sigResourceGroup -n $identityName --
subscription $subscriptionID
# get identity id
imgBuilderCliId=$(az identity show -g $sigResourceGroup -n
$identityName --subscription $subscriptionID -o json | grep
"clientId" | cut -c16- | tr -d '",')
# get the user identity URI, needed for the template
imgBuilderId=/subscriptions/$subscriptionID/resourcegroups/
$sigResourceGroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/
$identityName
# this command will download an Azure role definition template,
and update the template with the parameters specified earlier.
curl https://raw.githubusercontent.com/Azure/azvmimagebuilder/master/solutions
/12_Creating_AIB_Security_Roles/aibRoleImageCreation.json -o
aibRoleImageCreation.json
imageRoleDefName="Azure Image Builder Image Def"$(date +'%s')
# update the definition
sed -i -e "s/<subscriptionID>/$subscriptionID/g" aibRoleImageCreation.json
sed -i -e "s/<rgName>/$sigResourceGroup/g" aibRoleImageCreation.json
sed -i -e "s/Azure Image Builder Service Image Creation Role/$imageRoleDefName
/g" aibRoleImageCreation.json
# create role definitions
az role definition create --role-definition ./aibRoleImageCreation.json
# need to wait a bit here
sleep 45
# grant role definition to the user assigned identity
# If this gives an error, wait a bit longer and try again
az role assignment create \
--assignee $imgBuilderCliId \
--role "$imageRoleDefName" \
--scope /subscriptions/$subscriptionID/resourceGroups/$sigResourceGroup
Create an image definition and gallery
To use Image Builder with a shared image gallery, you need to have an existing image gallery and image definition. Image Builder will not create the image gallery and image definition for you.
We will start by creating a gallery and image definition. First, we will create the Gallery:
az sig create \
-g $sigResourceGroup \
--gallery-name $sigName \
--subscription $subscriptionID
Then, create an image definition. This uses the variables we set earlier.
az sig image-definition create \
-g $sigResourceGroup \
--gallery-name $sigName \
--gallery-image-definition $imageDefName \
--publisher $ProPlanPublisher \
--offer $ProPlanOffer \
--sku $ProPlanSku \
--os-type Linux \
--plan-name $ProPlanSku \
--plan-product $ProPlanOffer \
--plan-publisher $ProPlanPublisher \
--subscription $subscriptionID
Customise a template for our deployment
Now we are going to create a template that contains the build instructions for the standard, “golden” image we want to create.
We can download a starting point for this from here
wget https://gist.githubusercontent.com/Hooloovoo/3e544681a12121a36b5dbda684465b8d/
raw/85a7c4461e704b722b901ffc981e23db9a14ce82/BasicCISUbuntuPro1804SIGTemplate.json
Then we can customise it to use the values we have set above. The sed
commands below simply replace the <variable>
placeholders in BasicCISUbuntuPro1804SIGTemplate.json
with the values for the parameters that we set earlier:
sed -i -e "s/<subscriptionID>/$subscriptionID/g"
BasicCISUbuntuPro1804SIGTemplate.json
sed -i -e "s/<rgName>/$sigResourceGroup/g" BasicCISUbuntuPro1804SIGTemplate.json
sed -i -e "s/<imageDefName>/$imageDefName/g" BasicCISUbuntuPro1804SIGTemplate.json
sed -i -e "s/<sharedImageGalName>/$sigName/g" BasicCISUbuntuPro1804SIGTemplate.json
sed -i -e "s/<region1>/$location/g" BasicCISUbuntuPro1804SIGTemplate.json
sed -i -e "s/<region2>/$additionalregion/g" BasicCISUbuntuPro1804SIGTemplate.json
sed -i -e "s/<runOutputName>/$runOutputName/g"
BasicCISUbuntuPro1804SIGTemplate.json
sed -i -e "s%<imgBuilderId>%$imgBuilderId%g" BasicCISUbuntuPro1804SIGTemplate.json
sed -i -e "s/<ProPlanPublisher>/$ProPlanPublisher/g"
BasicCISUbuntuPro1804SIGTemplate
.json
sed -i -e "s/<ProPlanOffer>/$ProPlanOffer/g" BasicCISUbuntuPro1804SIGTemplate.json
sed -i -e "s/<ProPlanSku>/$ProPlanSku/g" BasicCISUbuntuPro1804SIGTemplate.json