5.1 KiB
5.1 KiB
Surface.Secrets Schema (Security-approved)
Status: Final · 2025-11-23 Owners: Security Guild · Scanner Guild · Zastava Guild Related tasks: SURFACE-SECRETS-01/02/03/04/05/06, SCANNER-SECRETS-03, ZASTAVA-SECRETS-01/02
Purpose
Canonical schema for declaring and validating secret providers used by Surface consumers (Scanner, Zastava, Scheduler). Supersedes the draft notes in surface-secrets.md §4–5 and unblocks validation + integration tasks.
Configuration Document
Location: Surface:Secrets (appsettings, env, or offline kit manifest). JSON Schema (v2020-12):
{
"$id": "https://stellaops/policy/surface-secrets.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"required": ["provider", "providers"],
"properties": {
"provider": {"type": "string", "enum": ["kubernetes", "file", "inline"], "description": "active provider id"},
"fallbackProvider": {"type": "string", "enum": ["kubernetes", "file", "inline"], "nullable": true},
"providers": {
"type": "object",
"properties": {
"kubernetes": {
"type": "object",
"required": ["namespace", "prefix"],
"properties": {
"namespace": {"type": "string", "pattern": "^[a-z0-9]([-a-z0-9]*[a-z0-9])?$"},
"prefix": {"type": "string", "default": "surface-"},
"ttlSeconds": {"type": "integer", "minimum": 30, "default": 600},
"allowServiceAccountFallback": {"type": "boolean", "default": false}
}
},
"file": {
"type": "object",
"required": ["root"],
"properties": {
"root": {"type": "string", "pattern": "^/.+"},
"format": {"type": "string", "enum": ["json", "yaml"], "default": "json"},
"permissions": {"type": "string", "enum": ["0600"], "default": "0600"}
}
},
"inline": {
"type": "object",
"properties": {
"payloadBase64": {"type": "string", "contentEncoding": "base64"},
"enabled": {"type": "boolean", "default": false}
}
}
},
"additionalProperties": false
},
"requiredSecrets": {
"type": "array",
"items": {
"type": "object",
"required": ["tenant", "component", "secretType"],
"properties": {
"tenant": {"type": "string"},
"component": {"type": "string"},
"secretType": {"type": "string", "enum": ["cas-access", "registry", "attestation", "tls"]},
"name": {"type": "string"}
}
},
"uniqueItems": true
}
},
"additionalProperties": false
}
Secret Object Shape
Secrets resolved by providers must conform to one of:
cas-access:{ "accessKey": "...", "secretKey": "...", "sessionToken": "..." }registry:{ "username": "...", "password": "..." }or{ "token": "..." }attestation:{ "privateKeyPem": "...", "keyId": "...", "rekorApiKey": "..." }tls:{ "certPem": "...", "keyPem": "..." }Binary values may be base64 but must decode to UTF-8 cleanly; otherwise return base64 string and markisBinary: truein handle metadata.
Determinism & Validation
- Deterministic ordering: providers resolved in request order; when multiple secrets share tenant/component/type, choose lexicographically smallest
namethen earliestingestedAtmetadata. Surface.Validationcodes:SURFACE_SECRET_PROVIDER_UNKNOWN,SURFACE_SECRET_MISSING,SURFACE_SECRET_STALE,SURFACE_SECRET_FORMAT_INVALID(new).- Validators must reject world-readable files (
permissions != 0600) and inline payloads whenenabled=false(air-gapped safety).
Offline / Air-Gap Profile
- Offline kit must ship
offline/secrets/manifest.jsonmatching this schema with hashes for each secret blob (SHA-256 hex) andcreatedAtin UTC. - Importer scripts map manifest entries to file provider layout:
<root>/<tenant>/<component>/<secretType>/<name>.json. - No external network calls during validation or resolution.
Examples
Minimal Kubernetes config:
{
"provider": "kubernetes",
"providers": {"kubernetes": {"namespace": "stellaops-runtime", "prefix": "surface-"}},
"requiredSecrets": [
{"tenant": "acme", "component": "scanner-worker", "secretType": "cas-access"},
{"tenant": "acme", "component": "scanner-worker", "secretType": "registry", "name": "primary"}
]
}
File provider (offline):
{
"provider": "file",
"providers": {"file": {"root": "/etc/stellaops/secrets", "format": "json"}},
"requiredSecrets": []
}
Implementation Notes
- Aligns with design doc
surface-secrets.md; this file is the authoritative schema for SURFACE-SECRETS-01/02/03. ISurfaceSecretProvidermust emit metadata{ "provider": "kubernetes", "ageDays": <int>, "isBinary": <bool> }for observability.- Add JSON Schema to
schemas/surface/surface-secrets.schema.json(mirrored in Offline Kit) when code lands.
Acceptance
- SECURITY sign-off requires adherence to this schema and validation rules.
- SURFACE-SECRETS-01 moves to DONE; SURFACE-SECRETS-02 to TODO (implementation); SURFACE-VAL-01 unblocks because schema is defined.