Secrets done safely

Generators, SOPS, and the pitfalls.

Advanced14 min · lesson 9 of 12

Kustomize can generate Secrets, but generation is not protection — a secretGenerator only base64-encodes values into a Secret object, and base64 is encoding, not encryption. So the source of a generated Secret (literals in kustomization.yaml or an env file) is plaintext, and if you commit it, the secret is in Git for anyone with repo access. The safe pattern keeps secret material out of the repo entirely.

terminal
$ kustomize build overlays/prod | grep -A2 "kind: Secret"
kind: Secret
data:
password: UzNjcjN0IQ== # base64("S3cr3t!") — trivially decodable, NOT encrypted

SOPS and external secrets

Two solid approaches. SOPS encrypts the secret values so the file in Git is ciphertext, and a Kustomize SOPS plugin (or the KSOPS generator) decrypts at build time with a key you control — the same pattern as Helm secrets or the SOPS course. Better still for many teams, do not put secrets in manifests at all: use the External Secrets Operator or a CSI secrets driver so the Secret is materialized in-cluster from Vault or a cloud store, and Kustomize only references it.

kustomization.yaml (KSOPS)
generators:
- secret-generator.yaml # a KSOPS generator that decrypts a SOPS file at build
# the encrypted file (db.enc.yaml) is safe in Git; the key decrypts it at build time
# — plaintext secrets never touch the repo
A generated Secret in build output is plaintext-equivalent
Piping kustomize build to a log, artifact, or PR comment exposes any generated Secret in base64 — decodable in one command. Never render secret-bearing overlays into CI logs or artifacts, keep secret sources encrypted (SOPS) or external (ESO/Vault), and treat base64 in a Secret as visible plaintext. Encoding is not a security control.