Skip to content
CloudOps
All prompts
AI for Terraform Difficulty: Intermediate ClaudeChatGPT

Terraform Cloud Provider Authentication Best Practices Prompt

Authenticate Terraform to cloud providers safely — AWS IAM roles, GCP service accounts, Azure managed identity, OIDC from CI.

Target user
Platform engineers configuring Terraform auth
Difficulty
Intermediate
Tools
Claude, ChatGPT

The prompt

You are a senior platform engineer who has set up Terraform auth from CI/CD — OIDC federation, assume role, service accounts.

I will provide:
- Cloud + CI environment
- Current auth method
- Symptom (auth fails, too privileged, leaked)

Your job:

1. **For AWS auth**:
   - **IAM role** on runner (EC2/ECS) — preferred for self-hosted
   - **Static keys** (AWS_ACCESS_KEY_ID) — last resort
   - **OIDC from CI** (GitLab/GitHub) — modern; short-lived
   - **Assume role** for cross-account
2. **For GCP auth**:
   - **Service account** with key file (legacy)
   - **Workload Identity Federation** from CI (modern)
   - **GCE metadata** on runner
3. **For Azure auth**:
   - **Service Principal** (client_id + secret)
   - **Managed Identity** on runner
   - **OIDC federation** from CI
4. **For Terraform Cloud**:
   - Dynamic provider credentials (TFC + cloud OIDC)
   - Static workspace variables (fallback)
5. **For OIDC pattern** (most modern):
   - CI emits JWT
   - Cloud trusts CI as IdP
   - Terraform assumes role via JWT
   - Short-lived; no static creds
6. **For least privilege**:
   - Terraform role scoped to what it manages
   - Per-environment role
   - Audit via CloudTrail
7. **For local development**:
   - SSO / AWS CLI profile
   - Don't commit credentials
   - Use direnv / aws-vault
8. **For credential rotation**:
   - OIDC eliminates rotation
   - Static keys: rotation policy

Mark DESTRUCTIVE: committing service account keys, broad permissions on Terraform role, sharing creds across teams, OIDC trust too broad.

---

Cloud + CI: [DESCRIBE]
Current auth: [DESCRIBE]
Symptom: [DESCRIBE]

Why this prompt works

Auth is foundational and often misdone. This prompt walks modern patterns.

How to use it

  1. OIDC from CI preferred.
  2. Least privilege role.
  3. No static creds in code.
  4. Audit cloud trail.

Patterns

AWS OIDC from GitLab CI

# .gitlab-ci.yml
terraform-apply:
  id_tokens:
    AWS_JWT:
      aud: https://gitlab.com
  variables:
    AWS_ROLE_ARN: arn:aws:iam::123456789012:role/GitLabCITerraform
    AWS_WEB_IDENTITY_TOKEN_FILE: /tmp/jwt
  script:
    - echo "$AWS_JWT" > /tmp/jwt
    - terraform apply -auto-approve
# IAM role trust policy (one-time setup)
resource "aws_iam_role" "ci_terraform" {
  name = "GitLabCITerraform"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect = "Allow"
      Principal = {
        Federated = "arn:aws:iam::123456789012:oidc-provider/gitlab.com"
      }
      Action = "sts:AssumeRoleWithWebIdentity"
      Condition = {
        StringLike = {
          "gitlab.com:sub" = "project_path:myorg/infrastructure:ref_type:branch:ref:main"
        }
        StringEquals = {
          "gitlab.com:aud" = "https://gitlab.com"
        }
      }
    }]
  })
}

AWS local dev (aws-vault)

# Install aws-vault
brew install aws-vault

# Add profile (encrypted)
aws-vault add myorg-dev

# Run terraform with creds
aws-vault exec myorg-dev -- terraform plan

GCP Workload Identity Federation

# Provider pool + workload identity pool (one-time)
resource "google_iam_workload_identity_pool" "github" {
  workload_identity_pool_id = "github-actions"
}

resource "google_iam_workload_identity_pool_provider" "github" {
  workload_identity_pool_id          = google_iam_workload_identity_pool.github.workload_identity_pool_id
  workload_identity_pool_provider_id = "github-provider"

  oidc {
    issuer_uri = "https://token.actions.githubusercontent.com"
  }

  attribute_mapping = {
    "google.subject"       = "assertion.sub"
    "attribute.repository" = "assertion.repository"
  }

  attribute_condition = "attribute.repository == 'myorg/infrastructure'"
}

resource "google_service_account" "ci_terraform" {
  account_id = "ci-terraform"
}

resource "google_service_account_iam_binding" "wif" {
  service_account_id = google_service_account.ci_terraform.name
  role               = "roles/iam.workloadIdentityUser"

  members = [
    "principalSet://iam.googleapis.com/projects/${data.google_project.current.number}/locations/global/workloadIdentityPools/${google_iam_workload_identity_pool.github.workload_identity_pool_id}/attribute.repository/myorg/infrastructure"
  ]
}
# GitHub Actions
jobs:
  terraform:
    permissions:
      id-token: write
    steps:
    - uses: google-github-actions/auth@v2
      with:
        workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/github-actions/providers/github-provider'
        service_account: 'ci-terraform@myorg.iam.gserviceaccount.com'
    - run: terraform apply -auto-approve

Azure Managed Identity (runner)

provider "azurerm" {
  features {}
  use_msi = true                # use managed identity
}

Cross-account assume role

provider "aws" {
  alias  = "audit"
  region = "us-east-1"

  assume_role {
    role_arn     = "arn:aws:iam::AUDIT_ACCOUNT:role/TerraformAudit"
    session_name = "TerraformAuditSession"
    external_id  = "myorg-tf-external-id"
  }
}

Common findings this catches

  • Static key in committed .tfvars → rotate; remove; use OIDC.
  • Admin permissions on Terraform role → least privilege.
  • OIDC trust matches any branch → restrict via sub.
  • No external_id on cross-account → CD attack.
  • Local creds in shell history → aws-vault.
  • TFC variables containing secrets — mark sensitive.
  • Cloud trail not capturing Terraform actions → enable.

When to escalate

  • Org-wide IAM design — security.
  • OIDC integration across CIs — coordinate.
  • Compliance audit of Terraform access — security.

Related prompts

Newsletter

Get weekly AI workflows for DevOps engineers

Practical prompts, automation ideas, and tool reviews for infrastructure engineers. One email per week. No spam.