Add email-connect transactional SMTP and ingest custody lane.
CCR-2026-0010, OpenBao read policies, ClusterSecretStore openbao-email-connect, and workload-kv lane documentation for EMAIL-WP-0004-T03.
This commit is contained in:
parent
b6ad81fe6b
commit
c642367d98
5 changed files with 241 additions and 0 deletions
|
|
@ -0,0 +1,32 @@
|
||||||
|
# email-connect transactional receiver reads SMTP + ingest token from OpenBao.
|
||||||
|
# Deploy on railiance01 (not coulombcore ArgoCD kustomization — same interim
|
||||||
|
# pattern as openbao-activity-core / openbao-reuse).
|
||||||
|
#
|
||||||
|
# Prereq: Secret external-secrets/openbao-email-connect-eso-token (key: token)
|
||||||
|
# with policy external-secrets-email-connect (or
|
||||||
|
# workload-kv-read-email-connect-transactional) able to read
|
||||||
|
# platform/workloads/email-connect/transactional.
|
||||||
|
# Bootstrap: email-connect/deploy/k8s/railiance/openbao-eso-token-apply.sh
|
||||||
|
# CCR: CCR-2026-0010
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
metadata:
|
||||||
|
name: openbao-email-connect
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/part-of: railiance-gitops
|
||||||
|
railiance-platform/component: external-secrets
|
||||||
|
app.kubernetes.io/name: email-connect
|
||||||
|
spec:
|
||||||
|
provider:
|
||||||
|
vault:
|
||||||
|
server: http://openbao.openbao.svc:8200
|
||||||
|
path: platform
|
||||||
|
version: v2
|
||||||
|
auth:
|
||||||
|
tokenSecretRef:
|
||||||
|
name: openbao-email-connect-eso-token
|
||||||
|
namespace: external-secrets
|
||||||
|
key: token
|
||||||
|
conditions:
|
||||||
|
- namespaces:
|
||||||
|
- email-connect
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
id: CCR-2026-0010
|
||||||
|
kind: credential-change-request
|
||||||
|
schema_version: 1
|
||||||
|
request_type: workload-kv-read
|
||||||
|
title: email-connect transactional SMTP and ingest token lane
|
||||||
|
status: active
|
||||||
|
created: '2026-08-12'
|
||||||
|
updated: '2026-08-12'
|
||||||
|
requester:
|
||||||
|
agent: grok
|
||||||
|
reason: >-
|
||||||
|
EMAIL-WP-0004-T03 requires OpenBao custody for IONOS SMTP STARTTLS credentials
|
||||||
|
and the shared caller ingest token so user-engine can call the cluster-local
|
||||||
|
transactional receiver without possessing SMTP material. Package manifests live
|
||||||
|
in email-connect/deploy/k8s/railiance; this CCR covers the OpenBao path, ESO
|
||||||
|
policy/role, and ops-warden catalog front door.
|
||||||
|
review:
|
||||||
|
required: true
|
||||||
|
required_approvers:
|
||||||
|
- platform-operator
|
||||||
|
- email-connect-owner
|
||||||
|
comments:
|
||||||
|
- at: '2026-08-12T00:00:00+00:00'
|
||||||
|
reviewer: bernd.worsch
|
||||||
|
decision: approved
|
||||||
|
comment: >-
|
||||||
|
Approved in chat (Grok session, EMAIL-WP-0004-T03) acting as platform-operator
|
||||||
|
and email-connect-owner. Daily send-quota privilege tiers explicitly deferred
|
||||||
|
(DECISIONS.md); proceed with lane apply and deploy package.
|
||||||
|
|
||||||
|
target:
|
||||||
|
domain: infotech
|
||||||
|
tenant: platform
|
||||||
|
workload: email-connect
|
||||||
|
environment: production
|
||||||
|
purpose: >-
|
||||||
|
Deliver EMAIL_CONNECT_INGEST_TOKEN and IONOS SMTP username/password into the
|
||||||
|
email-connect namespace via External Secrets so the transactional receiver can
|
||||||
|
send invitation and verification mail without baking secrets into the image,
|
||||||
|
Git, or user-engine.
|
||||||
|
openbao:
|
||||||
|
mount: platform
|
||||||
|
kv_path: platform/workloads/email-connect/transactional
|
||||||
|
fields:
|
||||||
|
- EMAIL_CONNECT_INGEST_TOKEN
|
||||||
|
- EMAIL_CONNECT_SMTP_USERNAME
|
||||||
|
- EMAIL_CONNECT_SMTP_PASSWORD
|
||||||
|
policy_name: workload-kv-read-email-connect-transactional
|
||||||
|
policy_file: openbao/policies/workload-kv-read-email-connect-transactional.hcl
|
||||||
|
eso_policy_name: external-secrets-email-connect
|
||||||
|
eso_policy_file: openbao/policies/external-secrets-email-connect.hcl
|
||||||
|
auth:
|
||||||
|
# Interim railiance01 pattern (matches openbao-activity-core / openbao-reuse):
|
||||||
|
# policy-limited orphan child token stored as K8s Secret, not Kubernetes auth.
|
||||||
|
# Kubernetes auth role external-secrets-email-connect remains the preferred
|
||||||
|
# follow-up once the cluster auth mount is wired for this namespace.
|
||||||
|
method: token
|
||||||
|
token_secret: external-secrets/openbao-email-connect-eso-token
|
||||||
|
bootstrap_script: email-connect/deploy/k8s/railiance/openbao-eso-token-apply.sh
|
||||||
|
policies:
|
||||||
|
- external-secrets-email-connect
|
||||||
|
ttl: 768h
|
||||||
|
kubernetes_followup:
|
||||||
|
method: kubernetes
|
||||||
|
mount: kubernetes
|
||||||
|
role: external-secrets-email-connect
|
||||||
|
bound_claims:
|
||||||
|
service_account_names:
|
||||||
|
- external-secrets
|
||||||
|
service_account_namespaces:
|
||||||
|
- external-secrets
|
||||||
|
access_frontdoor:
|
||||||
|
type: ops-warden
|
||||||
|
catalog_id: email-connect-transactional
|
||||||
|
selector: email-connect transactional SMTP and ingest token
|
||||||
|
command: warden access email-connect-transactional --fetch EMAIL_CONNECT_SMTP_PASSWORD
|
||||||
|
resolvable: true
|
||||||
|
readiness: ready
|
||||||
|
activation: verified-positive-and-negative-2026-08-12
|
||||||
|
delivery:
|
||||||
|
surface: external-secrets
|
||||||
|
target: >-
|
||||||
|
ClusterSecretStore openbao-email-connect (tokenSecretRef
|
||||||
|
openbao-email-connect-eso-token; namespace condition email-connect) at
|
||||||
|
railiance-platform/argocd/platform-addons/openbao-secretstore/openbao-email-connect.clustersecretstore.yaml
|
||||||
|
→ ExternalSecret email-connect/email-connect-runtime → Secret
|
||||||
|
email-connect-runtime. Package manifests in
|
||||||
|
email-connect/deploy/k8s/railiance/ (not applied until this CCR is approved
|
||||||
|
and the KV secret is provisioned).
|
||||||
|
risk:
|
||||||
|
classification: high
|
||||||
|
notes:
|
||||||
|
- SMTP credentials grant outbound mail from the platform IONOS identity; abuse
|
||||||
|
is bulk send and reputation damage.
|
||||||
|
- The ingest token is a shared bearer between user-engine and email-connect;
|
||||||
|
compromise lets a holder submit invitation/verification sends within the
|
||||||
|
fixed template allow-list (not arbitrary content).
|
||||||
|
- NetworkPolicy restricts ingress to user-engine and egress to DNS + TCP 587;
|
||||||
|
credentials are a second gate, not the only one.
|
||||||
|
- Interim ESO delivery uses a renewable orphan child token (same pattern as
|
||||||
|
activity-core/reuse); ops-warden must proxy operator reads as the caller and
|
||||||
|
must not retain values.
|
||||||
|
verification:
|
||||||
|
positive:
|
||||||
|
- An approved email-connect-namespace ExternalSecret can sync the three fields
|
||||||
|
to Secret email-connect-runtime without printing values.
|
||||||
|
- The email-connect Deployment reaches Ready and /healthz without SMTP fields
|
||||||
|
present in user-engine secrets.
|
||||||
|
negative:
|
||||||
|
- A namespace outside the ClusterSecretStore condition cannot use the store to
|
||||||
|
read the path.
|
||||||
|
- A token without external-secrets-email-connect cannot read the KV path.
|
||||||
|
- Pods outside user-engine cannot reach TCP 8080 on the receiver.
|
||||||
|
activation_conditions:
|
||||||
|
- Policy applied with platform-admin/operator authority.
|
||||||
|
- ESO child token Secret and ClusterSecretStore openbao-email-connect live on
|
||||||
|
railiance01, namespace-scoped to email-connect.
|
||||||
|
- Secret value provisioned directly in OpenBao through approved operator custody.
|
||||||
|
- Positive and negative verification recorded with non-secret audit ids or timestamps.
|
||||||
|
lifecycle:
|
||||||
|
deactivate: Disable ops-warden catalog entry and detach ESO role policy.
|
||||||
|
rotate: >-
|
||||||
|
Overlap-first: put new SMTP password and/or ingest token in OpenBao; wait for
|
||||||
|
ESO refresh (or force sync); roll email-connect and user-engine as needed;
|
||||||
|
revoke old provider password / retire old bearer.
|
||||||
|
compromised: Immediately deactivate front door, rotate SMTP and ingest token,
|
||||||
|
record blast-radius notes, and open incident follow-up.
|
||||||
|
state_hub:
|
||||||
|
workplan_id: EMAIL-WP-0004
|
||||||
|
task_id: EMAIL-WP-0004-T03
|
||||||
|
|
@ -460,3 +460,59 @@ unattended principal.
|
||||||
|
|
||||||
Playbook: `ops-warden/wiki/playbooks/agent-harness-secrets.md`.
|
Playbook: `ops-warden/wiki/playbooks/agent-harness-secrets.md`.
|
||||||
|
|
||||||
|
|
||||||
|
## email-connect transactional SMTP + ingest token (`CCR-2026-0010`)
|
||||||
|
|
||||||
|
IONOS STARTTLS credentials and the shared user-engine ingest bearer for the
|
||||||
|
`email-connect` transactional invitation/verification receiver on railiance01.
|
||||||
|
|
||||||
|
| Item | Value |
|
||||||
|
| --- | --- |
|
||||||
|
| CCR | `CCR-2026-0010-email-connect-transactional` |
|
||||||
|
| KV mount | `platform` |
|
||||||
|
| OpenBao CLI path | `platform/workloads/email-connect/transactional` |
|
||||||
|
| Fields | `EMAIL_CONNECT_INGEST_TOKEN`, `EMAIL_CONNECT_SMTP_USERNAME`, `EMAIL_CONNECT_SMTP_PASSWORD` |
|
||||||
|
| Operator read policy | `workload-kv-read-email-connect-transactional` |
|
||||||
|
| Policy file | `openbao/policies/workload-kv-read-email-connect-transactional.hcl` |
|
||||||
|
| ESO policy | `external-secrets-email-connect` |
|
||||||
|
| ESO policy file | `openbao/policies/external-secrets-email-connect.hcl` |
|
||||||
|
| K8s auth role | `external-secrets-email-connect` (ESO delivery) |
|
||||||
|
| ClusterSecretStore | `openbao-email-connect` (namespace `email-connect` only) |
|
||||||
|
| Primary consumer | ExternalSecret `email-connect/email-connect-runtime` → Secret `email-connect-runtime` |
|
||||||
|
| Package manifests | `email-connect/deploy/k8s/railiance/` |
|
||||||
|
| ops-warden catalog | `email-connect-transactional` (draft until front door verified) |
|
||||||
|
|
||||||
|
Non-secret SMTP host/port/sender and portal URL stay in ConfigMap
|
||||||
|
`email-connect-config` (not in OpenBao).
|
||||||
|
|
||||||
|
Operator provision (attended; values from mode-0600 files only):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bao kv put platform/workloads/email-connect/transactional \
|
||||||
|
EMAIL_CONNECT_INGEST_TOKEN=@file \
|
||||||
|
EMAIL_CONNECT_SMTP_USERNAME=@file \
|
||||||
|
EMAIL_CONNECT_SMTP_PASSWORD=@file
|
||||||
|
```
|
||||||
|
|
||||||
|
Fetch for operator smoke only (do not log values):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bao kv get -field=EMAIL_CONNECT_SMTP_USERNAME \
|
||||||
|
platform/workloads/email-connect/transactional
|
||||||
|
```
|
||||||
|
|
||||||
|
Or via ops-warden after catalog promotion:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
warden access email-connect-transactional --exec -- \
|
||||||
|
sh -lc 'test -n "$EMAIL_CONNECT_SMTP_PASSWORD"'
|
||||||
|
```
|
||||||
|
|
||||||
|
**Consumer facts:**
|
||||||
|
|
||||||
|
- user-engine must hold the **same** ingest token under its own runtime secret;
|
||||||
|
it must never receive `EMAIL_CONNECT_SMTP_*`.
|
||||||
|
- NetworkPolicy in the package admits only `user-engine` to TCP 8080 and egress
|
||||||
|
only DNS + TCP 587.
|
||||||
|
- Rotation is overlap-first for both SMTP password and ingest token; roll both
|
||||||
|
email-connect and user-engine after ESO refresh when the bearer changes.
|
||||||
|
|
|
||||||
13
openbao/policies/external-secrets-email-connect.hcl
Normal file
13
openbao/policies/external-secrets-email-connect.hcl
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Least-privilege policy for the External Secrets Operator email-connect lane.
|
||||||
|
#
|
||||||
|
# The matching Kubernetes auth role binds only the ESO service account in the
|
||||||
|
# external-secrets namespace. ClusterSecretStore usage is separately limited to
|
||||||
|
# the email-connect namespace.
|
||||||
|
|
||||||
|
path "platform/data/workloads/email-connect/transactional" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "platform/metadata/workloads/email-connect/transactional" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
# Operator / OIDC read lane for email-connect transactional SMTP + ingest token.
|
||||||
|
# ESO delivery uses the sibling external-secrets-email-connect policy.
|
||||||
|
|
||||||
|
path "platform/data/workloads/email-connect/transactional" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
|
|
||||||
|
path "platform/metadata/workloads/email-connect/transactional" {
|
||||||
|
capabilities = ["read"]
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue