ARTIFACT-STORE-WP-0007 D7.3: STS credential vending assessment for NetKingdom

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-02 11:15:45 +02:00
parent e1dd365586
commit f4a7b92543
2 changed files with 109 additions and 1 deletions

View File

@@ -0,0 +1,95 @@
# STS Credential Vending Assessment for NetKingdom
Status: assessment complete (ARTIFACT-STORE-WP-0007 D7.3)
Date: 2026-07-02
Upstream baseline: `net-kingdom/docs/object-storage-sts-credential-vending.md`
(NK-WP-0007, 2026-05-18) — this assessment specializes that architecture for
artifact-store and records the current-state inventory it asks for.
## 1. Current object-storage credential inventory
| Consumer | Credential path today | Temporary-credential ready? |
| --- | --- | --- |
| artifact-store S3 backend | Static key pair via `ARTIFACTSTORE_S3_ACCESS_KEY_REF` / `ARTIFACTSTORE_S3_SECRET_KEY_REF` (file/env refs, no plaintext in config) | **No**`S3BackendConfig` has no `session_token` field and `aioboto3.Session` is constructed without `aws_session_token` (`src/artifactstore/storage/backends/s3.py`); STS credentials cannot be consumed until D7.4 lands |
| NetKingdom CNPG backups (`net-kingdom-pg-backup-s3`) | Documented as a static `kubectl create secret generic --from-literal` key pair in `sso-mfa/k8s/postgresql/README.md`; **not yet provisioned** — backups are parked "until object storage is available" | No — static by design today; should adopt the vending flow (or at minimum an ExternalSecret lane) when object storage is provisioned |
| MinIO compatibility harness (`make test-minio` / `test-minio-local`) | One-run generated throwaway root credentials, local container only | N/A — dev double, never a production path |
No other live S3/MinIO credential consumers were found in net-kingdom or
artifact-store. The most important inventory conclusion: **nothing is
production-live yet**, so the vending architecture can be adopted without a
migration burden — the CNPG backup lane should start on the target pattern
rather than shipping static keys first.
## 2. Can Keycloak / Authelia / local-identity act as the OIDC IdP for MinIO `AssumeRoleWithWebIdentity`?
MinIO's STS `AssumeRoleWithWebIdentity` accepts any OIDC JWT whose issuer is
configured in MinIO's identity-provider settings and whose claims map to a
MinIO policy. Assessment per NetKingdom issuer:
- **key-cape (lightweight mode)** — yes, and it is the preferred first
issuer: it already issues IAM Profile v0.2 tokens with OIDC discovery +
JWKS (proven by the Core Hub verifier integration test, CUST-WP-0025-T03).
MinIO consumes the discovery URL directly.
- **Keycloak (expanded mode)** — yes; standard, widely documented MinIO OIDC
pairing. This is the production/enterprise-federation issuer per the
NetKingdom baseline; not yet deployed (NK-WP-0001 Keycloak was cancelled as
superseded, so key-cape leads until enterprise federation is needed).
- **Authelia** — technically an OIDC provider, but it is the NetKingdom
session/portal SSO layer and does not issue IAM Profile v0.2 claims
(`tenant`, `principal_type`, `assurance`). Using it as a storage IdP would
bypass the IAM Profile contract. **Do not use** as the vending issuer.
- **local-identity** — dev/bootstrap contexts only, per the baseline's
local-dev restrictions: only explicitly configured dev vending instances
may accept it, and minted credentials must be confined to local/sandbox
object stores.
Important nuance from the baseline: consumers should not hit MinIO STS
directly with raw IdP tokens. The **credential-vending service** verifies the
IAM Profile and asks **flex-auth** for the decision first; MinIO's own
claim-to-policy mapping is then deliberately coarse (one policy per
tenant/prefix class), keeping authorization in flex-auth rather than in MinIO
policy JSON.
## 3. Target architecture (artifact-store specialization)
Follow the NetKingdom baseline flow (IAM Profile token → vending service →
flex-auth decision → backend exchange → temporary credentials). The
artifact-store-specific bindings:
| Element | Binding |
| --- | --- |
| Issuer | key-cape lightweight mode first; Keycloak expanded mode when enterprise federation arrives; local-identity for sandbox only |
| Audience | the credential-vending service audience (not artifact-store, not MinIO) — `aud` per IAM Profile v0.2 |
| Role/policy mapping | flex-auth vocabulary from the baseline: tenant, protected-system=`object-storage`, bucket, prefix, actions (`read`/`write`/`list`), TTL; MinIO side keeps one coarse policy per tenant-prefix class |
| Expiration | default lease 1560 min with refresh-before-expiry + jitter in the consumer; TTL bounds enforced by flex-auth (proven pattern: `ttl_out_of_bounds` denial in the FLEX-WP-0007 smoke) |
| Revocation | short TTLs are the primary control; for immediate cuts, disable the MinIO policy or the vending grant; OpenBao lease revocation applies only to broker-held parent material |
| Audit | vending service emits the baseline's audit event (issuer, sub, tenant, decision id, backend, TTL, non-secret request ids); OpenBao audit covers parent-credential access |
| Break-glass | platform-control-plane path per the baseline: short-lived, post-event review record mandatory; never a tenant-plane shortcut |
### artifact-store consumer work (feeds D7.4)
1. Add `session_token: str | None` to `S3BackendConfig` and pass
`aws_session_token` into `aioboto3.Session`.
2. Add `ARTIFACTSTORE_S3_SESSION_TOKEN_REF` (and optionally
`ARTIFACTSTORE_S3_CREDENTIAL_EXPIRATION_REF`) alongside the existing refs,
with atomic refresh of all three values.
3. Support the delivery modes from the baseline in priority order: mounted
files refreshed by a controller/sidecar first (fits the current `_REF`
file pattern), `credential_process` for CLI/batch use later.
### Sequencing recommendation
1. D7.4: session-token consumer support (small, local, no deployment gate).
2. Vending service + flex-auth vocabulary (NetKingdom/flex-auth owned;
artifact-store is a consumer, not the owner).
3. Wire the CNPG backup lane and artifact-store deployment to the vending
flow when Railiance provisions the production object store — do not ship
static production keys in the interim.
## Non-goals confirmed
- artifact-store does not own identity, authorization, or secret custody
(baseline ownership table).
- OpenBao is not the object-storage authorization engine; it holds parent
material and audit only.
- MinIO policy JSON is not the canonical tenant policy model; flex-auth is.

