SOPS
age key secret store β decrypt-at-apply planned
SOPS β π§ store ready, decrypt-at-apply planned
SOPS encrypts values in YAML/JSON files while keeping keys readable. Wardn has a sops/age secret store for the key side β what isn't wired yet is the apply-time decrypt in the manifest pipeline.
Status
| Piece | Status |
|---|---|
sops/age secret store | β
registered β Test does an encrypt/decrypt round-trip |
Apply-time decrypt of .sops.yaml files | π not wired β encrypted manifests apply as-is |
| KMS / GCP KMS / Vault Transit / PGP providers | π not registered β 400 on create |
Today the store validates keys, nothing more. If you commit a .sops.yaml-encrypted Secret, the operator applies the ENC[β¦] values literally. Keep plaintext-out-of-git via env.store (vault/ESO) until decrypt-at-apply lands.
Configure the store
Via the API
curl -X POST http://localhost:8080/api/v1/secret-stores -b cookies.txt \
-H "Content-Type: application/json" \
-d '{
"name": "dev-age",
"type": "sops",
"provider": "age",
"credentials": {"privateKey": "AGE-SECRET-KEY-1XYZβ¦"}
}'Via the UI
Secret Stores β Add Store β sops / age β paste the age private key; the provider schema drives the form.
POST /api/v1/secret-stores/{id}/test runs an actual encrypt/decrypt round-trip β connected means the key works end-to-end.
Intended apply-time flow (π)
βββββββββββββββ encrypted ββββββββββββ decrypt ββββββββββββββββ
β Developer ββββββββββββββΆβ Git βββββββββββββΆβ Operator β
β (sops -e) β β Repo β at apply β (store key) β
βββββββββββββββ ββββββββββββ ββββββββ¬ββββββββ
β
βΌ
ββββββββββββββββ
β K8s Secret β
β (plaintext) β
ββββββββββββββββWhen wired, the manifest pipeline will detect sops:-marked files under source.git.path and decrypt them against the registered age store before apply.
Working with SOPS today (client-side)
You can still encrypt and version secrets in Git β the decrypt happens on your side:
Step 1: Generate an age key
age-keygen -o key.txt
# public key printed to stderr: age1abcβ¦Step 2: Encrypt the secret file
sops --encrypt --age age1abc⦠--in-place manifests/secret.yamlStep 3: Register the key with Wardn
curl -X POST http://localhost:8080/api/v1/secret-stores -b cookies.txt \
-H "Content-Type: application/json" \
-d '{"name":"dev-age","type":"sops","provider":"age","credentials":{"privateKey":"β¦"}}'Step 4: Use .sops.yaml creation rules
creation_rules:
- path_regex: manifests/production/.*\.yaml
age: age1prodβ¦
- age: age1devβ¦sops -e --in-place then picks the right key per path.
What works vs what doesn't
| Capability | Status |
|---|---|
| Store an age private key | β
sealed via WARDN_CREDENTIALS_KEY |
Round-trip Test | β |
| Auto-detect + decrypt on apply | π |
sops-aware health (Secret exists with ENC[β¦] values β warn) | π |
Security Notes
- Never commit the private key β
.sops.yamlgoes to git;key.txtnever does - Sealed at rest β the store row encrypts to
enc:v1:keyed byWARDN_CREDENTIALS_KEY - Session-only writes β creating/rotating the store requires a session, not an API key
Related
- Secret Management Overview β compare the three layers
- External Secrets Operator β working alternative today
- Secret Stores API β manage stores via API