feat(secrets): compose delivery — env_file for nested docker/compose apps#494
Merged
Conversation
…apps KMS-protected tenant secrets are decrypted (via the KMS-unwrapped DEK) and delivered to the app, but the existing `env` (LXC config) and `file` (/run/secrets) modes both miss a docker-compose stack running inside the LXC: a docker container doesn't inherit the LXC environment and doesn't see /run/secrets. This is the gap OTel closed with a dotenv `env_file:`. Add a third delivery mode, `compose`, that renders the tenant's compose-mode secrets into a single dotenv file at /run/containarium/secrets.env (mode 0400, tmpfs) for docker-compose `env_file:` consumption. Built on the shared EnvFile helper from #492 — no copy-paste of the OTel plumbing. - internal/secrets/store.go: DeliveryCompose constant; ValidateDelivery accepts it; ValidateValueForDelivery rejects multi-line values for compose at set-time (a dotenv KEY=value line can't represent a newline). - pkg/core/container/secrets_envfile.go: SecretsEnvFile EnvFile value (path /run/containarium/secrets.env, mode 0400). - internal/server/secrets_server.go: stampSecretsOnLXC batches compose rows and Write/RemoveEnvFile once per tenant (the empty-map Remove cleans up after the last compose secret is deleted). - CLI `--delivery` help + secrets.proto comments updated (regen); no wire change (delivery is a free string validated server-side). - docs/security/SECRETS-ENV-VAR-RISK.md: compose-mode section + exposure profile vs env/file. Tests: ValidateDelivery accepts compose; ValidateValueForDelivery single-line guard (env/file allow multi-line, compose rejects newline/CR). Closes #491. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
a46c748 to
aef0691
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #491. Stacked on #493 (the shared
EnvFileextraction); base isrefactor/envfile-deliveryand re-targets tomainonce #493 merges.Summary
KMS-protected tenant secrets are decrypted (via the KMS-unwrapped DEK, incl. the AWS backend in #490) and delivered to the app — but the existing
env(LXC config) andfile(/run/secrets) modes both miss a docker-compose stack running inside the LXC: a docker container doesn't inherit the LXC environment and doesn't see/run/secrets. That's the gap OTel closed with a dotenvenv_file:(#370).Adds a third delivery mode,
compose, that renders the tenant's compose-mode secrets into a single dotenv file at/run/containarium/secrets.env(mode0400, tmpfs) for docker-composeenv_file:. Built on the sharedEnvFilehelper from #492/#493 — no copy-paste of the OTel plumbing.Changes
internal/secrets/store.go—DeliveryComposeconstant;ValidateDeliveryaccepts it;ValidateValueForDeliveryrejects multi-line values forcomposeat set-time (a dotenvKEY=valueline can't hold a newline). Multi-line blobs → usefiledelivery.pkg/core/container/secrets_envfile.go—SecretsEnvFileEnvFilevalue (/run/containarium/secrets.env,0400).internal/server/secrets_server.go—stampSecretsOnLXCbatchescomposerows andWrite/RemoveEnvFileonce per tenant (empty-mapRemovecleans up after the last compose secret is deleted/switched).--deliveryhelp +secrets.protocomments updated (regen). No wire change —deliveryis a free string validated server-side.docs/security/SECRETS-ENV-VAR-RISK.md—compose-mode section + exposure profile vsenv/file.Security notes
0400root (not OTel's0644) — the compose runtime (root) reads it at container-create time and injects values as env; the app never reads the file, so0400 rootis safe and sufficient./run(tmpfs) — evicted on container stop, never on the writable rootfs.incus config show(unlikeenvmode).Test plan
go build ./...✅,go vetclean.go test ./internal/secrets/ ./pkg/core/container/✅ —ValidateDeliveryacceptscompose;ValidateValueForDeliverysingle-line guard (env/file allow multi-line, compose rejects newline/CR); constant shape.Refs
EnvFiledelivery (prerequisite)env_filedelivery (the pattern)🤖 Generated with Claude Code