Files
git.stella-ops.org/ops/devops/secrets/surface-secrets-provisioning.md
StellaOps Bot bc0762e97d up
2025-12-09 00:20:52 +02:00

4.1 KiB

Surface.Secrets provisioning playbook (OPS-SECRETS-01)

Audience: DevOps/Ops teams shipping Scanner/Zastava/Orchestrator bundles. Scope: how to provision secrets for the StellaOps.Scanner.Surface.Secrets providers across Kubernetes, Docker Compose, and Offline Kit.

Secret types (handles only)

  • Registry pull creds (CAS / OCI / private feeds)
  • CAS/attestation tokens
  • TLS client certs for Surface.FS / RustFS (optional)
  • Feature flag/token bundles used by Surface.Validation (non-sensitive payloads still go through handles)

All values are referenced via secret:// handles inside service configs; plaintext never enters configs or SBOMs.

Provider matrix

Environment Provider Location Notes
Kubernetes kubernetes Namespace-scoped Secret objects Mount-free: providers read via API using service account; RBAC must allow get/list on the secret names.
Compose (connected) file Host-mounted path (e.g., /etc/stellaops/secrets) Keep per-tenant subfolders; chmod 700 root; avoid embedding in images.
Airgap/Offline Kit file Unpacked bundle surface-secrets/<tenant>/... Bundled as encrypted payloads; decrypt/unpack to the expected directory before first boot.
Tests inline Environment variables or minimal inline JSON Only for unit/system tests; disable in prod (SCANNER_SURFACE_SECRETS_ALLOW_INLINE=false).

Kubernetes workflow

  1. Namespace: choose one per environment (e.g., stellaops-prod).
  2. Secret layout: one K8s Secret per tenant+component to keep RBAC narrow.
apiVersion: v1
kind: Secret
metadata:
  name: scanner-secrets-default
  namespace: stellaops-prod
stringData:
  registry.json: |
    { "type": "registry", "name": "default", "username": "svc", "password": "********", "scopes": ["stella/*"] }
  cas.json: |
    { "type": "cas-token", "name": "default", "token": "********" }
  1. RBAC: service accounts for Scanner Worker/WebService and Zastava Observer/Webhook need get/list on these secrets.
  2. Values: set in Helm via surface.secrets.provider=kubernetes and surface.secrets.namespace=<ns> (already templated in values*.yaml).

Compose workflow

  1. Create secrets directory (default /etc/stellaops/secrets).
  2. Layout per schema (see docs/modules/scanner/design/surface-secrets-schema.md):
/etc/stellaops/secrets/
  tenants/default/registry/default.json
  tenants/default/cas/default.json
  1. Set env in .env files:
SCANNER_SURFACE_SECRETS_PROVIDER=file
SCANNER_SURFACE_SECRETS_ROOT=/etc/stellaops/secrets
SCANNER_SURFACE_SECRETS_NAMESPACE=
SCANNER_SURFACE_SECRETS_ALLOW_INLINE=false
ZASTAVA_SURFACE_SECRETS_PROVIDER=${SCANNER_SURFACE_SECRETS_PROVIDER}
ZASTAVA_SURFACE_SECRETS_ROOT=${SCANNER_SURFACE_SECRETS_ROOT}
  1. Ensure docker-compose mounts the secrets path read-only to the services that need it. Use SURFACE_SECRETS_HOST_PATH to point at the decrypted bundle on the host (defaults to ./offline/surface-secrets in the Compose profiles).

Offline Kit workflow

  • The offline kit already ships encrypted surface-secrets bundles (see docs/24_OFFLINE_KIT.md).
  • Operators must: (a) decrypt using the provided key, (b) place contents under /etc/stellaops/secrets (or override *_SURFACE_SECRETS_ROOT), (c) keep permissions 700/600.
  • Set *_SURFACE_SECRETS_PROVIDER=file and root path envs as in Compose; Kubernetes provider is not available offline.

Validation & observability

  • Surface.Validation will fail readiness if required secrets are missing or malformed.
  • Metrics/Logs: look for surface.secrets.* issue codes; readiness should fail on Error severities.
  • For CI smoke: run service with SURFACE_SECRETS_ALLOW_INLINE=true and inject test secrets via env for deterministic integration tests.

Quick checklist

  • Provider selected per environment (kubernetes/file/inline)
  • Secrets directory or namespace populated per schema
  • RBAC (K8s) or file permissions (Compose/offline) locked down
  • Env variables set for both Scanner (SCANNER_*) and Zastava (ZASTAVA_* prefixes)
  • Readiness wired to Surface.Validation so missing secrets block rollout