securely cache every aws ssm parameter inside k3s #417
Labels
No labels
burndown-2026-06
coherence-core
consult
headless
interactive
P0
P1
P2
P3
P4
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
coilyco-flight-deck/infrastructure#417
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The real problem (why this matters today)
The forgejo API token (and every other secret) lives in AWS SSM Parameter Store. The only way to read it today is a live AWS call (
ward-kdl ops aws ssm get-parameter --name /forgejo/api-token ..., seeagentic-os/scripts/git-credential-forgejo-ssm.sh). That call needs AWS auth, which needs 2FA. So a lost/absent 2FA device locks Kai out of her own git token. The fix is to mirror SSM into the cluster so day-to-day retrieval is akubectl get secretover the tailnet, never a 2FA-gated AWS round-trip.Current state (verified in-repo - do NOT rebuild this, extend it)
The cluster already runs external-secrets with the spine you need:
deploy/secretstore.yml- aSecretStoreandClusterSecretStorenamedaws-parameter-store, provider AWSParameterStore, regionus-east-1, authenticating with a staticaws-credentialssecret in theexternal-secretsnamespace (bootstrapped once viacoily aws-secrets aws_access_key_id=<ID> aws_secret_access_key=<SECRET>). That static key is NOT 2FA-gated - it is exactly what removes the 2FA dependency once params are mirrored.ExternalSecrets already exist, hand-written one at a time:deploy/externalsecret.yml(/github/pat),deploy/forgejo.yml(/forgejo/secret-key,/forgejo/internal-token, ...),deploy/forgejo-runner.yml(/forgejo/api-token-> secretforgejo-runner-secretskeyapi-token, nsforgejo).The gap: every param is mirrored by hand. This issue is to mirror all of SSM automatically.
What to build
Add
deploy/externalsecret-ssm-cache.ymlusing external-secrets bulk discovery (dataFrom->find) instead of enumerating keys. Example shape (verify against the external-secrets version installed -kubectl get deploy -n external-secrets):Do one ExternalSecret per top-level SSM prefix (
/coilysiren,/forgejo,/github, ...), each landing in its own namespaced Secret - do NOT dump all of SSM into a single secret (blast radius: any reader of that one secret reads everything). Scope by prefix and lock down RBAC so only intended consumers read each.Register the new manifest in
deploy/_flux/infrastructure/kustomization.yamlso Flux GitOps-reconciles it (this repo is Flux-managed underdeploy/_flux/).Write
docs/ssm-cache.md: what is mirrored, the prefix->namespace->secret mapping, the refresh interval, the RBAC/blast-radius reasoning, and the new everyday-retrieval recipe (kubectl get secret ... -o jsonpath).Acceptance
kubectl get secret ssm-cache-<prefix> -n <ns> -o jsonshows the SSM params under that prefix, base64-decodable, refreshing on the interval.docs/ssm-cache.mdexists and the manifests are wired into Flux.Files
deploy/secretstore.yml(read),deploy/externalsecret.yml(template),deploy/_flux/infrastructure/kustomization.yaml, newdeploy/externalsecret-ssm-cache.yml, newdocs/ssm-cache.md. Related: this unblocks the secrets gap in #418; see also #419.