Secrets and Variables
You pass secrets and variables to Terraform with GitHub secrets and variables, GitLab CI/CD variables, env steps in hooks and workflows, or .tfvars files. Stategraph Orchestration runs Terraform on your GitHub Actions or GitLab CI runners for each pull request, so these values reach Terraform as in any other CI job. Use the one that fits your workflow.
Defining secrets
GitHub secrets and variables, and GitLab CI/CD variables, become environment variables in the runner, where your Terraform code and your workflow steps read them. Create them with the CLI or the web interface of your VCS.
GitHub
Using the GitHub CLI
Create a secret named AWS_ACCESS_KEY_ID:
gh secret set AWS_ACCESS_KEY_ID --body "<YOUR_ACTUAL_AWS_ACCESS_KEY_ID>"
Using the GitHub web interface
- Open the repository where Orchestration is installed.
- Go to Settings, then Secrets and variables, then Actions.
- Click New repository secret.
- Enter the Name (
AWS_ACCESS_KEY_ID) and the Secret value. - Click Add secret.
GitLab
Using the GitLab web interface
- Open your GitLab project.
- Go to Settings, then CI/CD, then Variables.
- Click Add variable.
- Enter the Key (
AWS_ACCESS_KEY_ID) and the Value. - Select Mask variable to hide it in logs.
- Click Add variable.
Orchestration starts plan pipelines on the merge request's source branch. GitLab passes a variable marked Protect variable only to pipelines on protected branches and tags, so leave that option cleared for each variable that a plan needs.
Using secrets in Terraform
CI secrets are usually uppercase, and Terraform variables are usually lowercase. The runner copies each environment variable that starts with TF_VAR_ to a name with the rest in lowercase:
- The uppercase variable stays as it is.
- If the lowercase name already exists, nothing changes.
For example, the secret TF_VAR_DATABASE_PASSWORD becomes TF_VAR_database_password, which Terraform maps to the variable database_password:
variable "database_password" {
description = "Password for database connection"
type = string
sensitive = true
}
resource "aws_db_instance" "example" {
# Other configuration...
password = var.database_password
}
Security
Your VCS stores secrets encrypted, and the CI platform decrypts them only in the runner of the job. The Orchestration server does not store unencrypted secrets.
Masking is different on each CI platform:
- GitHub: the runner masks each GitHub Actions secret in the job log, and in the plan and apply output that it posts to the pull request.
- GitLab: GitLab masks the variables marked Mask variable in the job log.
On both platforms, the runner masks the credentials of the oidc hook, and the values of env hooks and steps marked sensitive. Declare Terraform variables that hold secrets with sensitive = true, so that Terraform hides them in the plan output.
Plan files can contain sensitive values. For where they are stored, see Plan file storage.
Hooks and workflows
You can also set environment variables in .stategraph/config.yml, with hooks and workflows.
Hooks
An env hook sets a variable at the start of an operation:
hooks:
plan:
pre:
- type: env
name: FOO
cmd: ['echo', 'BAR']
apply:
pre:
- type: env
name: BAZ
cmd: ['echo', 'QUX']
The output of the command becomes the value, so you can compute a variable. This one gets the current Git branch:
hooks:
plan:
pre:
- type: env
name: CURRENT_GIT_BRANCH
cmd: ['bash', '-c', 'echo $(git rev-parse --abbrev-ref HEAD)']
A GitLab CI job checks out a detached commit, so there this command prints HEAD. On GitLab, read the predefined CI_COMMIT_REF_NAME variable.
Workflows
An env step sets a variable at the start of each plan and apply, for the directories that the workflow matches:
workflows:
- tag_query: ""
plan:
- type: init
- type: env
name: FOO
cmd: ["echo", "BAR"]
- type: plan
apply:
- type: init
- type: env
name: FOO
cmd: ["echo", "BAR"]
- type: apply
.tfvars files
Terraform reads variable values from .tfvars files. Pass one to the plan step with extra_args:
workflows:
- tag_query: ""
plan:
- type: init
- type: plan
extra_args: ["-var-file=qa.tfvars"]
apply:
- type: init
- type: apply
An example qa.tfvars:
region = "us-west-2"
instance_type = "t3.micro"
vpc_cidr = "10.0.0.0/16"
environment = "qa"
The plan step reads qa.tfvars. The apply step uses the stored plan, so the same values apply.
Next Steps
- Environment variables: the built-in variables the runner sets.
- Cloud credentials: OIDC and static credentials for your cloud provider.
- hooks and workflows: every step type.