feat(docs): Add comprehensive documentation for Vexer, Vulnerability Explorer, and Zastava modules

- Introduced AGENTS.md, README.md, TASKS.md, and implementation_plan.md for Vexer, detailing mission, responsibilities, key components, and operational notes.
- Established similar documentation structure for Vulnerability Explorer and Zastava modules, including their respective workflows, integrations, and observability notes.
- Created risk scoring profiles documentation outlining the core workflow, factor model, governance, and deliverables.
- Ensured all modules adhere to the Aggregation-Only Contract and maintain determinism and provenance in outputs.
This commit is contained in:
2025-10-30 00:09:39 +02:00
parent 3154c67978
commit 7b5bdcf4d3
503 changed files with 16136 additions and 54638 deletions

View File

@@ -0,0 +1,22 @@
# Signer agent guide
## Mission
Signer validates callers, enforces Proof-of-Entitlement, and produces signed DSSE bundles for SBOMs, reports, and exports.
## Key docs
- [Module README](./README.md)
- [Architecture](./architecture.md)
- [Implementation plan](./implementation_plan.md)
- [Task board](./TASKS.md)
## How to get started
1. Open ../../implplan/SPRINTS.md and locate the stories referencing this module.
2. Review ./TASKS.md for local follow-ups and confirm status transitions (TODO → DOING → DONE/BLOCKED).
3. Read the architecture and README for domain context before editing code or docs.
4. Coordinate cross-module changes in the main /AGENTS.md description and through the sprint plan.
## Guardrails
- Honour the Aggregation-Only Contract where applicable (see ../../ingestion/aggregation-only-contract.md).
- Preserve determinism: sort outputs, normalise timestamps (UTC ISO-8601), and avoid machine-specific artefacts.
- Keep Offline Kit parity in mind—document air-gapped workflows for any new feature.
- Update runbooks/observability assets when operational characteristics change.

View File

@@ -0,0 +1,30 @@
# StellaOps Signer
Signer validates callers, enforces Proof-of-Entitlement, and produces signed DSSE bundles for SBOMs, reports, and exports.
## Responsibilities
- Enforce plan quotas and PoE before signing artifacts.
- Support keyless and keyful signing backends.
- Emit DSSE payloads consumed by Attestor and downstream bundles.
- Maintain audit trails for all signing operations.
## Key components
- `StellaOps.Signer` service host.
- Crypto providers under `StellaOps.Cryptography.*`.
## Integrations & dependencies
- Authority for OpTok validation.
- Attestor for transparency logging.
- Export Center and CLI for artifact signing flows.
## Operational notes
- Key management via Authority/DevOps runbooks.
- Metrics for signing latency/throttle states.
- Offline kit integration for signature verification.
## Backlog references
- SIG docs/tasks in ../../TASKS.md (e.g., DOCS-SIG-26-006).
## Epic alignment
- **Epic 10 Export Center:** provide signing pipelines, cosign interoperability, and provenance manifests for bundle promotion.
- **Epic 19 Attestor Console:** supply DSSE payloads and Proof-of-Entitlement enforcement feeding attestation workflows described in `docs/modules/attestor/`.

View File

@@ -0,0 +1,9 @@
# Task board — Signer
> Local tasks should link back to ./AGENTS.md and mirror status updates into ../../TASKS.md when applicable.
| ID | Status | Owner(s) | Description | Notes |
|----|--------|----------|-------------|-------|
| SIGNER-DOCS-0001 | DOING (2025-10-29) | Docs Guild | Validate that ./README.md aligns with the latest release notes. | See ./AGENTS.md |
| SIGNER-OPS-0001 | TODO | Ops Guild | Review runbooks/observability assets after next sprint demo. | Sync outcomes back to ../../TASKS.md |
| SIGNER-ENG-0001 | TODO | Module Team | Cross-check implementation plan milestones against ../../implplan/SPRINTS.md. | Update status via ./AGENTS.md workflow |

View File

