Tier-derived AWS cred mount: grant ward ops aws exec -> mount ~/.aws #545

Open
opened 2026-07-03 05:14:03 +00:00 by coilysiren · 0 comments
Owner

Problem

Warded containers should get AWS credentials mounted when, and only when, their ward-kdl tier grants ward ops aws exec. Today cred access does not follow the tier grant. A warded architect on the write tier (which grants aws CLI exec) has no way to read SSM/Secrets Manager from inside the container, even though the tier says she can.

Current wiring (two decoupled axes)

"Can I run the aws verbs" and "do I have creds" are separate axes today, and only the first is guardfile-derived:

  • Guardfile presence is uniform, not tier-derived. cmd/ward/wardkdl_exec.go embeds //go:embed execassets/*.guardfile.kdl and mountWardKdlExec grafts every embedded guardfile - including ward-kdl.aws.guardfile.kdl - onto every container regardless of tier. That is why ward ops aws ssm ... is surfaced even in a read-only director surface. The aws guardfile is a single flat file, not read/write/admin-tiered the way forgejo/signoz are (cmd/ward-kdl/ward-kdl-{read,write,admin}/).
  • Cred presence is a separate opt-in mount. --aws mounts host ~/.aws read-only to /root/.aws (cmd/ward/container_compute.go:366, containerAWSMount). --tailnet implies it (ward#362); the director paths add it (agent_director.go:122, agent_director_heartbeat.go:477). Nothing derives it from the tier grant.

Net: the aws guardfile is always present; creds ride a manual flag. Intent is the inverse - the grant should imply the mount.

Desired model

If a run's ward-kdl tier grants the ward ops aws wrap, ward auto-mounts creds (--aws becomes a consequence of the guardfile set, not a separate flag). If the tier does not grant aws exec, the container stays credless.

Design questions for the advisor pass

  1. Where does the per-run tier-grant set live? Today the guardfile set is uniform-embedded, so "your tier grants aws" is not a thing the container launcher can test. Introduce a per-run notion of which wraps the tier grants (tiered aws guardfile variants, or a tier->wrap map), then key the mount off it.
  2. Broad ~/.aws vs scoped creds. The guardfile already narrows operations (deny */prod/* secrets, *tfstate*/*-backup* s3, etc.), but the mounted credential itself is whole. Decide whether the broad ~/.aws mount is acceptable given the op-level guard, or whether creds should be scoped/minted per-tier.
  3. Interaction with existing implicit --aws (--tailnet implies it; director paths add it). Reconcile so grant-derived mounting does not double-wire or contradict those.
  4. The host-side resolve-and-inject boundary (container.go:44-48, ward#186): today host ward resolves specific SSM params (/forgejo/api-token, ollama host) and injects only the resolved values, deliberately keeping raw AWS creds out of the image. Grant-derived mounting relaxes that for aws-granted tiers - the design must state the new boundary explicitly.

Deliverable

A design proposal on this thread: the tier-grant representation, the mount trigger, the cred-scope decision, and a migration path. No code in the advisor pass.

## Problem Warded containers should get AWS credentials mounted **when, and only when, their ward-kdl tier grants `ward ops aws` exec**. Today cred access does not follow the tier grant. A warded architect on the write tier (which grants aws CLI exec) has no way to read SSM/Secrets Manager from inside the container, even though the tier says she can. ## Current wiring (two decoupled axes) "Can I run the aws verbs" and "do I have creds" are separate axes today, and only the first is guardfile-derived: - **Guardfile presence is uniform, not tier-derived.** `cmd/ward/wardkdl_exec.go` embeds `//go:embed execassets/*.guardfile.kdl` and `mountWardKdlExec` grafts **every** embedded guardfile - including `ward-kdl.aws.guardfile.kdl` - onto **every** container regardless of tier. That is why `ward ops aws ssm ...` is surfaced even in a read-only director surface. The aws guardfile is a single flat file, not read/write/admin-tiered the way forgejo/signoz are (`cmd/ward-kdl/ward-kdl-{read,write,admin}/`). - **Cred presence is a separate opt-in mount.** `--aws` mounts host `~/.aws` read-only to `/root/.aws` (`cmd/ward/container_compute.go:366`, `containerAWSMount`). `--tailnet` implies it (ward#362); the director paths add it (`agent_director.go:122`, `agent_director_heartbeat.go:477`). Nothing derives it from the tier grant. Net: the aws guardfile is always present; creds ride a manual flag. Intent is the inverse - the grant should imply the mount. ## Desired model If a run's ward-kdl tier grants the `ward ops aws` wrap, ward auto-mounts creds (`--aws` becomes a consequence of the guardfile set, not a separate flag). If the tier does not grant aws exec, the container stays credless. ## Design questions for the advisor pass 1. **Where does the per-run tier-grant set live?** Today the guardfile set is uniform-embedded, so "your tier grants aws" is not a thing the container launcher can test. Introduce a per-run notion of which wraps the tier grants (tiered aws guardfile variants, or a tier->wrap map), then key the mount off it. 2. **Broad `~/.aws` vs scoped creds.** The guardfile already narrows *operations* (deny `*/prod/*` secrets, `*tfstate*`/`*-backup*` s3, etc.), but the mounted credential itself is whole. Decide whether the broad `~/.aws` mount is acceptable given the op-level guard, or whether creds should be scoped/minted per-tier. 3. **Interaction with existing implicit `--aws`** (`--tailnet` implies it; director paths add it). Reconcile so grant-derived mounting does not double-wire or contradict those. 4. **The host-side resolve-and-inject boundary** (`container.go:44-48`, ward#186): today host ward resolves specific SSM params (`/forgejo/api-token`, ollama host) and injects only the resolved values, deliberately keeping raw AWS creds out of the image. Grant-derived mounting relaxes that for aws-granted tiers - the design must state the new boundary explicitly. ## Deliverable A design proposal on this thread: the tier-grant representation, the mount trigger, the cred-scope decision, and a migration path. No code in the advisor pass.
coilyco-ops added
P3
and removed
P2
labels 2026-07-10 09:00:43 +00:00
coilyco-ops added
P4
and removed
P3
labels 2026-07-14 06:50:32 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilyco-flight-deck/ward#545
No description provided.