Skip to content

Getting started

This page takes one file, credentials.toml, through the basic steps: marking its secrets, encrypting it and decrypting it, on the command line and in Python. The sections after that cover checks in CI, changing the password and supplying it in automation.

1 Mark the secrets

A value is secret only when it is wrapped in an object carrying the reserved __keyloom__ marker. Keyloom never infers from a field name such as token or password that a value is sensitive. The value holds either the secret itself or the placeholder __keyloom__secret__:

[git."gitlab.example.org"]
username = "oauth2"
token = { __keyloom__ = "secret", value = "__keyloom__secret__" }
git:
  gitlab.example.org:
    username: oauth2
    token:
      __keyloom__: secret
      value: __keyloom__secret__
{
  "git": {
    "gitlab.example.org": {
      "username": "oauth2",
      "token": {
        "__keyloom__": "secret",
        "value": "__keyloom__secret__"
      }
    }
  }
}

The wrapper is the same logical object in all three formats, so the rest of this page uses TOML. There are two ways to provide the secret:

  • Write the placeholder, as above, and type the secret when the file is encrypted. The secret then never exists in the file as plaintext.
  • Write the secret itself into value. This suits a file kept on a tmpfs or other storage where plaintext is acceptable, a secret that spans several lines such as a PEM key, and an existing plaintext configuration.

2 Encrypt the file

2.1 On the command line

keyloom encrypt credentials.toml

The command asks for the vault password and then for the secret of every placeholder, each named by its location in the file and each entered twice. Nothing is echoed:

Vault password:
Confirm vault password:
Secret for git."gitlab.example.org".token:
Confirm secret for git."gitlab.example.org".token:
credentials.toml: encrypted 1 secret

A secret typed at the prompt goes to its envelope in memory; a secret written into value is encrypted without a prompt. Either way the file ends up the same, and everything outside the wrappers stays readable:

[git."gitlab.example.org"]
username = "oauth2"
token = { __keyloom__ = "secret", value = "$KEYLOOM;1;argon2-v2;s=..." }

Adding a secret later is the same step: add a wrapper and run encrypt again. Values that are already encrypted are left encrypted and are first verified against the supplied password, so a single run never produces a file whose secrets use different passwords.

Placeholders need a terminal. Where there is none, as in a CI job, a placeholder is an error and nothing is written; secrets written into value need no terminal.

2.2 In Python

keyloom.encrypt_file does the same for a file. prompt is called once for every placeholder with its location and returns the secret; None makes a placeholder an error. Pass the same path twice to encrypt in place:

import getpass

import keyloom

keyloom.encrypt_file(
    input_path="credentials.toml",
    output_path="credentials.toml",
    password=password,
    algorithm=keyloom.Algorithm.ARGON2_V2,
    prompt=lambda location: getpass.getpass(f"Secret for {location}: "),
)

An application that produces its configuration itself marks the secrets with keyloom.secret and writes the data with keyloom.store, which encrypts them on the way to the file:

keyloom.store(
    path="credentials.toml",
    data={"git": {"token": keyloom.secret(value=token)}},
    password=password,
    algorithm=keyloom.Algorithm.ARGON2_V2,
)

store writes the file fresh, so the comments of an existing file are lost; encrypt_file keeps the file as it is apart from the encrypted values. Unlike the command line, the API has no default algorithm: every call that encrypts names one, as a member of keyloom.Algorithm.

3 Decrypt the file

3.1 On the command line

decrypt writes the decrypted file to standard output with the wrappers still in place:

keyloom decrypt credentials.toml

--unwrap replaces each wrapper by its value and emits the ordinary configuration:

keyloom decrypt --unwrap credentials.toml

--output FILE writes the decrypted file to disk instead, with mode 0600.

3.2 In Python

An application reads the file with keyloom.load, which decrypts and unwraps the marked values in memory and returns ordinary Python data:

import keyloom

credentials = keyloom.load(path="credentials.toml", password=password)
token = credentials["git"]["gitlab.example.org"]["token"]

keyloom.decrypt_file writes the decrypted file to disk with its wrappers and mode 0600, so encrypt_file turns it back into an encrypted file. It refuses to write onto the input file:

keyloom.decrypt_file(
    input_path="credentials.toml",
    output_path="credentials.plain.toml",
    password=password,
)

In both, a marked value that is still plaintext is an error. A file that was never encrypted, or whose envelope was replaced by plaintext, is therefore never decrypted silently.

4 Advanced use

4.1 Keep plaintext out of the repository

keyloom check credentials.toml

check fails if any marked value is not a well-formed envelope: plaintext, a placeholder, or a malformed envelope. It needs no password, so it fits a pre-commit hook or a CI job.

4.2 Change the password or the algorithm

reencrypt encrypts every secret again in memory, so the plaintext never reaches the disk:

keyloom reencrypt --change-password credentials.toml

The same command moves a file to another algorithm with --algorithm.

In Python, keyloom.reencrypt_file takes the current and the new password. Passing the same password twice changes only the algorithm:

keyloom.reencrypt_file(
    input_path="credentials.toml",
    output_path="credentials.toml",
    password=password,
    new_password=new_password,
    algorithm=keyloom.Algorithm.ARGON2_V2,
)

4.3 Supply the password in automation

Interactive commands prompt for the password. CI jobs, containers and other non-interactive environments pass it on standard input or in a file:

printf '%s\n' "$KEYLOOM_PASSWORD" |
  keyloom decrypt --password-stdin credentials.toml
keyloom decrypt \
  --password-file /run/secrets/keyloom-password \
  credentials.toml

Note

Keyloom has no --password PASSWORD option. A password given as a command-line argument can leak through shell history, logs or process inspection.

Next steps

How it works explains the wrapper, the envelopes and what Keyloom protects. The command-line reference and the Python API list every command, option and function.