diff --git a/plans/mas-tem-relay-smtp.md b/plans/mas-tem-relay-smtp.md new file mode 100644 index 0000000..47f1550 --- /dev/null +++ b/plans/mas-tem-relay-smtp.md @@ -0,0 +1,121 @@ +--- +id: mas-tem-relay-smtp +demand_source: mail-address-semantics/workplans/MAS-WP-0003-T03 +consumer_repo: mail-address-semantics +credential_type: openbao-kv-founder-provision +status: draft +approved_by: null +approved_at: null +created: "2026-10-18" +updated: "2026-10-18" +--- + +# Construction plan: MAS live-test TEM SMTP relay credential + +## 1. Demand + +`MAS-WP-0003-T03` runs a temporary live-test MX (`mas/mas-mx`) on +railiance01. It sends service replies through Scaleway Transactional Email +at `[smtp.tem.scaleway.com]:587`, because outbound port 25 is blocked on the +node. The MX needs one SMTP credential: `username` (the Scaleway project ID, +which is not secret) and `password` (a Scaleway API secret key). The founder +types the value into the OpenBao UI. ops-mason builds an empty home and a +read path into namespace `mas`, delivered as Secret `mas-relay`, which the MX +mounts optionally at `/etc/mas-relay`. The lane is temporary: it is removed +with the `mas` namespace when MAS-WP-0003 closes. + +Requested by hub message `14bdd217` (2026-10-18). The request suggested +`kv/mas/tem-relay`, a ClusterSecretStore `openbao-mas` and an ESO token. +This plan keeps the shape but adapts it to the current conventions (§3). + +## 2. Existing-structure survey + +Checked 2026-10-18 from repo sources only. **Live survey pending:** no +`ops-mason-survey` grant was active (`bao-session.sh status`: none). Run +before review: + +```bash +./scripts/plan-survey.py --kv-path platform/workloads/mas/tem-relay \ + --policy workload-kv-read-mas-tem-relay \ + --k8s-role external-secrets-mas-tem-relay \ + --consumer mail-address-semantics --keyword tem --keyword smtp +``` + +- **Catalog** (`ops-warden/registry/routing/catalog.yaml`): no entry for + `mas`, TEM or SMTP relay. +- **railiance-platform:** no CCR, policy or store mentions `mas` or + `tem.scaleway`. The latest CCR is `CCR-2026-0050`. +- **Nearest lane:** `openbao-email-connect` (CCR-2026-0010) is a TEM-adjacent + sender for namespace `email-connect`. It is a separate product with its own + Scaleway key. Reusing it would give the throwaway test MX a production + sender's key, so it is not reused. +- **Store pattern:** new lanes use Kubernetes auth bound to one namespace + and one ServiceAccount, with no static ESO token (RPF-WP-0045, + CCR-2026-0050). Older AppRole/token stores, such as + `openbao-backup-object-storage`, are being migrated away from. +- **Does an existing lane already satisfy this?** No (draft; confirm with + the live survey). + +## 3. Proposed changes + +SEC-DSM §37: + +- **Q1** Can the operation use identity directly? No. TEM SMTP + authenticates only with username/password. +- **Q2** Can the target accept federated identity? No. TEM SMTP has no + federation. +- **Q3** Can the target issue an ephemeral credential? Not viably. Scaleway + API keys can carry an expiry, but adding an issuer for a temporary test + lane would be issuance for show (`DSM-TRANS-003`). Instead the founder sets + the key's own Scaleway expiry to the end of MAS-WP-0003. +- **Q4** Can an existing static credential be rotated automatically? No + automated rotation for a lane this short-lived. +- **Q5** Must a persistent static credential exist? Yes, for the life of + MAS-WP-0003 only. This is §5 level "vaulted static secret". + +**Credential facts:** + +| Field | Value | +|---|---| +| Owner | founder (Scaleway IAM) | +| Consumer | `mas/mas-mx` | +| Authority | Scaleway IAM API key on a dedicated application with only the Transactional Email permission set, on the TEM project | +| Delivery | ESO → Secret `mas/mas-relay` | +| Copies | OpenBao KV, plus one Kubernetes Secret (a delivery copy, not the authority) | +| Rotation | Replace the KV version; ESO refreshes | +| Revocation | Delete the API key in Scaleway, then tear down (rows 6–7 below) | +| Detection | TEM sending logs and the OpenBao audit log for reads of the path | +| What would eliminate it | Removing the MX, or an MTA that relays through `email-connect`'s API instead of SMTP | + +| # | Action | Object | Reuse-vs-new rationale | +|---|---|---|---| +| 1 | create | KV v2 `platform/workloads/mas/tem-relay`, fields `username`, `password` (placeholder `xxx`) | No existing home (§2). This follows the `platform/workloads//` convention, not `kv/` | +| 2 | create | policy `workload-kv-read-mas-tem-relay`: `read` on `platform/data/workloads/mas/tem-relay` only | Single-path ESO reader; no metadata read needed | +| 3 | create | Kubernetes auth role `external-secrets-mas-tem-relay`: SA `mas-tem-relay-eso`, ns `mas`, audience `openbao`, ttl/max 15m, `token_no_default_policy` | Current pattern (CCR-2026-0050), with no static ESO token to deliver or expire | +| 4 | create (consumer repo) | ServiceAccount `mas-tem-relay-eso`, **namespaced** SecretStore `openbao-mas-tem-relay`, ExternalSecret `mas-relay` (keys `username`, `password`), all in ns `mas` | Namespaced instead of a ClusterSecretStore, so the store is deleted with the namespace | +| 5 | create (railiance-platform) | CCR-2026-00NN `workload-kv-read` for rows 1–3 | Platform allocates the CCR and applies it through the delegated applier | +| 6 | tear-down (at MAS-WP-0003 close) | auth role, policy, KV path (`metadata delete`) | Cluster-scoped OpenBao objects do not go away with the namespace | +| 7 | tear-down (founder) | Scaleway API key | Revokes the authority itself | + +No catalog entry: the lane is temporary and has a single consumer. + +## 4. Review notes + +- **Naming:** `mas-tem-relay` is used for the path, policy, role, SA and + store, so one grep finds every object to retire. Secret `mas-relay` keeps + the name the consumer asked for. +- **TTL/scoping:** 15m role TTL matches CCR-2026-0050. The policy covers one + data path and no metadata. Binding is to exact SA and namespace claims. +- **Redundancy:** does not reuse the `email-connect` sender key (§2). +- **Deviation from the request:** it asked for a ClusterSecretStore + `openbao-mas` and an ESO token. Both are replaced, by Kubernetes auth + (DSM-K8S-001, projected identity before a broker token) and by a + namespaced store (easier to retire). The consumer applies rows 4 itself. +- **Secret values:** ops-mason neither reads nor writes them. The policy + grants `read` only to the ESO role. +- **Open:** live survey (§2); CCR number from railiance-platform; + `bound_claims_confirmed` after the SA exists. + +## 5. Executive summary + +*(Generated after review.)* diff --git a/workplans/MASON-WP-0014-mas-tem-relay-smtp.md b/workplans/MASON-WP-0014-mas-tem-relay-smtp.md new file mode 100644 index 0000000..2a5d385 --- /dev/null +++ b/workplans/MASON-WP-0014-mas-tem-relay-smtp.md @@ -0,0 +1,64 @@ +--- +id: MASON-WP-0014 +type: workplan +title: "Build the temporary MAS live-test TEM SMTP relay lane" +domain: infotech +repo: ops-mason +status: proposed +owner: claude +topic_slug: netkingdom-security-architecture +created: "2026-10-18" +updated: "2026-10-18" +flavor: implementation +depends_on: [] +--- + +# MAS TEM SMTP relay lane + +Demand: hub message `14bdd217` from mail-address-semantics (MAS-WP-0003-T03). +Plan: `plans/mas-tem-relay-smtp.md`. Temporary; retires with namespace `mas`. + +## Draft the construction plan + +```task +id: MASON-WP-0014-T01 +status: done +priority: high +``` + +Drafted `plans/mas-tem-relay-smtp.md` (status `draft`) and replied to the +requester with the proposed path, role and store names. + +## Live survey and self-review + +```task +id: MASON-WP-0014-T02 +status: wait +priority: high +``` + +Needs an `ops-mason-survey` grant (`bao-session.sh grant MASON-WP-0014-T02`). +Run `plan-survey.py` as given in plan §2, then set the plan to `reviewed`. + +## CCR and founder approval + +```task +id: MASON-WP-0014-T03 +status: wait +priority: high +``` + +railiance-platform allocates the CCR for plan rows 1–3. The founder approves +the plan and the CCR, applies them through the delegated applier, and fills +`password` in the OpenBao UI. + +## Verify delivery and record teardown + +```task +id: MASON-WP-0014-T04 +status: wait +priority: medium +``` + +Confirm KV metadata exists and that Secret `mas/mas-relay` syncs (names only). +Record the teardown steps (plan rows 6–7) as a residual against MAS-WP-0003 close.