@@ -0,0 +1,420 @@
# component_architecture_signer.md — **StellaOps Signer** (2025Q4)
> Supports deliverables from Epic10 Export Center and Epic19 Attestor Console.
> **Scope.** Implementationready architecture for the **Signer**: the *only* service allowed to produce **StellaOpsverified** signatures over SBOMs and reports. It enforces **entitlement** (PoE), **release integrity** (scanner provenance), **senderconstrained auth** (DPoP/mTLS), and emits **intoto/DSSE** bundles suitable for **Rekor v2** logging by the Attestor. Includes APIs, data flow, storage, quotas, security, and test matrices.
---
## 0) Mission & boundaries
**Mission.** Convert authenticated signing requests from trusted StellaOps services into **verifiable** DSSE bundles while enforcing **license policy** and **supplychain integrity**.
**Boundaries.**
* **Signer does not push to Rekor** — it returns DSSE to the caller; **Attestor** logs to **Rekor v2**.
* **Signer does not compute PASS/FAIL** — it signs SBOMs/reports produced by Scanner/WebService after backend evaluation.
* **Signer is stateless for hot path** — longterm storage is limited to audit events; all secrets/keys live in KMS/HSM or are ephemeral (keyless).
---
## 1) Responsibilities (contract)
1. **Authenticate** caller with **OpTok** (Authority OIDC, DPoP or mTLSbound).
2. **Authorize** scopes (`signer.sign`) + audience (`aud=signer`) + tenant/installation.
3. **Validate entitlement** via **PoE** (ProofofEntitlement) against Cloud Licensing `/license/introspect`.
4. **Verify release integrity** of the **scanner** image digest presented in the request: must be **cosignsigned** by StellaOps release key, discoverable via **OCI Referrers API**.
5. **Enforce plan & quotas** (concurrency/QPS/artifact size/rate caps).
6. **Mint signing identity**:
* **Keyless** (default): get a shortlived X.509 cert from **Fulcio** using the Signers OIDC identity and sign the DSSE.
* **Keyful** (optional): sign with an HSM/KMS key.
7. **Return DSSE bundle** (subject digests + predicate + cert chain or KMS key id).
8. **Audit** every decision; expose metrics.
---
## 2) External dependencies
* **Authority** (onprem OIDC): validates OpToks (JWKS/introspection) and DPoP/mTLS.
* **Licensing Service (cloud)**: `/license/introspect` to verify PoE (active, claims, expiry, revocation).
* **Fulcio** (Sigstore) *or* **KMS/HSM**: to obtain certs or perform signatures.
* **OCI Registry (Referrers API)**: to verify **scanner** image release signature.
* **Attestor**: downstream service that writes DSSE bundles to **Rekor v2**.
* **Config/state stores**: Redis (caches, rate buckets), Mongo/Postgres (audit log).
---
## 3) API surface (mTLS; DPoP supported)
Base path: `/api/v1/signer`. **All endpoints require**:
* Access token (JWT) from **Authority** with `aud=signer`, `scope=signer.sign`.
* **Sender constraint**: DPoP proof per request or mTLS client cert.
* **PoE** presented as either:
* **Client TLS cert** (if PoE is mTLSstyle) chained to Licensing CA, *or*
* **PoE JWT** (DPoP/mTLSbound) in `X-PoE` header or request body.
### 3.1 `POST /sign/dsse`
Request (JSON):
```json
{
"subject": [
{ "name": "s3://stellaops/images/sha256:.../inventory.cdx.pb",
"digest": { "sha256": "..." } }
],
"predicateType": "https://stella-ops.org/attestations/sbom/1",
"predicate": {
"image_digest": "sha256:...",
"stellaops_version": "2.3.1 (2027.04)",
"license_id": "LIC-9F2A...",
"customer_id": "CUST-ACME",
"plan": "pro",
"policy_digest": "sha256:...", // optional for final reports
"views": ["inventory", "usage"],
"created": "2025-10-17T12:34:56Z"
},
"scannerImageDigest": "sha256:sc-web-or-worker-digest",
"poe": {
"format": "jwt", // or "mtls"
"value": "eyJhbGciOi..." // PoE JWT when not using mTLS PoE
},
"options": {
"signingMode": "keyless", // "keyless" | "kms"
"expirySeconds": 600, // cert lifetime hint (keyless)
"returnBundle": "dsse+cert" // dsse (default) | dsse+cert
}
}
```
Response 200:
```json
{
"bundle": {
"dsse": { "payloadType": "application/vnd.in-toto+json", "payload": "<base64>", "signatures": [ ... ] },
"certificateChain": [ "-----BEGIN CERTIFICATE-----...", "... root ..." ],
"mode": "keyless",
"signingIdentity": { "issuer": "https://fulcio.internal", "san": "urn:stellaops:signer", "certExpiry": "2025-10-17T12:44:56Z" }
},
"policy": { "plan": "pro", "maxArtifactBytes": 104857600, "qpsRemaining": 97 },
"auditId": "a7c9e3f2-1b7a-4e87-8c3a-90d7d2c3ad12"
}
```
Errors (RFC7807):
* `401 invalid_token` (JWT/DPoP/mTLS failure)
* `403 entitlement_denied` (PoE invalid/revoked/expired; release year mismatch)
* `403 release_untrusted` (scanner image not Stellasigned)
* `429 plan_throttled` (license plan caps)
* `413 artifact_too_large` (size cap)
* `400 invalid_request` (schema/predicate/type invalid)
* `500 signing_unavailable` (Fulcio/KMS outage)
### 3.2 `GET /verify/referrers?imageDigest=<sha256>`
Checks whether the **image** at digest is signed by **StellaOps release key**.
Response:
```json
{ "trusted": true, "signatures": [ { "type": "cosign", "digest": "sha256:...", "signedBy": "StellaOps Release 2027 Q2" } ] }
```
> **Note:** This endpoint is also used internally by Signer before issuing signatures.
---
## 4) Validation pipeline (hot path)
```mermaid
sequenceDiagram
autonumber
participant Client as Scanner.WebService
participant Auth as Authority (OIDC)
participant Sign as Signer
participant Lic as Licensing Service (cloud)
participant Reg as OCI Registry (Referrers)
participant Ful as Fulcio/KMS
Client->>Sign: POST /sign/dsse (OpTok + DPoP/mTLS, PoE, request)
Note over Sign: 1) Validate OpTok, audience, scope, DPoP/mTLS binding
Sign->>Lic: /license/introspect(PoE)
Lic-->>Sign: { active, claims: {license_id, plan, valid_release_year, max_version}, exp }
Note over Sign: 2) Enforce plan/version window and revocation
Sign->>Reg: Verify scannerImageDigest signed (Referrers + cosign)
Reg-->>Sign: OK with signer identity
Note over Sign: 3) Enforce release integrity
Note over Sign: 4) Enforce quotas (QPS/concurrency/size)
Sign->>Ful: Mint cert (keyless) or sign via KMS
Ful-->>Sign: Cert or signature
Sign-->>Client: DSSE bundle (+cert chain), policy counters, auditId
```
**DPoP nonce dance (when enabled for highvalue ops):**
* If DPoP proof lacks a valid nonce, Signer replies `401` with `WWW-Authenticate: DPoP error="use_dpop_nonce", dpop_nonce="<nonce>"`.
* Client retries with new proof including the nonce; Signer validates nonce and `jti` uniqueness (Redis TTL cache).
---
## 5) Entitlement enforcement (PoE)
* **Accepted forms**:
* **mTLS PoE**: client presents a **PoE client cert** at TLS handshake; Signer validates chain to **Licensing CA** (CA bundle configured) and calls `/license/introspect` with cert thumbprint + serial.
* **JWT PoE**: `X-PoE` bearer token (DPoP/mTLSbound) is validated (sig + `cnf`) locally (Licensing JWKS) and then **introspected** for status and claims.
* **Claims required**:
* `license_id`, `plan` (free|pro|enterprise|gov), `valid_release_year`, `max_version`, `exp`.
* Optional: `tenant_id`, `customer_id`, `entitlements[]`.
* **Enforcements**:
* Reject if **revoked**, **expired**, **plan mismatch** or **release outside window** (`stellaops_version` in predicate exceeds `max_version` or release date beyond `valid_release_year`).
* Apply plan **throttles** (QPS/concurrency/artifact bytes) via tokenbucket in Redis keyed by `license_id`.
---
## 6) Release integrity (scanner provenance)
* **Input**: `scannerImageDigest` representing the actual Scanner component that produced the artifact.
* **Check**:
1. Use **OCI Referrers API** to enumerate signatures of that digest.
2. Verify **cosign** signatures against the configured **StellaOps Release** keyring (keyless Fulcio roots *or* keyful public keys).
3. Optionally require Rekor inclusion for those signatures.
* **Policy**:
* If not signed by an authorized **StellaOps Release** identity → **deny**.
* If signed but **release year** > PoE `valid_release_year`**deny**.
* **Cache**: LRU of digest → verification result (TTL 1030min) to avoid registry thrash.
---
## 7) Signing modes
### 7.1 Keyless (default; Sigstore Fulcio)
* Signer authenticates to **Fulcio** using its onprem OIDC identity (client credentials) and requests a **shortlived cert** (510min).
* Generates **ephemeral keypair**, gets cert for the public key, signs DSSE with the **private key**.
* DSSE **bundle** includes **certificate chain**; verifiers validate to Fulcio root.
### 7.2 Keyful (optional; KMS/HSM)
* Signer uses a configured **KMS** key (AWS KMS, GCP KMS, Azure Key Vault, Vault Transit, or HSM).
* DSSE bundle includes **key metadata** (kid, cert chain if x509).
* Recommended for FIPS/sovereign environments.
---
## 8) Predicates & schema
Supported **predicate types** (extensible):
* `https://stella-ops.org/attestations/sbom/1` (SBOM emissions)
* `https://stella-ops.org/attestations/report/1` (final PASS/FAIL reports)
* `https://stella-ops.org/attestations/vex-export/1` (Excititor exports; optional)
**Validation**:
* JSONSchema per predicate type; **canonical property order**.
* `subject[*].digest` must include `sha256`.
* `predicate.stellaops_version` must parse and match policy windows.
---
## 9) Quotas & throttling
Per `license_id` (from PoE):
* **QPS** (token bucket), **concurrency** (semaphore), **artifact bytes** (sliding window).
* On exceed → `429 plan_throttled` with `Retry-After`.
* Free/community plan may also receive **randomized delay** to disincentivize farmed signing.
---
## 10) Storage & caches
* **Redis**:
* DPoP nonce & `jti` replay cache (TTL ≤ 10min).
* PoE introspection cache (short TTL, e.g., 60120s).
* Releaseverify cache (`scannerImageDigest` → { trusted, ts }).
* **Audit store** (Mongo or Postgres): `signer.audit_events`
```
{ _id, ts, tenantId, installationId, licenseId, customerId,
plan, actor{sub,cnf}, request{predicateType, subjectSha256[], imageDigest},
poe{type, thumbprint|jwtKid, exp, introspectSnapshot},
release{digest, signerId, policy},
mode: "keyless"|"kms",
result: "success"|"deny:<reason>"|"error:<reason>",
bundleSha256? }
```
* **Config**: StellaOps release signing keyring, Fulcio roots, Licensing CA bundle.
---
## 11) Security & privacy
* **mTLS** on all Signer endpoints.
* **No bearer fallbacks** — DPoP/mTLS enforced for `aud=signer`.
* **PoE** is never persisted beyond audit snapshots (minimized fields).
* **Secrets**: no longlived private keys on disk (keyless) or handled via KMS APIs.
* **Input hardening**: schemavalidate predicates; cap payload sizes; zstd/gzip decompression bombs guarded.
* **Logging**: redact PoE JWTs, access tokens, DPoP proofs; log only hashes and identifiers.
---
## 12) Metrics & observability
* `signer.requests_total{result}`
* `signer.latency_seconds{stage=auth|introspect|release_verify|sign}`
* `signer.poe_failures_total{reason}`
* `signer.release_verify_failures_total{reason}`
* `signer.plan_throttle_total{license_id}`
* `signer.bundle_bytes_total`
* `signer.keyless_certs_issued_total` / `signer.kms_sign_total`
* OTEL traces across stages; correlation id (`auditId`) returned to client.
---
## 13) Configuration (YAML)
```yaml
signer:
listen: "https://0.0.0.0:8443"
authority:
issuer: "https://authority.internal"
jwksUrl: "https://authority.internal/jwks"
require: "dpop" # "dpop" | "mtls"
poe:
mode: "both" # "jwt" | "mtls" | "both"
licensing:
introspectUrl: "https://www.stella-ops.org/api/v1/license/introspect"
caBundle: "/etc/ssl/licensing-ca.pem"
cacheTtlSeconds: 90
release:
referrers:
allowRekorVerified: true
keyrings:
- type: "cosign-keyless"
fulcioRoots: ["/etc/fulcio/root.pem"]
identities:
- san: "mailto:release@stella-ops.org"
- san: "https://sigstore.dev/oidc/stellaops"
signing:
mode: "keyless" # "keyless" | "kms"
fulcio:
issuer: "https://fulcio.internal"
oidcClientId: "signer"
oidcClientSecretRef: "env:FULCIO_CLIENT_SECRET"
certTtlSeconds: 600
kms:
provider: "aws-kms"
keyId: "arn:aws:kms:...:key/..."
quotas:
default:
qps: 100
concurrency: 20
maxArtifactBytes: 104857600
free:
qps: 5
concurrency: 1
maxArtifactBytes: 1048576
```
---
## 14) Testing matrix
* **Auth & DPoP**: bad `aud`, wrong `jkt`, replayed `jti`, missing nonce, mTLS mismatch.
* **PoE**: expired, revoked, plan mismatch, release year gate, max_version gate.
* **Release verify**: unsigned digest, wrong signer, Rekorabsent (when required), referrers unreachable.
* **Signing**: Fulcio outage; KMS timeouts; bundle correctness (verifier harness).
* **Quotas**: burst above QPS, artifact over size, concurrency overflow.
* **Schema**: invalid predicate types/required fields.
* **Determinism**: same request → identical DSSE (aside from cert validity period).
* **Perf**: P95 endtoend under 120ms with caches warm (excluding network to Fulcio).
---
## 15) Failure modes & responses
| Failure | HTTP | Problem type | Notes |
| ----------------------- | ---- | --------------------- | -------------------------------------------- |
| Invalid OpTok / DPoP | 401 | `invalid_token` | `WWW-Authenticate` with DPoP nonce if needed |
| PoE invalid/revoked | 403 | `entitlement_denied` | Include `license_id` (hashed) and reason |
| Scanner image untrusted | 403 | `release_untrusted` | Include digest and required identity |
| Plan throttle | 429 | `plan_throttled` | Include limits and `Retry-After` |
| Artifact too large | 413 | `artifact_too_large` | Include cap |
| Fulcio/KMS down | 503 | `signing_unavailable` | RetryAfter with jitter |
---
## 16) Deployment & HA
* Run ≥ 2 replicas; front with L7 LB; **sticky** not required.
* Redis for replay/quota caches (HA).
* Audit sink (Mongo/Postgres) in primary region; asynchronous write with local fallback buffer.
* Fulcio/KMS clients configured with retries/backoff; circuit breakers.
---
## 17) Implementation notes
* **.NET 10** minimal API + Kestrel mTLS; custom DPoP middleware; JWT/JWKS cache.
* **Cosign verification** via sigstore libraries; Referrers queries over registry API with retries.
* **DSSE** via intoto libs; canonical JSON writer for predicates.
* **Backpressure** paths: refuse at auth/quota stages before any expensive network calls.
---
## 18) Examples (wire)
**Request (free plan; expect throttle if burst):**
```http
POST /api/v1/signer/sign/dsse HTTP/1.1
Authorization: DPoP <JWT>
DPoP: <proof>
Content-Type: application/json
```
**Error (release untrusted):**
```json
{
"type": "https://stella-ops.org/problems/release_untrusted",
"title": "Scanner image not signed by StellaOps",
"status": 403,
"detail": "sha256:abcd... not in trusted keyring",
"instance": "urn:audit:a7c9e3f2-..."
}
```
---
## 19) Roadmap
* **Key Transparency**: optional publication of Signers *own* certs to a KT log.
* **Attested Build**: SLSAstyle provenance for Signer container itself, checked at startup.
* **FIPS mode**: enforce `ES256` + KMS/HSM only; disallow Ed25519.
* **Dual attestation**: optional immediate push to **Attestor** (sync mode) with timeout budget, returning Rekor UUID inline.

