Create Ubuntu Pro FIPS golden image with Azure Image Builder

This guide will provide instructions for using the Azure Image Builder (AIB) to create an Ubuntu Pro 20.04 FIPS “golden” image in an Azure Compute Gallery, (formerly Shared Image Gallery). In the process, you’ll:

  • Set up an environment with an Azure Compute Gallery (ACG) and the necessary resources to distribute an image from it

  • Create an image definition for Ubuntu Pro 20.04 FIPS

  • Create a build configuration template to add optional applications

  • Create the golden image using the AIB service

  • Create a VM from the golden image in the ACG

Note

We are using a pre-enabled FIPS image, but you can also use the standard Ubuntu Pro if it better suits your needs.

What you’ll need

Create a configuration template

We’ll be using a sample JSON template to configure the image. It can be customised to include build instructions that are specifically needed for your golden image. Download a template:

curl https://pastebin.com/raw/fCkQAgAc -o UbuntuProFips2004SIGTemplate.json

Customise it to use the values set above:

sed -i -e "s/<subscriptionID>/$subscriptionID/g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s/<rgName>/$sigResourceGroup/g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s/<imageDefName>/$imageDefName/g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s/<sharedImageGalName>/$sigName/g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s/<region1>/$location/g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s/<region2>/$additionalregion/g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s/<runOutputName>/$runOutputName/g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s%<imgBuilderId>%$imgBuilderId%g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s/<ProPlanPublisher>/$ProPlanPublisher/g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s/<ProPlanOffer>/$ProPlanOffer/g" UbuntuProFips2004SIGTemplate.json
sed -i -e "s/<ProPlanSku>/$ProPlanSku/g" UbuntuProFips2004SIGTemplate.json

Review the template content

In case you want to change something or add your own actions, some of the following sections might help. The plan details of the VM image being used as a starting point for your golden image are under ‘source’:

"source": {
    "type": "PlatformImage",
        "publisher": "canonical",
        "offer": "0001-com-ubuntu-pro-focal-fips",
        "sku": "pro-fips-20_04-gen2",
        "version": "latest",
"planInfo": {
            "planName": "pro-fips-20_04-gen2",
            "planProduct": "0001-com-ubuntu-pro-focal-fips",
            "planPublisher": "canonical"
        }
},

The customize section allows you to run commands as part of the image building process. The command seen here is used to include a wait until Ubuntu’s ua client is attached to its subscription.