View File

@@ -137,7 +137,7 @@ Completed 2026-07-02:
```task ```task
id: ARTIFACT-STORE-WP-0007-T003 id: ARTIFACT-STORE-WP-0007-T003
status: todo status: done
priority: high priority: high
state_hub_task_id: "d3d5c4c1-d3b2-4163-b99d-1b08f90566d1" state_hub_task_id: "d3d5c4c1-d3b2-4163-b99d-1b08f90566d1"
``` ```
@@ -152,6 +152,19 @@ Acceptance:
token audience, role/policy mapping, expiration, revocation, audit, token audience, role/policy mapping, expiration, revocation, audit,
and break-glass behavior. and break-glass behavior.
Completed 2026-07-02: added `docs/sts-credential-vending-assessment.md`,
specializing the NetKingdom baseline (`net-kingdom/docs/object-storage-sts-
credential-vending.md`, NK-WP-0007) for artifact-store. Inventory found no
production-live object-storage credentials yet (artifact-store static-ref
bridge, CNPG backup lane parked pre-provisioning), confirmed key-cape/Keycloak
as viable MinIO `AssumeRoleWithWebIdentity` issuers (Authelia rejected —
no IAM Profile claims; local-identity sandbox-only), and bound the target
architecture: vending-service audience, flex-auth decision vocabulary, 1560
min leases with refresh jitter, audit event shape, and break-glass rules.
Key code finding for D7.4: `S3BackendConfig` lacks `session_token` and the
`aioboto3.Session` omits `aws_session_token`, so STS credentials cannot be
consumed until that lands.
## D7.4 - Artifact-Store Temporary Credential Support ## D7.4 - Artifact-Store Temporary Credential Support
```task ```task