Chillbox can be used store and use secrets locally. The steps below will show an example of using OpenTofu and Chillbox together in a way that securely stores sensitive information. Using the below example, the tfstate files generated by OpenTofu are automatically encrypted with a passphrase. This passphrase is then encrypted by the GPG key that chillbox uses. These encrypted files could then be committed to source control and/or backed up.

Prerequisites
  • Setup a chillbox instance and be familiar with the chillbox configuration file (chillbox.toml) and commands.

  • Install OpenTofu on the local machine.

Tutorial Steps

1. Add a secret passphrase to encrypt tfstate

The passphrase used for OpenTofu must be at least 16 characters long. Please read the State and Plan Encryption for more details. It is recommended to also save this passphrase using your password manager.

  1. Add a secret prompt to the chillbox.toml file

    Update file: chillbox.toml
    [[secret]]
    id = "tfstate_passphrase_alice"
    name = "TF_VAR_tfstate_passphrase" (1)
    prompt = "Enter passphrase to encrypt the tfstate with."
    owner = "alice" (2)
    1 This name needs to be prefixed with 'TF_VAR_' so OpenTofu will automatically use it to set tf variable with the name after the prefix.
    2 Only alice will be using tofu and will own the passphrase used to encrypt the tfstate.

2. Create the minimal OpenTofu configuration files

OpenTofu can use either .tf or .tofu file extensions for configuration files written in the OpenTofu Language. For this tutorial the .tofu extension is used since only OpenTofu has the encryption feature.

  1. Define the variable for storing the passphrase used for encrypting the tfstate. A new directory is used here with the name 'example-iac'. This is where the OpenTofu configuration files will be saved and where the tofu command should be used.

    Add the example-iac/variables.tofu file
    variable "tfstate_passphrase" {
      # Should be set via env variable TF_VAR_tfstate_passphrase
      type = string
      description = "Passphrase to use for encrypting the local tfstate file."
      sensitive = true
      nullable = false
      validation {
        condition = length(var.tfstate_passphrase) >= 16
        error_message = "The passphrase must be at least 16 characters long."
      }
    }
  2. Use a 'local' backend and enforce encryption. See State and Plan Encryption for more information.

    Add the example-iac/main.tofu file
    terraform {
      backend "local" {
        path = "tofu.tfstate"
      }
      encryption {
        key_provider "pbkdf2" "chillbox_local_tf_key_v1" {
          passphrase = var.tfstate_passphrase
        }
        method "aes_gcm" "chillbox_local_method_v1" {
          keys = key_provider.pbkdf2.chillbox_local_tf_key_v1
        }
        state {
          enforced = true
          method = method.aes_gcm.chillbox_local_method_v1
        }
        plan {
          enforced = true
          method = method.aes_gcm.chillbox_local_method_v1
        }
      }
    }
  3. Add an example resource using the opentofu/random provider.

    Update the example-iac/main.tofu file
    terraform {
      # ...
    
      required_providers {
        random = {
          source = "opentofu/random"
          version = "3.6.2"
        }
      }
    }
    Add the example-iac/example.tofu file
    resource "random_pet" "example" {
    }

3. Initialize Chillbox and apply the OpenTofu configuration

  1. Use the chillbox init command which will prompt for the new passphrase to use when encrypting the tfstate. This passphrase will be encrypted with the GPG key that was used with chillbox. This also assumes that the current user is 'alice' as that user is the owner of the tfstate_passphrase_alice secret in chillbox.toml.

    chillbox init
    Store the passphrase for encrypting the tfstate in a password manager for actual production use. Chillbox shouldn’t be used as the only place that secrets like this are stored! If this passphrase is lost there will be no way to decrypt the tfstate files used for OpenTofu.
  2. Load up the env and secrets stored with chillbox by using the 'output-env' command. This will set the TF_VAR_tfstate_passphrase in the environment thus allowing the tofu command to decrypt the tfstate as needed.
    set +x; set -a; . "$(chillbox output-env --sensitive)"; chillbox output-env-clean; set +a

    Explanation of previous single line command
    set +x (1)
    set -a (2)
    . "$(chillbox output-env --sensitive)" (3)
    chillbox output-env-clean (4)
    set +a (5)
    1 Turn off echoing of commands being run to protect the sensitive values.
    2 Allow export of each variable
    3 Source the temporary file of all env variables including secrets
    4 Deletes the temporary file
    5 Unset the export option
  3. Use OpenTofu commands with the added security of having the tfstate file encrypted at rest. The example-iac/tofu.tfstate file can be committed to source control along with the .chillbox/secrets/tfstate_passphrase_alice.aes file as they are both encrypted.

    cd example-iac
    tofu init
    tofu apply
    cd -
  4. Ensure files are encrypted by doing a hexdump since these are in binary format.

    hexdump -C example-iac/tofu.tfstate
    hexdump -C .chillbox/secrets/tfstate_passphrase_alice.aes

Summary

One benefit of encrypting the tfstate file locally and storing it in a git repository is it allows others to also run tofu commands without needing a remote backend. This of course will require coordination between the individuals that know the tfstate_passphrase, since they will need to commit and push any changes that were done.

This also makes it easier for a developer to backup these encrypted files safely.


https://git.sr.ht/~jkenlooper/chillbox