Azure workload identity federation with Terraform in GitLab pipelines

Noël Gaß
5 min readMay 8, 2023

This article provides an overview of how to use workload identity federation to deploy Infrastructure as Code (IaC) with Terraform in GitLab pipelines. By utilizing workload identity federation, you can retrieve temporary Azure credentials without the need to store secrets. This approach allows you to deploy infrastructure using Terraform via a service principal and OpenID Connect, providing a more secure and efficient method.

Azure workload identity federation with Terraform in GitLab pipelines.

Table of Contents:

  • Why use workload identity federation?
  • How it works with Terraform in GitLab pipelines
  • Conclusion
  • Limitations
  • References

Why use workload identity federation?

Workloads typically require a set of credentials (identity and secret) for authentication and resource access. These credentials pose a security risk and must be stored securely and rotated regularly. In addition, you also run the risk of service downtime, if the credentials expire.

The workflow for exchanging a GitLab ID token for an access token and accessing Azure AD protected resources:

The workflow for exchanging a GitLab ID token for an access token.

How it works with Terraform in GitLab pipelines

Step 1: Create a service principal and federated identity credential.

To register an application with Azure AD and create a service principal, follow the steps outlined in this Microsoft Learn guide: https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal. This guide provides detailed instructions for those who may not be familiar with the registration process.

After creating the application and service principal, the next step is to assign sufficient RBAC roles, such as ‘Contributor’ and configure federated credentials. To configure the federated credentials in the Azure Portal, follow these steps:

  1. Navigate to the ‘Certificates & secrets’ page for your application registration.
  2. Navigate to the ‘Federated credentials’ tab and click ‘Add credentials’.
  3. Choose the ‘Other issuer’ scenario and enter the required descriptions and configurations below:
  4. ‘Issuer’ (required): Enter the name of the identity provider (e.g. contonso.gitlab.com).
  5. ‘Subject identifier’ (required): Enter the exact subject identifier (e.g. ‘project_path:noel.gass/azure-federation:ref_type:branch:ref:main’).
  6. ‘Name’ (required): Name of the federated credential.
  7. ‘Description’ (optional): Description of the federated credential.
  8. ‘Audience’ (optional): The audience of the accessed resource.
  9. Click ‘Save’ to apply the changes.

Certificates & secrets > Federated credentials

Add federated credentials.

Step 2: Write your Terraform configuration.

The Terraform file ‘main.tf’ provided in the article includes all necessary information for deploying Azure resources, but it may not follow best practices to keep the example simple and easy to understand. The included code demonstrates how to deploy a resource group in Azure.

// provider
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "3.55.0"
}
}
}

provider "azurerm" {
# Configuration options
features {}
}

// locals
locals {
location = "westeurope"
resource_group_name = "rg-federation-dev-weu"
}

// main
resource "azurerm_resource_group" "this" {
location = local.location
name = local.resource_group_name
tags = {
"business_criticality" = "low"
"environment" = "dev"
"owner" = "noel.gass"
}
}

Step 3: Write your GitLab pipeline.

When deploying Terraform configurations to Azure, it is necessary to provide certain variables. These variables can be added to GitLab CI/CD variables for easy management. The required variables include:

  1. ‘ARM_TENANT_ID’ (required): The Tenant ID which should be used.
  2. ‘ARM_SUBSCRIPTION_ID’ (required): The Subscription ID which should be used.
  3. ‘ARM_CLIENT_ID’ (required): The Client ID which should be used.

When using federated identity with Terraform in GitLab pipeline, there are certain variables that must be set via the pipeline. These required variables are:

  1. ‘ARM_USE_OIDC’ (required): Use OpenID Connect. Default is false but needs to be set to true.
  2. ‘ARM_OIDC_TOKEN’ (required): Environment variable as an OIDC token.

The ‘ARM_OIDC_TOKEN’ is set via the ‘id_tokens’ parameter and leverages GitLab ID token authentication. The audience - ‘aud’ - value of the token must match the one configured in the federated identity. Additional information on this topic can be found in the GitLab documentation: https://docs.gitlab.com/ee/ci/secrets/id_token_authentication.html.

To configure the GitLab pipeline for deploying infrastructure with Terraform using workload identity federation, you can use a configuration file similar to the example below, which is defined in ‘.gitlab-ci.yml’.

---

stages:
- validate
- plan
- apply

variables:
TF_STATE: federation-state
ARM_USE_OIDC: "true"

.terraform_init:
id_tokens:
ARM_OIDC_TOKEN:
aud: api://AzureADTokenExchange
image:
name: hashicorp/terraform:1.4.6
entrypoint:
- /usr/bin/env
- "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
before_script:
- terraform init
cache:
key: terraform
paths:
- .terraform

terraform_fmt:
stage: validate
script:
- terraform fmt -list=true -write=false -diff=true -check=true -recursive

terraform_validate:
stage: validate
script:
- terraform validate

terraform_plan:
stage: plan
extends: .terraform_init
script:
- terraform plan --out ${TF_STATE}.json
artifacts:
paths:
- ${TF_STATE}.json

terraform_apply:
stage: apply
extends: .terraform_init
script:
- terraform apply --auto-approve ${TF_STATE}.json
when: manual

Step 4: Deploy and Enjoy!

Conclusion

In conclusion, workload identity federation is a powerful tool that allows for secure and efficient deployment of infrastructure as code with Terraform. By leveraging Azure AD and GitLab pipelines, it is possible to retrieve temporary credentials without the need for secret storage, and deploy infrastructure via a service principal and OpenID Connect. This approach reduces the risk of security breaches and service downtime, while also streamlining the deployment process. By following the steps outlined in this article, users can easily implement workload identity federation in their own workflows and take advantage of its benefits.

Limitations

Adding to the previous conclusion, it is important to note that while workload identity federation is a powerful tool, it may not be the best solution for every situation. The limitations of the federated credential properties, particularly the ‘Subject identifier’ field, can be restrictive in certain scenarios due to the lack of support for wildcard characters. It is important to carefully evaluate the needs of your specific environment and determine if workload identity federation is the best solution for your use case.

Read more: https://learn.microsoft.com/en-us/azure/active-directory/workload-identities/workload-identity-federation-considerations

--

--