Generated secrets
generatedSecrets produces one Opaque Secret per entry, named
<fullname>-gen-<name>, filled with credential material the cluster
generates rather than a value a human writes into values.yaml:
generatedSecrets:
- name: admin # -> Secret <fullname>-gen-admin
keys:
- key: password
kind: password # randAlphaNum
length: 32 # 16–128, default 32
- key: auth
kind: htpasswd # bcrypt "user:$2a$..." line
username: admin
passwordFrom: password # sibling key of kind passwordKey kinds
password—length(16–128, default 32) random alphanumeric characters viarandAlphaNum.htpasswd— a bcryptuser:$2a$...line viausernameplus eitherpasswordFrom(the name of a siblingpassword-kind key in the same entry) or an inlinepasswordstring.passwordandpasswordFromare mutually exclusive — set exactly one, or the render fails with a named error.
Reconciliation, not regeneration
On upgrade, the existing Secret is looked up and every requested key is reconciled independently:
- a key already present in the live Secret is reused verbatim,
- a key not yet present is generated fresh,
- a key no longer listed in values is dropped from the Secret — values are the contract, not an accumulating superset.
An htpasswd key sourced via passwordFrom is regenerated whenever its
source password key was itself freshly generated this render (a bcrypt
hash of a rotated password is invalid the moment the password rotates), so
the two stay consistent without you having to bump both by hand.
There’s no expiry or rotation tracking — unlike tlsSelfSigned and
webhooks, which track a platform/tls-not-after annotation and rotate
automatically near expiry, credential Secrets here don’t expire. Rotate by
deleting the key (or the whole Secret) and running helm upgrade; a
deleted key is treated as absent and regenerated, and a deleted Secret is
recreated from scratch.
Validation
Entry name and each keys[].key are required and pattern-checked
(name: DNS-1123 label; key: [A-Za-z0-9._-]+). Names are also checked
against a reserved-suffix list (-tls, -ca, -secret, -webhook-cert,
-mtls-client-*) so a generatedSecrets entry can never collide with a
release-managed Secret name from another feature. Duplicate entry names,
duplicate keys within an entry, and an entry with an empty keys list all
fail the render with a message naming the offending index.
Offline renders
helm template and client-side --dry-run never perform the Secret
lookup — every key generates fresh, every time. That’s why every rendered
Secret here carries the platform/generated: "true" annotation: the
lint gate’s golden-snapshot normalization redacts data: under that
marker so goldens stay byte-stable across runs instead of failing on
every render because of fresh random data.