CI/CD with Other Platforms
The TF_TOKEN_* pattern works on any platform that can set environment variables. See the CI/CD overview for prerequisites and how authentication works.
Spacelift
Based on Spacelift's environment configuration documentation, compliance.tf tokens are configured as follows.
Store the Token
Per stack:
- Open your stack in Spacelift
- Go to Environment
- Click Add Variable
- Key:
TF_TOKEN_soc2_compliance_tf - Value: paste your token
- Check Secret
Organization-wide (recommended):
- Go to Contexts in your Spacelift account
- Create a new context (e.g., "compliance-tf-credentials")
- Add the environment variable
TF_TOKEN_soc2_compliance_tfas a secret - Attach the context to all relevant stacks
No Pipeline File Needed
Spacelift handles terraform init, plan, and apply automatically. Once the environment variable is available to the stack, module downloads from the compliance.tf registry work without further configuration.
Reference: Spacelift Contexts
Atlantis
Based on Atlantis server configuration documentation, compliance.tf tokens are configured at the server level.
Store the Token
Atlantis runs Terraform server-side, so the token is configured once on the Atlantis server, not per repository.
Set the environment variable in your Atlantis deployment:
services:
atlantis:
image: ghcr.io/runatlantis/atlantis:latest
environment:
# compliance.tf registry authentication
TF_TOKEN_soc2_compliance_tf: "${CTF_TOKEN}"
# ... other configuration
apiVersion: v1
kind: Secret
metadata:
name: atlantis-ctf-token
type: Opaque
stringData:
TF_TOKEN_soc2_compliance_tf: "ctf_YOUR_TOKEN_HERE"
Reference the secret in your Atlantis deployment's envFrom or env configuration.
Add TF_TOKEN_soc2_compliance_tf to your task definition's secrets block, referencing an AWS Secrets Manager or SSM Parameter Store value.
Optional: Custom Workflow
If you want to add a verification step, define a custom workflow in repos.yaml:
repos:
- id: /.*/
workflow: compliance
workflows:
compliance:
plan:
steps:
- init
- plan
apply:
steps:
- apply
Reference: Atlantis custom workflows
env0
Based on env0's variable documentation, compliance.tf tokens are configured as follows.
Store the Token
- Go to Organization Settings > Variables (for organization-wide) or your project/environment variables
- Click Add Variable
- Type: Environment
- Key:
TF_TOKEN_soc2_compliance_tf - Value: paste your token
- Mark as Sensitive
Optional: Custom Flow
If you want to add a verification step, use a Custom Flow:
deploy:
steps:
planCommand:
after:
- name: Save Plan Output
command: terraform show -json tfplan > plan.json
Reference: env0 Custom Flows
Jenkins
Store the Token
- Go to Manage Jenkins > Credentials
- Select the appropriate scope (global or folder)
- Click Add Credentials
- Kind: Secret text
- Secret: paste your token
- ID:
ctf-token
Configure Your Pipeline
pipeline {
agent any
tools {
terraform 'terraform-1.9'
}
stages {
stage('Init') {
steps {
withCredentials([string(credentialsId: 'ctf-token', variable: 'CTF_TOKEN')]) {
withEnv(["TF_TOKEN_soc2_compliance_tf=${CTF_TOKEN}"]) {
sh 'terraform init'
}
}
}
}
stage('Plan') {
steps {
withCredentials([string(credentialsId: 'ctf-token', variable: 'CTF_TOKEN')]) {
withEnv(["TF_TOKEN_soc2_compliance_tf=${CTF_TOKEN}"]) {
sh 'terraform plan -out=tfplan'
}
}
}
}
stage('Apply') {
when {
branch 'main'
}
steps {
withCredentials([string(credentialsId: 'ctf-token', variable: 'CTF_TOKEN')]) {
withEnv(["TF_TOKEN_soc2_compliance_tf=${CTF_TOKEN}"]) {
sh 'terraform apply -auto-approve tfplan'
}
}
}
}
}
}
Reference: Jenkins credentials handling
CircleCI
Store the Token
Add CTF_TOKEN as an environment variable in your CircleCI project or in a shared context:
- Open your project in CircleCI
- Go to Project Settings > Environment Variables
- Click Add Environment Variable
- Name:
CTF_TOKEN - Value: paste your token
- Go to Organization Settings > Contexts
- Create a new context (e.g.,
compliance-tf) - Add the environment variable
CTF_TOKEN - Reference the context in your workflow jobs
Configure Your Pipeline
version: 2.1
orbs:
terraform: hashicorp/terraform@1.0
jobs:
terraform-plan:
docker:
- image: hashicorp/terraform:1.12
steps:
- checkout
- run:
name: Terraform Init
command: |
export TF_TOKEN_soc2_compliance_tf="${CTF_TOKEN}"
terraform init
- run:
name: Terraform Validate
command: terraform validate
- run:
name: Terraform Plan
command: |
export TF_TOKEN_soc2_compliance_tf="${CTF_TOKEN}"
terraform plan -out=tfplan
- persist_to_workspace:
root: .
paths:
- .
terraform-apply:
docker:
- image: hashicorp/terraform:1.12
steps:
- attach_workspace:
at: .
- run:
name: Terraform Apply
command: |
export TF_TOKEN_soc2_compliance_tf="${CTF_TOKEN}"
terraform apply -auto-approve tfplan
workflows:
infrastructure:
jobs:
- terraform-plan:
context: compliance-tf
- hold-apply:
type: approval
requires:
- terraform-plan
filters:
branches:
only: main
- terraform-apply:
context: compliance-tf
requires:
- hold-apply
filters:
branches:
only: main
The hold-apply job is a built-in approval gate — the apply step will not run until a team member manually approves it in the CircleCI dashboard.
Reference: CircleCI contexts, CircleCI environment variables
Azure DevOps
Store the Token
Add CTF_TOKEN as a secret pipeline variable or in a shared variable group:
- Open your pipeline in Azure DevOps
- Click Edit > Variables
- Click New Variable
- Name:
CTF_TOKEN - Value: paste your token
- Check Keep this value secret
- Go to Pipelines > Library
- Click + Variable group
- Name the group (e.g.,
compliance-tf-credentials) - Add
CTF_TOKENand mark it as secret - Reference the group in any pipeline that needs registry access
Configure Your Pipeline
trigger:
branches:
include:
- main
- feature/*
pool:
vmImage: ubuntu-latest
variables:
- group: compliance-tf-credentials
stages:
- stage: Plan
displayName: Terraform Plan
jobs:
- job: TerraformPlan
steps:
- task: TerraformInstaller@1
displayName: Install Terraform
inputs:
terraformVersion: latest
- script: |
export TF_TOKEN_soc2_compliance_tf="$(CTF_TOKEN)"
terraform init
displayName: Terraform Init
- script: terraform validate
displayName: Terraform Validate
- script: |
export TF_TOKEN_soc2_compliance_tf="$(CTF_TOKEN)"
terraform plan -out=tfplan
displayName: Terraform Plan
- publish: $(System.DefaultWorkingDirectory)/tfplan
artifact: tfplan
displayName: Publish Plan Artifact
- stage: Apply
displayName: Terraform Apply
dependsOn: Plan
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: TerraformApply
environment: production
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: tfplan
- task: TerraformInstaller@1
displayName: Install Terraform
inputs:
terraformVersion: latest
- script: |
export TF_TOKEN_soc2_compliance_tf="$(CTF_TOKEN)"
terraform init
displayName: Terraform Init
- script: |
export TF_TOKEN_soc2_compliance_tf="$(CTF_TOKEN)"
terraform apply -auto-approve $(Pipeline.Workspace)/tfplan/tfplan
displayName: Terraform Apply
The Apply stage uses a deployment job targeting the production environment. Configure Approvals and checks on that environment to require manual approval before apply runs.
Reference: Azure DevOps variable groups, Azure DevOps environments
Generic / Other
The TF_TOKEN_* environment variable pattern works on any CI/CD platform that can set environment variables and run shell commands. This includes AWS CodeBuild, Buildkite, Drone, Harness, and Codefresh.
The Pattern
- Store your compliance.tf token as a secret in your CI/CD platform
- Expose it as an environment variable named
TF_TOKEN_soc2_compliance_tf - Run
terraform init— Terraform picks up the token automatically
# The CI/CD platform injects CTF_TOKEN from its secret store
export TF_TOKEN_soc2_compliance_tf="${CTF_TOKEN}"
terraform init
terraform validate
terraform plan -out=tfplan
Alternative: Dynamic .terraformrc
If your platform does not support environment variable names with underscores, you can write a credentials file dynamically:
# Write credentials file (token comes from CI secret store)
cat > ~/.terraformrc <<EOF
credentials "soc2.compliance.tf" {
token = "${CTF_TOKEN}"
}
EOF
terraform init
terraform plan -out=tfplan
# Clean up credentials file
rm -f ~/.terraformrc
Clean up credentials files
If you write a .terraformrc file dynamically, delete it at the end of the pipeline run. Do not leave credentials on shared build agents.