Requires jo
sudo apt update && sudo apt install jo -y
https:/github.com/richenmey/terraform-cloud-example
Terraform Cloud https://app.terraform.io/session
Create an organization (azurecitadel)
Structure
- Terraform Cloud
- Organisation
- Projects (Default Project)
- Workspaces
terraform login
Follow the prompts.
Screenshot.
az ad sp create-for-rbac --name "terraform-cloud" --role Contributor --scope "/subscriptions/$(az account show --query id -otsv)"
Save the output.
audience api://AzureADTokenExchange
hostname app.terraform.io
issuer https://app.terraform.io
organization azurecitadel
project "Default Project"
workspace terraform-cloud-example
appId az ad sp list --filter "displayname eq 'terraform-cloud'" --query [0].appId -otsv
object-id az ad sp list --filter "displayname eq 'terraform-cloud'" --query [0].id -otsv
display_name terraform-cloud-example-plan terraform-cloud-example-apply
subject "organization:${organization}:project:${project}:workspace:${workspace}:run_phase:plan" "organization:${organization}:project:${project}:workspace:${workspace}:run_phase:apply"
e.g.
"organization:azurecitadel:project:Default Project:workspace:terraform-cloud-example:run_phase:plan" "organization:azurecitadel:project:Default Project:workspace:terraform-cloud-example:run_phase:apply"
Need both for the plan and apply steps, in cse you want to use different service principals with different roles.
organization="azurecitadel"
project="Default Project"
workspace="terraform-cloud-example"
desc="Terraform Cloud to Azure"
subid="organization:${organization}:project:${project}:workspace:${workspace}"
iss="https://app.terraform.io"
aud="api://AzureADTokenExchange"
appObjectId=$(az ad sp list --filter "displayname eq 'terraform-cloud'" --query [0].id -otsv)
planJson=$(jo name="$workspace-plan"\
issuer=$iss \
subject="$subid:run_phase:plan" \
description="$desc (terraform plan)" \
audiences=$(jo -a $aud))
applyJson=$(jo name="$workspace-apply"\
issuer=$iss \
subject="$subid:run_phase:apply" \
description="$desc (terraform apply)" \
audiences=$(jo -a $aud))
{
"name":"${REPO_NAME}-pull-request",
"issuer":"https://token.actions.githubusercontent.com",
"subject":"repo:${REPO_OWNER}/${REPO_NAME}:refs:refs/heads/main",
"description":"${REPO_OWNER} PR",
"audiences":["api://AzureADTokenExchange"],
}
az rest --method POST \
--uri https://graph.microsoft.com/beta/applications/${APP_OBJ_ID}/federatedIdentityCredentials \
--headers Content-Type='application/json' \
--body @body.json
az rest --method POST \
--uri https://graph.microsoft.com/beta/applications/${APP_OBJ_ID}/federatedIdentityCredentials \
--headers Content-Type='application/json' \
--body @body.json
Organization Settings | Variable sets
Apply to all workspaces (can be more selective later) Environment variables
appId=$(az ad sp list --filter "displayname eq 'terraform-cloud'" --query [0].appId -otsv)
Variable | Value |
---|---|
TFC_AZURE_PROVIDER_AUTH | true |
TFC_AZURE_RUN_CLIENT_ID | appId |
ARM_TENANT_ID | |
ARM_SUBSCRIPTION_ID | |
ARM_CLIENT_ID | appId |
az account show --query tenantId -otsv az account show --query id -otsv az ad sp list --filter "displayname eq 'terraform-cloud'" --query [0].appId -otsv
terraform-cloud-example (same name for the project)
Add the cloud block in
terraform init
This will initialise for CLI driven runs. There are other
Grab this output again with aha
Initializing Terraform Cloud...
Initializing provider plugins...
- Finding hashicorp/azurerm versions matching "~> 3.45.0"...
- Installing hashicorp/azurerm v3.45.0...
- Installed hashicorp/azurerm v3.45.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
Terraform Cloud has been successfully initialized!
You may now begin working with Terraform Cloud. Try running "terraform plan" to
see any changes that are required for your infrastructure.
If you ever set or change modules or Terraform Settings, run "terraform init"
again to reinitialize your working directory.