The repository demonstrates simple usage of Terraform to configure an Azure infrastructure to store and use Packer images, and Packer templates to generate images to store in the Storage Account created in Azure.
You will need an Azure Service Principal Account. See Authorizing Packer Builds in Azure.
Variable | Required | Default | Description |
---|---|---|---|
azure_client_id |
Yes | Azure Client ID, Azure portal shows this as the Application ID. | |
azure_client_secret |
Yes | Service principal secret / password. Found in Keys from the Settings menu. | |
azure_subscription_id |
Yes | UUID identifying your Azure subscription. | |
azure_tenant_id |
Yes | Tenant ID found in the application configure parameters, authorization endpoint ID | |
azure_object_id |
Yes | Specify an OAuth Object ID to protect WinRM certificates created at runtime. | |
resourceGroupName |
Yes | name of the resource group where your VHD(s) will be stored. | |
location |
No | southcentralus |
Primary location for the resource group and storage account. |
storageAccountPrefix |
No | packerimages |
Prefix used for the storage account name where your VHDs will be stored. |
storageAccountType |
No | Standard_GRS |
Standard_LRS``Standard_GRS``Standard_RAGRS``Standard_ZRS``Premium_LRS |
These variables are expected to be defined as environment variables, which are prefixed with TF_VAR_
. If using with Jenkins, these can be defined as parameters and the azure connection information (first 4 variables above) defined as password parameters to mask them.
See Notes (below) for obtaining the subscription and tenant IDs through the Azure CLI
Variable | Required | Default / Source |
---|---|---|
azure_subscription_id |
Yes | env var: TF_VAR_azure_subscription_id |
azure_client_id |
Yes | env var: TF_VAR_azure_client_id |
azure_client_secret |
Yes | env var: TF_VAR_azure_client_secret |
azure_object_id |
Yes | env var: azure_object_id |
resource_group_name |
Yes | env var: TF_VAR_resourceGroupName |
location |
Yes | env var: TF_VAR_location |
storage_account |
Yes | env var: storageAccountName |
container_name |
No | packer-images |
capture_name_prefix |
No | packer |
vm_size |
No | Standard_DS1_V2 |
image_publisher |
No | MicrosoftWindowsServer |
image_offer |
No | WindowsServer |
image_sku |
No | 2016-Datacenter |
winrm_username |
No | Administrator |
# Mask these first 5 parameters...
export TF_VAR_azure_client_id=.....
export TF_VAR_azure_client_secret=.....
export TF_VAR_azure_subscription_id=.....
export TF_VAR_azure_tenant_id=.....
export azure_object_id=.....
export TF_VAR_resourceGroupName="packerimages"
export TF_VAR_location="westus"
export TF_VAR_storageAccountPrefix="images"
export captureContainerName="custom-images"
Validate and apply terraform plan.
terraform plan
terraform apply
Validate packer template and apply using storage account name from Terraform tfstate:
Packer will take variables assigned previously as environment variables.
# Inspect
packer inspect packer_windows.json
# Set storage account name as environment variable
export storageAccountName=$(terraform output storage_account_name)
# Validate
packer validate packer_windows.json
# Build
packer build packer_windows.json
Variables can be overwritten with -var 'key=value'
arguments.
Variables for Packer can also be set from an external JSON file. The -var-file flag reads a file containing a basic key/value mapping of variables to values and sets those variables. The JSON file is simple:
{
"azure_subscription_id": "xxxxx-xxxxx-xxxxxx-xxxxxx",
"azure_client_id": "xxxxx-xxxxx-xxxxxx-xxxxxx",
"azure_client_secret": "xxxxx-xxxxx-xxxxxx-xxxxxx",
"azure_object_id": "xxxxx-xxxxx-xxxxxx-xxxxxx",
"azure_tenant_id": "xxxxx-xxxxx-xxxxxx-xxxxxx",
"resource_group_name": "MyResourceGroup",
"location": "westus",
"container_name": "packer-images",
"capture_name_prefix": "packer",
"vm_size": "Standard_DS1_V2",
"image_publisher": "MicrosoftWindowsServer",
"image_offer": "WindowsServer",
"image_sku": "2016-Datacenter",
"winrm_username": "Administrator"
}
It is a single JSON object where the keys are variables and the values are the variable values. Assuming this file is in variables.json, we can build our template using the following command:
# Set storage account name as variable
storageAccountName=$(terraform output storage_account_name)
packer validate \
-var-file=variables.json \
-var storage_account=$storageAccountName \
packer_windows.json
packer build \
-var-file=variables.json \
-var storage_account=$storageAccountName \
packer_windows.json
The Subscription ID, Object ID, and Tenant ID can be obtained by using the azure cli. Ensure you're logged in by using azure login
and following instructions.
$ azure account show
info: Executing command account show
data: Name : <Your Subscription Name>
data: ID : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
data: State : Enabled
data: Tenant ID : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
data: Is Default : true
data: Environment : AzureCloud
data: Has Certificate : Yes
data: Has Access Token : Yes
data: User name : myemail@domain.com
data:
info: account show command OK
To obtain the object_id
required by Packer:
$ azure ad sp show -n CLIENT_ID