Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Keeping secrets out of the code

After this lesson: I can keep a secret out of OpenTofu files and say where it still ends up.

60 min lesson10 commandsOpenTofu lab: infrastructure as code with plan, apply and state on one VM

The key on the front page

Keeping secrets out of code means a password, key or token is never written into the files of a project. It matters because anybody who can read the files can use the key. It also stays in the history after the file is changed.

A student pushes a project to a public repository. One file holds an access key, because it made the first test work. Programs that read public repositories all day find it within minutes.

By the end of this lesson

Note

I can keep a secret out of OpenTofu files and say where it still ends up.

Key words

WordWhat it meansExample
Secreta value nobody else should see, such as a key
Sensitivemarked so the tool hides it on screen
Environment variablea value the shell hands to a commandTF_VAR_token
Statethe file where OpenTofu records what it made
Ignore filea list of files that version control skips.gitignore

The cells students fill in are left blank in this preview.

A secret stays out of committed files

A value written in a .tf file is saved with the project, copied to every clone and kept in the history. So a secret is given to OpenTofu from outside.

The usual way is an environment variable. A variable called token is set by TF_VAR_token. Marking the variable sensitive then hides it on screen.

Make a folder and go in

Command
mkdir -p ~/iac-demo/vault && cd ~/iac-demo/vault

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Write a project that takes a secret

Command
printf '%s\n' 'variable "token" {' '  type      = string' '  sensitive = true' '}' '' 'resource "terraform_data" "login" {' '  input = var.token' '}' '' 'output "shown" {' '  value     = terraform_data.login.output' '  sensitive = true' '}' > main.tf

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Prepare the folder

Command
tofu init -no-color | grep successfully

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Plan with the secret in the environment

Command
TF_VAR_token=moon42 tofu plan -no-color | grep -E "input|^Plan"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Apply it

Command
TF_VAR_token=moon42 tofu apply -auto-approve -no-color | grep -E "Apply complete|shown"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

List the outputs

Command
tofu output

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Sensitive hides a value only

sensitive only changes what is printed. The state still records every value in plain text, because OpenTofu needs it to compare next time.

So the state file is as secret as the secret. Keep it out of version control, and in real work keep it in a store that is encrypted and has limited access.

Count the places the state holds the value

Command
grep -c moon42 terraform.tfstate

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Ask for the raw output

Command
tofu output -raw shown; echo

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A common mistake

Warning

Many people think sensitive encrypts a value. It does not. It hides the value in the plan and the output, and anybody who can read the state or run tofu output -raw still sees it. Protect the state as well.

An ignore file keeps the state out

A .gitignore lists files that version control never adds. Four lines cover an OpenTofu project: the state, its backup, any .tfvars file and the .terraform folder.

Leaving one out is how a state with a secret in it gets pushed.

Write an ignore file

Command
printf '%s\n' 'terraform.tfstate' 'terraform.tfstate.backup' '*.tfvars' '.terraform/' > .gitignore

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Plant a secret and scan for it

Command
printf '%s\n' 'locals {' '  api_token = "moon42"' '}' > leak.tf; grep -nE '(token|secret|password|key)[a-z_]* *= *"' *.tf; rm leak.tf

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

A scan for secrets, worked out in Python

Code: python
# Find lines that give a secret a value in the file itself.
lines = [
    'region = "eu-west-2"',
    'api_token = "moon42"',
    'api_token = var.api_token',
]
words = ["token", "secret", "password", "key"]
for number, line in enumerate(lines, 1):
    name = line.split("=")[0].strip().lower()
    value = line.split("=")[1].strip()
    if any(word in name for word in words) and value.startswith('"'):
        print("line", number, "gives", name, "a value")
# Change the third line to a quoted value and look again.

Going further: a variable file

Write the line token = "sun77" in a file called secret.tfvars. Run tofu plan -no-color -var-file=secret.tfvars | grep -E "input|^Plan", then delete the file.

Why is *.tfvars in the ignore file, and does the plan show the new value?

About this lab and its source: OpenTofu lab: infrastructure as code with plan, apply and state on one VM

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.