Skip to main content
The Microsoft 365 provider supports workload identity federation, which allows Kubernetes pods to authenticate to Microsoft 365 services without storing client secrets. This provides a more secure approach for containerized applications running in Kubernetes.
Running Terraform in Kubernetes is a specialized use case with specific benefits and challenges. This authentication method is most appropriate for GitOps workflows, internal developer platforms, or custom Kubernetes operators that use Terraform for infrastructure management.

How Workload Identity Works

Workload identity federation creates a trust relationship between:
  1. A Kubernetes service account
  2. A Microsoft Entra ID application
Instead of using long-lived secrets, the Kubernetes service account token is exchanged for an Azure access token through the OIDC protocol.

Benefits

  • Eliminates the need to manage secrets in Kubernetes
  • Reduces the risk of credential leakage
  • Aligns with zero trust security principles

Prerequisites

Use Cases for Terraform in Kubernetes

GitOps Workflows

ArgoCD, Flux, or custom controllers to manage infrastructure

Developer Platforms

Self-service infrastructure provisioning for development teams

CI/CD Pipelines

Running Terraform as Kubernetes jobs in your CI/CD pipeline

Custom Operators

Kubernetes operators that provision resources using Terraform

Setup

1

Create App Registration

# Set variables
TENANT_ID="00000000-0000-0000-0000-000000000000"
APP_NAME="terraform-m365-provider"

# Create app registration
APP_ID=$(az ad app create --display-name $APP_NAME --query appId -o tsv)
APP_OBJECT_ID=$(az ad app show --id $APP_ID --query id -o tsv)

# Create service principal
az ad sp create --id $APP_ID

# Grant API permissions
az ad app permission add \
  --id $APP_ID \
  --api 00000003-0000-0000-c000-000000000000 \
  --api-permissions 9241abd9-d0e6-425a-bd4f-47ba86e767a4=Role

# Grant admin consent
az ad app permission admin-consent --id $APP_ID
2

Configure Kubernetes Service Account

# Create namespace
kubectl create namespace terraform-m365

# Create service account
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: terraform-m365-sa
  namespace: terraform-m365
  annotations:
    azure.workload.identity/client-id: $APP_ID
EOF
3

Configure Federated Identity

# Get Kubernetes OIDC issuer
SERVICE_ACCOUNT_ISSUER="$(kubectl get --raw /.well-known/openid-configuration | jq -r '.issuer')"

# Create federated credential
az ad app federated-credential create \
  --id $APP_OBJECT_ID \
  --parameters "{\"name\":\"kubernetes-federated-credential\",\"issuer\":\"$SERVICE_ACCOUNT_ISSUER\",\"subject\":\"system:serviceaccount:terraform-m365:terraform-m365-sa\",\"audiences\":[\"api://AzureADTokenExchange\"]}"

Running Terraform in Kubernetes

Example Kubernetes Job:
apiVersion: batch/v1
kind: Job
metadata:
  name: terraform-apply
  namespace: terraform-m365
spec:
  template:
    metadata:
      labels:
        azure.workload.identity/use: "true"
    spec:
      serviceAccountName: terraform-m365-sa
      containers:
      - name: terraform
        image: hashicorp/terraform:latest
        command:
        - /bin/sh
        - -c
        - |
          cd /workspace
          terraform init
          terraform apply -auto-approve
        env:
        - name: M365_TENANT_ID
          value: "00000000-0000-0000-0000-000000000000"
        - name: M365_AUTH_METHOD
          value: "workload_identity"
        - name: M365_CLIENT_ID
          value: "00000000-0000-0000-0000-000000000000"
        volumeMounts:
        - name: terraform-code
          mountPath: /workspace
        resources:
          requests:
            cpu: "500m"
            memory: "512Mi"
          limits:
            cpu: "1"
            memory: "1Gi"
      volumes:
      - name: terraform-code
        configMap:
          name: terraform-code
      restartPolicy: Never
  backoffLimit: 2

Provider Configuration

Security Considerations

Security Best Practices
  • The service account token file is automatically mounted in pods
  • Tokens are short-lived and automatically rotated by Kubernetes
  • Configure RBAC to limit which pods can use the service account
  • Configure conditional access policies in Azure
  • Enable audit logging for both Kubernetes and Microsoft Entra ID

Troubleshooting

Ensure the pod has the correct service account and the token file is mounted correctly.
Verify the federated credential is configured correctly with matching issuer and subject.
Ensure you’ve granted admin consent for the required Microsoft Graph permissions.
Verify the OIDC issuer URL in your federated credential matches your Kubernetes cluster’s issuer.
Check that the pod has the azure.workload.identity/use: "true" label.

Build docs developers (and LLMs) love