"customize": [
    {
    "type": "Shell",
    "name": "WaitForUAtokenAutoAttach",
    "inline": [
        "sudo ua status --wait"
    ]
},

Within this section you can add your own actions, for say hardening the image or installing specific software.

{
    "type": "Shell",
    "name": "Placeholder for custom commands required in each Ubuntu VM",
    "inline": [
        "echo 'Replace me!'"
    ]
},

The following commands deregister the golden image from Ubuntu Pro and remove the machine-id. This will ensure that VMs generated from the golden image will generate their own unique IDs.

{
    "type": "Shell",
    "name": "DetachUA -- images created from this will auto attach themselves with new credentials",
    "inline": [
        "sudo ua detach --assume-yes && sudo rm -rf /var/log/ubuntu-advantage.log"
    ]
},

{
    "type": "Shell",
    "name": "Replace /etc/machine-id with empty file to ensure UA client does not see clones as duplicates",
    "inline": [
        "sudo rm -f /etc/machine-id && sudo touch /etc/machine-id"
    ]
}

Create the golden image

To create the image in ACG, submit the image configuration to the AIB service:

az resource create \
    --resource-group $sigResourceGroup \
    --subscription $subscriptionID \
    --properties @UbuntuProFips2004SIGTemplate.json \
    --is-full-object \
    --resource-type Microsoft.VirtualMachineImages/imageTemplates \
    -n UbuntuProFips2004SIG01

Accept the legal terms of the image:

az vm image terms accept --plan $ProPlanSku --offer $ProPlanOffer --publisher $ProPlanPublisher --subscription $subscriptionID

Start the image build process:

az resource invoke-action \
    --resource-group $sigResourceGroup \
    --subscription $subscriptionID \
    --resource-type  Microsoft.VirtualMachineImages/imageTemplates \
    -n UbuntuProFips2004SIG01 \
    --action Run

This step can take some time (~25 minutes) as Azure will actually launch a VM and run the steps that you have defined. While you are waiting for the AIB build process to complete, you can view the corresponding logs by going to the storage account inside the resource group created by AIB. (i.e. Go to Azure Portal > Resource groups > IT_ibUbuntuFIPSGalleryRG_*** > Random ID of the storage account > Containers > packerlogs > Random ID of the container > customization.log > Download)

Once the build process is completed, the status will change from “Running” to “Succeeded”, to show something like:

{
    "endTime": "2022-09-10T23:13:25.9008064Z",
    "name": "37962BEF-34DC-45B1-A1C6-E827CE20F89B",
    "startTime": "2022-09-10T22:48:19.7520483Z",
    "status": "Succeeded"
}

Create a VM - using the Portal

To create a VM based on the golden image, in the portal:

  1. Go to Azure services > Virtual Machines > Create > Virtual machine

  2. Open the See all images link located below the Image field drop-down

  3. Select Shared Images from the column on the left

  4. Choose your golden image and it should now be the selected image in the Image field

  5. Complete the remaining fields as per your requirements and select Review + Create

Create a VM - using the CLI

To create a VM from the command line, you’ll need to use all the variables created earlier. If you already have an SSH key use the following commands to launch the VM:

SSHPublicKeyPath=<path to your id_rsa.pub>
az vm create \
    --resource-group $sigResourceGroup \
    --subscription $subscriptionID \
    --name myAibGalleryVM \
    --admin-username aibuser \
    --location $location \
    --image "/subscriptions/$subscriptionID/resourceGroups/$sigResourceGroup/providers/Microsoft.Compute/galleries/$sigName/images/$imageDefName/versions/latest" \
    --ssh-key-values $SSHPublicKeyPath \
    --plan-name $ProPlanSku \
    --plan-product $ProPlanOffer \
    --public-ip-sku Standard \
    --plan-publisher $ProPlanPublisher

Alternatively, if you do not have an SSH key, replace the --ssh-key-values $SSHPublicKeyPath with --generate-ssh-keys as shown below. However this may overwrite the ssh keypair id_rsa and id_rsa.pub located in .ssh in your home directory.

az vm create \
    --resource-group $sigResourceGroup \
    --subscription $subscriptionID \
    --name myAibGalleryVM \
    --admin-username aibuser \
    --location $location \
    --image "/subscriptions/$subscriptionID/resourceGroups/$sigResourceGroup/providers/Microsoft.Compute/galleries/$sigName/images/$imageDefName/versions/latest" \
    --generate-ssh-keys \
    --plan-name $ProPlanSku \
    --plan-product $ProPlanOffer \
    --public-ip-sku Standard \
    --plan-publisher $ProPlanPublisher

Once the command completes, you should see something like:

{
    "fqdns": "",
    "id": "/subscriptions/50a71625-6dba-43a2-87ad-9eb26e52c9c4/resourceGroups/ibUbuntuFIPSGalleryRG/providers/Microsoft.Compute/virtualMachines/myAibGalleryVM",
    "identity": {
        "principalId": "632b1fc9-9d93-46da-bbd1-3b32e85f96eb",
        "tenantId": "40a524d9-f848-46d4-a96f-be6df491fe15",
        "type": "SystemAssigned",
        "userAssignedIdentities": null
    },
    "location": "westus2",
    "macAddress": "00-0D-3A-F5-29-B8",
    "powerState": "VM running",
    "privateIpAddress": "10.0.0.4",
    "publicIpAddress": "51.143.126.x",
    "resourceGroup": "ibUbuntuFIPSGalleryRG",
    "zones": ""
}

You can use the publicIpAddress (51.143.126.x in this case) to ssh into the machine. To check that the VM is attached to an Ubuntu Pro subscription and is running a FIPS kernel, run:

sudo ua status --wait

Post creation cleanup

You now have an Azure Compute Gallery with an Ubuntu Pro 20.04 FIPS image inside. You have also launched and tested a VM based on this golden image. So you can go ahead with the deletion of the resource groups that were created. You should be able to see the created resource groups with:

az group list --query [].name --output table --subscription $subscriptionID | grep $sigResourceGroup

This command returns something like:

ibUbuntuFIPSGalleryRG
IT_ibUbuntuFIPSGalleryRG_UbuntuProFips2004S_02ecb26b-21f4-4450-b207-e86c7fd6853e

If you want to delete these resource groups, use the following command on each of them. You may find that deleting the first one automatically deletes the second.

az group delete --name [the name from above] --subscription $subscriptionID