View File

@@ -0,0 +1,61 @@
# Implementation plan — Signer
## Delivery phases
- **Phase 1 Core service & PoE**
Harden OpTok validation, Proof-of-Entitlement (PoE) checks, quota enforcement, scanner release verification, and DSSE signing pipeline (keyless + keyful).
- **Phase 2 Export Center integration**
Produce signing bundles with provenance manifests for Export Center, deliver cosign-compatible outputs, and document verification workflows for offline exports.
- **Phase 3 Attestor alignment**
Emit DSSE envelopes, metadata, and signer identity information required by Attestor (key metadata, certificate chains, bundle hashes); expose audit APIs.
- **Phase 4 Observability & resilience**
Complete telemetry, throttling dashboards, audit trails, fallback key rotation, and offline kit packaging.
## Work breakdown
- **Authentication & entitlement**
- Enforce Authority-issued DPoP/mTLS tokens with `signer.sign` scope and tenant checks.
- Integrate PoE introspection (cloud licensing) and plan quotas.
- Validate scanner release signature via OCI referrers before signing reports/SBOMs.
- **Signing pipeline**
- Implement DSSE canonicalisation, keyless (Fulcio) and keyful (KMS/HSM/FIDO2) signing.
- Support multi-signature output, certificate chain embedding, and deterministic bundle hashing.
- Provide policy metadata (policy digest, view set) for report predicates.
- **Integrations**
- Coordinate with Attestor on bundle schema, signer identity payload, and error codes.
- Expose Export Center-ready signing API (`/sign/export`) that returns manifest + signature tuple.
- Surface CLI flows (`stella sign sbom/report`, offline verification helpers).
- **Security & key management**
- Key rotation and revocation runbooks; separation of signing keys per tenancy/plan.
- Hardware-backed key support (HSM/FIDO2) with audit logging and attested builds.
- **Observability**
- Metrics: signing latency, PoE failures, quota hits, key usage distribution.
- Structured logs with trace/context IDs, subject digests, issuer mode, decision outcome.
- Alerts for PoE outages, key exhaustion, quota breach, signing failure spikes.
- **Documentation & runbooks**
- Update README/architecture/implementation plan, operator runbooks, offline verification guidance, and CLI reference.
## Acceptance criteria
- Signer only signs requests that satisfy OpTok, PoE, quota, and scanner provenance checks.
- DSSE outputs (keyless + keyful) verify with standard cosign tooling; Attestor logs them without additional transformation.
- Export Center receives signed bundles, provenance manifests, and signature metadata to package exports deterministically.
- Audit logs capture every signing request with tenant, issuer, subject digest, PoE state, and key source.
- Observability dashboards/alerts reflect latency, failure rate, PoE status, and quota usage.
- CLI/Offline workflows verify signatures using Offline Kit trust roots.
## Risks & mitigations
- **PoE/entitlement outages:** cache last-known entitlement within TTL, provide emergency bypass toggles with audit trail.
- **Key compromise:** enforce hardware-backed keys, rotation cadence, immediate revocation workflow, incident runbook.
- **Release verification failures:** maintain allowlist for trusted scanner digests, fallback to manual approval with audit.
- **Determinism drift:** canonicalise JSON, lock timestamp sources, regression tests for DSSE hashing.
## Test strategy
- **Unit:** OpTok/PoE validation, quota enforcement, scanner signature verification, DSSE canonicalisation, multi-sig bundling.
- **Integration:** end-to-end signing for SBOM, report, export artifacts; Attestor ingestion; Export Center bundle signing.
- **Security:** fuzz signing inputs, simulate PoE tampering, ensure unauthorized actors are rejected.
- **Performance:** signing throughput benchmarks (keyless vs keyful), quota pressure, concurrency checks.
- **Offline:** verify signatures using Offline Kit trust roots and cosign CLI without network access.
## Definition of done
- Signing pipeline deployed with observability and incident runbooks.
- Export Center + Attestor dependencies validated; CLI parity confirmed.
- Documentation updated (README, architecture, runbooks, CLI guides) with imposed rule compliance.
- ./TASKS.md and ../../TASKS.md reflect the latest status transitions.