Add Authority Advisory AI and API Lifecycle Configuration

- Introduced AuthorityAdvisoryAiOptions and related classes for managing advisory AI configurations, including remote inference options and tenant-specific settings.
- Added AuthorityApiLifecycleOptions to control API lifecycle settings, including legacy OAuth endpoint configurations.
- Implemented validation and normalization methods for both advisory AI and API lifecycle options to ensure proper configuration.
- Created AuthorityNotificationsOptions and its related classes for managing notification settings, including ack tokens, webhooks, and escalation options.
- Developed IssuerDirectoryClient and related models for interacting with the issuer directory service, including caching mechanisms and HTTP client configurations.
- Added support for dependency injection through ServiceCollectionExtensions for the Issuer Directory Client.
- Updated project file to include necessary package references for the new Issuer Directory Client library.
This commit is contained in:
master
2025-11-02 13:40:38 +02:00
parent 66cb6c4b8a
commit f98cea3bcf
516 changed files with 68157 additions and 24754 deletions

View File

@@ -1,261 +1,320 @@
# Authority Scopes & Tenancy — AOC Update
> **Audience:** Authority Core, platform security engineers, DevOps owners.
> **Scope:** Scope taxonomy, tenancy enforcement, rollout guidance for the Aggregation-Only Contract (Sprint19).
Authority issues short-lived tokens bound to tenants and scopes. Sprint19 introduces new scopes to support the AOC guardrails in Concelier and Excititor. This document lists the canonical scope catalogue, describes tenancy propagation, and outlines operational safeguards.
---
## 1·Scope catalogue (post AOC)
| Scope | Surface | Purpose | Notes |
|-------|---------|---------|-------|
| `advisory:ingest` | Concelier ingestion APIs | Append-only writes to `advisory_raw` collections. | Requires tenant claim; blocked for global clients. |
| `advisory:read` | `/aoc/verify`, Concelier dashboards, CLI | Read-only access to stored advisories and guard results. | Must be requested with `aoc:verify`; Authority rejects tokens missing the pairing. |
| `vex:ingest` | Excititor ingestion APIs | Append-only writes to `vex_raw`. | Mirrors `advisory:ingest`; tenant required. |
| `vex:read` | `/aoc/verify`, Excititor dashboards, CLI | Read-only access to stored VEX material. | Must be requested with `aoc:verify`; Authority rejects tokens missing the pairing. |
| `aoc:verify` | CLI/CI pipelines, Console verification jobs | Execute Aggregation-Only Contract guard runs. | Always issued with tenant; required whenever requesting `advisory:read`, `vex:read`, or any `signals:*` scope. |
| `signals:read` | Signals API, reachability dashboards | Read-only access to stored reachability signals. | Tenant and `aoc:verify` required; missing pairing returns `invalid_scope`. |
| `signals:write` | Signals ingestion APIs | Append-only writes for reachability signals. | Requires tenant and `aoc:verify`; Authority logs `authority.aoc_scope_violation` on mismatch. |
| `signals:admin` | Signals administration tooling | Rotate credentials, manage reachability sensors, purge stale data. | Reserved for automation; `aoc:verify` + tenant mandatory; violations are audited. |
| `graph:write` | Cartographer pipeline | Enqueue graph build/overlay jobs. | Reserved for Cartographer service identity; tenant required. |
| `graph:read` | Graph API, Scheduler overlays, UI | Read graph projections/overlays. | Tenant required; granted to Cartographer, Graph API, Scheduler. |
| `graph:export` | Graph export endpoints | Stream GraphML/JSONL artefacts. | UI/gateway automation only; tenant required. |
| `graph:simulate` | Policy simulation overlays | Trigger what-if overlays on graphs. | Restricted to automation; tenant required. |
| `effective:write` | Policy Engine | Create/update `effective_finding_*` collections. | **Only** the Policy Engine service client may hold this scope; tenant required. |
| `findings:read` | Console, CLI, exports | Read derived findings materialised by Policy Engine. | Shared across tenants with RBAC; tenant claim still enforced. |
| `policy:author` | Policy Studio (Console, CLI) | Author drafts, run lint, execute quick simulations. | Tenant required; typically granted via `role/policy-author`. |
| `policy:review` | Policy Studio review panes | Review drafts, leave comments, request changes. | Tenant required; pair with `policy:simulate` for diff previews. |
| `policy:approve` | Policy Studio approvals | Approve or reject policy drafts. | Tenant required; fresh-auth enforced by Console UI. |
| `policy:operate` | Policy Studio promotion controls | Trigger batch simulations, promotions, and canary runs. | Tenant required; combine with `policy:run`/`policy:activate`. |
| `policy:audit` | Policy audit exports | Access immutable policy history, comments, and signatures. | Tenant required; read-only access. |
| `policy:simulate` | Policy Studio / CLI simulations | Run simulations against tenant inventories. | Tenant required; available to authors, reviewers, operators. |
| `vuln:read` | Vuln Explorer API/UI | Read normalized vulnerability data. | Tenant required. |
| `export.viewer` | Export Center APIs | List export profiles/runs, fetch manifests and bundles. | Tenant required; read-only access. |
| `export.operator` | Export Center APIs | Trigger export runs, manage schedules, request verifications. | Tenant required; pair with `export.admin` for retention/encryption changes. |
| `export.admin` | Export Center administrative APIs | Configure retention policies, encryption keys, and scheduling defaults. | Tenant required; token requests must include `export_reason` + `export_ticket`; Authority audits denials. |
| `orch:read` | Orchestrator dashboards/API | Read queued jobs, worker state, and rate-limit telemetry. | Tenant required; never grants mutation rights. |
| `orch:operate` | Orchestrator control actions | Execute pause/resume, retry, sync-now, and backfill operations. Requires tenant assignment **and** `operator_reason`/`operator_ticket` parameters when requesting tokens. |
| `exceptions:read` | Exception service APIs, Console | Enumerate exception definitions, routing templates, and approval state. | Tenant and approval routing metadata required for audit replay. |
| `exceptions:write` | Policy Engine → Authority bridge | Persist exception evaluations, lifecycle events, and status changes. | Tenant required; only service principals should hold this scope. |
| `exceptions:approve` | Console fresh-auth flows, delegated admins | Approve or reject exception requests routed through Authority. | Tenant required; Authority enforces MFA when any bound routing template has `requireMfa=true`. |
| `ui.read` | Console base APIs | Retrieve tenant catalog, profile metadata, and token introspection results. | Tenant header required; responses are DPoP-bound and audit logged. |
| `authority:tenants.read` | Console admin workspace | Enumerate configured tenants, default roles, and isolation metadata. | Tenant claim must match header; access audited via `authority.console.tenants.read`. |
| Existing scopes | (e.g., `policy:*`, `concelier.jobs.trigger`) | Unchanged. | `concelier.merge` is retired — clients must request `advisory:ingest`/`advisory:read`; requests continue to fail with `invalid_client`. Review `/docs/security/policy-governance.md` for policy-specific scopes. |
### 1.1Scope bundles (roles)
- **`role/concelier-ingest`** → `advisory:ingest`, `advisory:read`.
- **`role/excititor-ingest`** → `vex:ingest`, `vex:read`.
- **`role/signals-uploader`** → `signals:write`, `signals:read`, `aoc:verify`.
- **`role/aoc-operator`** → `aoc:verify`, `advisory:read`, `vex:read`.
- **`role/policy-engine`** → `effective:write`, `findings:read`.
- **`role/cartographer-service`** → `graph:write`, `graph:read`.
- **`role/graph-gateway`** → `graph:read`, `graph:export`, `graph:simulate`.
- **`role/console`** → `ui.read`, `advisory:read`, `vex:read`, `exceptions:read`, `aoc:verify`, `findings:read`, `orch:read`, `vuln:read`.
- **`role/ui-console-admin`** → `ui.read`, `authority:tenants.read`, `authority:roles.read`, `authority:tokens.read`, `authority:clients.read` (paired with write scopes where required).
- **`role/orch-viewer`** *(Authority role: `Orch.Viewer`)*`orch:read`.
- **`role/orch-operator`** *(Authority role: `Orch.Operator`)*`orch:read`, `orch:operate`.
- **`role/policy-author`** → `policy:author`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/policy-reviewer`** → `policy:review`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/policy-approver`** → `policy:approve`, `policy:review`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/policy-operator`** → `policy:operate`, `policy:run`, `policy:activate`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/policy-auditor`** → `policy:audit`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/export-viewer`** *(Authority role: `Export.Viewer`)*`export.viewer`.
- **`role/export-operator`** *(Authority role: `Export.Operator`)*`export.viewer`, `export.operator`.
- **`role/export-admin`** *(Authority role: `Export.Admin`)*`export.viewer`, `export.operator`, `export.admin`.
- **`role/exceptions-service`** → `exceptions:read`, `exceptions:write`.
- **`role/exceptions-approver`** → `exceptions:read`, `exceptions:approve`.
Roles are declared per tenant in `authority.yaml`:
```yaml
tenants:
- name: default
roles:
concelier-ingest:
scopes: [advisory:ingest, advisory:read]
signals-uploader:
scopes: [signals:write, signals:read, aoc:verify]
aoc-operator:
scopes: [aoc:verify, advisory:read, vex:read]
orch-viewer:
scopes: [orch:read]
orch-operator:
scopes: [orch:read, orch:operate]
policy-author:
scopes: [policy:author, policy:read, policy:simulate, findings:read]
policy-reviewer:
scopes: [policy:review, policy:read, policy:simulate, findings:read]
policy-approver:
scopes: [policy:approve, policy:review, policy:read, policy:simulate, findings:read]
policy-operator:
scopes: [policy:operate, policy:run, policy:activate, policy:read, policy:simulate, findings:read]
policy-auditor:
scopes: [policy:audit, policy:read, policy:simulate, findings:read]
policy-engine:
scopes: [effective:write, findings:read]
exceptions-service:
scopes: [exceptions:read, exceptions:write]
exceptions-approver:
scopes: [exceptions:read, exceptions:approve]
```
> **MFA requirement:** When any `exceptions.routingTemplates` entry sets `requireMfa: true`, Authority refuses to mint tokens containing `exceptions:approve` unless the authenticating identity provider advertises MFA support. Password/OIDC flows produce `authority.password.grant` audit events with `reason="Exception approval scope requires an MFA-capable identity provider."` when the requirement is violated.
---
## 2·Tenancy enforcement
### 2.1Token claims
Tokens now include:
- `tenant` claim (string) — required for all ingestion and verification scopes.
- `service_identity` (optional) — e.g., `policy-engine`, `cartographer`. Required when requesting `effective:write` or `graph:write`.
- `delegation_allowed` (boolean) — defaults `false`. Prevents console tokens from delegating ingest scopes.
Authority rejects requests when:
- `tenant` is missing while requesting `advisory:ingest`, `advisory:read`, `vex:ingest`, `vex:read`, or `aoc:verify` scopes.
- `aoc:verify` is absent while tokens request `advisory:read`, `vex:read`, or any `signals:*` scope (`invalid_scope` with deterministic message).
- `service_identity != policy-engine` but `effective:write` is present (`ERR_AOC_006` enforcement).
- `service_identity != cartographer` but `graph:write` is present (graph pipeline enforcement).
- Tokens attempt to combine `advisory:ingest` with `effective:write` (separation of duties).
- `exceptions:approve` is requested by a client without a tenant assignment or via an identity provider lacking MFA when `RequireMfaForApprovals=true`.
### 2.2Propagation
- API Gateway forwards `tenant` claim as header (`X-Stella-Tenant`). Services refuse requests lacking the header.
- Concelier/Excititor stamp tenant into raw documents and structured logs.
- Policy Engine copies `tenant` from tokens into `effective_finding_*` collections.
- Exception lifecycle services persist tenant and the selected routing template identifier alongside approval decisions. Authority audit events (`authority.password.grant`, `authority.client_credentials.grant`) surface `audit.scopes` and, on denials, a `scope.invalid` metadata entry so operators can trace exception approval attempts without inspecting downstream services.
### 2.3Cross-tenant scenarios
- Platform operators with `tenant:admin` can assume other tenants via `/authority/tenant/switch` if explicitly permitted.
- CLI commands accept `--tenant <id>` to override environment default; Authority logs tenant switch events (`authority.tenant.switch`).
- Console tenant picker uses delegated token exchange (`/token/exchange`) to obtain scoped tenant tokens without exposing raw credentials.
---
## 3·Configuration changes
### 3.1Authority configuration (`authority.yaml`)
Add new scopes and optional claims transformations:
```yaml
security:
scopes:
- name: advisory:ingest
description: Concelier raw ingestion (append-only)
- name: advisory:read
description: Read Concelier advisories and guard verdicts
- name: vex:ingest
description: Excititor raw ingestion
- name: vex:read
description: Read Excititor VEX records
- name: aoc:verify
description: Run AOC verification
- name: effective:write
description: Policy Engine materialisation
- name: findings:read
description: Read derived findings
- name: graph:write
description: Cartographer build submissions
- name: graph:read
description: Read graph overlays
- name: graph:export
description: Export graph artefacts
- name: graph:simulate
description: Run graph what-if simulations
- name: vuln:read
description: Read Vuln Explorer data
claimTransforms:
- match: { scope: "effective:write" }
require:
serviceIdentity: policy-engine
- match: { scope: "graph:write" }
require:
serviceIdentity: cartographer
```
### 3.2Client registration
Update service clients:
- `Concelier.WebService` → request `advisory:ingest`, `advisory:read`.
- `Excititor.WebService` → request `vex:ingest`, `vex:read`.
- `Policy.Engine` → request `effective:write`, `findings:read`; set `properties.serviceIdentity=policy-engine`.
- `Cartographer.Service` → request `graph:write`, `graph:read`; set `properties.serviceIdentity=cartographer`.
- `Graph API Gateway` → request `graph:read`, `graph:export`, `graph:simulate`; tenant hint required.
- `Console` → request `advisory:read`, `vex:read`, `aoc:verify`, `findings:read`, `vuln:read` plus existing UI scopes.
- `CLI automation` → request `aoc:verify`, `advisory:read`, `vex:read` as needed.
Client definition snippet:
```yaml
clients:
- clientId: concelier-web
grantTypes: [client_credentials]
scopes: [advisory:ingest, advisory:read]
tenants: [default]
- clientId: policy-engine
grantTypes: [client_credentials]
scopes: [effective:write, findings:read]
properties:
serviceIdentity: policy-engine
- clientId: cartographer-service
grantTypes: [client_credentials]
scopes: [graph:write, graph:read]
properties:
serviceIdentity: cartographer
```
---
## 4·Operational safeguards
- **Audit events:** Authority emits `authority.scope.granted` and `authority.scope.revoked` events with `scope` and `tenant`. Monitor for unexpected grants.
- **Rate limiting:** Apply stricter limits on `/token` endpoints for clients requesting `advisory:ingest` or `vex:ingest` to mitigate brute-force ingestion attempts.
- **Incident response:** Link AOC alerts to Authority audit logs to confirm whether violations come from expected identities.
- **Rotation:** Rotate ingest client secrets alongside guard deployments; add rotation steps to `ops/authority-key-rotation.md`.
- **Testing:** Integration tests must fail if tokens lacking `tenant` attempt ingestion; add coverage in Concelier/Excititor smoke suites (see `CONCELIER-CORE-AOC-19-013`).
---
## 5·Offline & air-gap notes
- Offline Kit bundles include tenant-scoped service credentials. Ensure ingest bundles ship without `advisory:ingest` scopes unless strictly required.
- CLI verification in offline environments uses pre-issued `aoc:verify` tokens; document expiration and renewal processes.
- Authority replicas in air-gapped environments should restrict scope issuance to known tenants and log all `/token` interactions for later replay.
---
## 6·References
- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md)
- [Architecture overview](../modules/platform/architecture-overview.md)
- [Concelier architecture](../modules/concelier/architecture.md)
- [Excititor architecture](../modules/excititor/architecture.md)
- [Policy governance](policy-governance.md)
# Authority Scopes & Tenancy — AOC Update
> **Audience:** Authority Core, platform security engineers, DevOps owners.
> **Scope:** Scope taxonomy, tenancy enforcement, rollout guidance for the Aggregation-Only Contract (Sprint19).
Authority issues short-lived tokens bound to tenants and scopes. Sprint19 introduces new scopes to support the AOC guardrails in Concelier and Excititor. This document lists the canonical scope catalogue, describes tenancy propagation, and outlines operational safeguards.
---
## 1·Scope catalogue (post AOC)
| Scope | Surface | Purpose | Notes |
|-------|---------|---------|-------|
| `advisory:ingest` | Concelier ingestion APIs | Append-only writes to `advisory_raw` collections. | Requires tenant claim; blocked for global clients. |
| `advisory:read` | `/aoc/verify`, Concelier dashboards, CLI | Read-only access to stored advisories and guard results. | Must be requested with `aoc:verify`; Authority rejects tokens missing the pairing. |
| `advisory-ai:view` | Advisory AI dashboards, remediation exports | Read-only access to Advisory AI artefacts (summaries, remediation bundles). | Requires `aoc:verify`; defaults granted to `advisory-ai-viewer` role. |
| `advisory-ai:operate` | Advisory AI remote inference workflows | Submit Advisory AI inference/remediation jobs and retrieve anonymized outputs. | Requires `aoc:verify`; remote inference must be enabled and tenant-consented. |
| `advisory-ai:admin` | Advisory AI configuration APIs, Console admin | Manage Advisory AI profiles, remote inference toggles, and audit exports. | Restricted to platform admins; requires `aoc:verify`; all operations audited. |
| `vex:ingest` | Excititor ingestion APIs | Append-only writes to `vex_raw`. | Mirrors `advisory:ingest`; tenant required. |
| `vex:read` | `/aoc/verify`, Excititor dashboards, CLI | Read-only access to stored VEX material. | Must be requested with `aoc:verify`; Authority rejects tokens missing the pairing. |
| `aoc:verify` | CLI/CI pipelines, Console verification jobs | Execute Aggregation-Only Contract guard runs. | Always issued with tenant; required whenever requesting `advisory:read`, `vex:read`, or any `signals:*` scope. |
| `signals:read` | Signals API, reachability dashboards | Read-only access to stored reachability signals. | Tenant and `aoc:verify` required; missing pairing returns `invalid_scope`. |
| `signals:write` | Signals ingestion APIs | Append-only writes for reachability signals. | Requires tenant and `aoc:verify`; Authority logs `authority.aoc_scope_violation` on mismatch. |
| `signals:admin` | Signals administration tooling | Rotate credentials, manage reachability sensors, purge stale data. | Reserved for automation; `aoc:verify` + tenant mandatory; violations are audited. |
| `airgap:status:read` | AirGap Controller status API, Console status pane, CLI | Read sealed state, staleness metrics, and import history. | Tenant required; defaulted via `airgap-viewer` and Console bundles. |
| `airgap:import` | AirGap Importer APIs, CLI workflows | Import offline bundles into catalog and object storage. | Tenant required; issued to `airgap-operator`; operations are fully audited. |
| `airgap:seal` | AirGap Controller sealing endpoints | Seal or unseal installations and confirm sealing tickets. | Tenant required; restrict to `airgap-admin`; pair with operator ticket policy. |
| `obs:read` | Observability API, Console dashboards | Read observability dashboards, SLO digests, and incident overlays. | Tenant required; typically paired with `timeline:read` and `evidence:read`. |
| `timeline:read` | Timeline API, observability consoles, CLI | Read incident timeline entries and annotations. | Issue alongside `obs:read` for analyst workflows; tenant enforced. |
| `timeline:write` | Timeline ingest workers, Scheduler | Append deterministic incident timeline events and annotations. | Automation only; Authority audits source client + tenant. |
| `evidence:create` | Evidence Locker ingestion APIs | Create evidence items, upload artefacts, and link attestations. | Append-only; emits `authority.evidence.create` audit trail per item. |
| `evidence:read` | Evidence Locker APIs, Offline Kit exports | Read evidence items, artefacts, and linkage metadata. | Analysts/legal staff; tenant enforced. |
| `evidence:hold` | Evidence Locker legal hold endpoints | Apply or release legal holds on evidence items. | Restricted to compliance/legal operators; audited. |
| `attest:read` | Attestation evidence explorer, Observability UI | Read attestation records, DSSE bundles, and verification proofs. | Read-only counterpart to signer/attestor pipelines; tenant required. |
| `obs:incident` | Incident bridge automation, Console | Toggle incident mode, extend retention, enable emergency telemetry. | Requires fresh auth + `incident_reason`, no refresh; audit via `/authority/audit/incident`. |
> **Observability scope bundle (added 2 Nov 2025).** `obs:read`, `timeline:read`, `timeline:write`, `evidence:create`, `evidence:read`, `evidence:hold`, `attest:read`, and `obs:incident` always require a tenant claim. Gateways must forward `X-StellaOps-Tenant` (or the configured tenant header) or resource servers will reject the request with `tenant_header_missing`. The sample `authority.yaml` assigns these scopes via the `observability-*` roles; reuse those roles when onboarding new tenants to keep bundles consistent.
> **Fresh auth enforcement (Sprint55).** Authority-issued `obs:incident` tokens must carry both `incident_reason` and `auth_time`. Resource servers enforce a five-minute freshness window and log `incident.reason`, `incident.auth_time`, and `incident.fresh_auth_satisfied` in `authority.resource.authorize` audit events, enabling `/authority/audit/incident` to verify activation reason and freshness.
| `graph:write` | Cartographer pipeline | Enqueue graph build/overlay jobs. | Reserved for Cartographer service identity; tenant required. |
| `graph:read` | Graph API, Scheduler overlays, UI | Read graph projections/overlays. | Tenant required; granted to Cartographer, Graph API, Scheduler. |
| `graph:export` | Graph export endpoints | Stream GraphML/JSONL artefacts. | UI/gateway automation only; tenant required. |
| `graph:simulate` | Policy simulation overlays | Trigger what-if overlays on graphs. | Restricted to automation; tenant required. |
| `effective:write` | Policy Engine | Create/update `effective_finding_*` collections. | **Only** the Policy Engine service client may hold this scope; tenant required. |
| `findings:read` | Console, CLI, exports | Read derived findings materialised by Policy Engine. | Shared across tenants with RBAC; tenant claim still enforced. |
| `policy:author` | Policy Studio (Console, CLI) | Author drafts, run lint, execute quick simulations. | Tenant required; typically granted via `role/policy-author`. |
| `policy:review` | Policy Studio review panes | Review drafts, leave comments, request changes. | Tenant required; pair with `policy:simulate` for diff previews. |
| `policy:approve` | Policy Studio approvals | Approve or reject policy drafts. | Tenant required; fresh-auth enforced by Console UI. |
| `policy:operate` | Policy Studio promotion controls | Trigger batch simulations, promotions, and canary runs. | Tenant required; combine with `policy:run`/`policy:activate`. |
| `policy:audit` | Policy audit exports | Access immutable policy history, comments, and signatures. | Tenant required; read-only access. |
| `policy:simulate` | Policy Studio / CLI simulations | Run simulations against tenant inventories. | Tenant required; available to authors, reviewers, operators. |
| `vuln:read` | Vuln Explorer API/UI | Read normalized vulnerability data. | Tenant required. |
| `export.viewer` | Export Center APIs | List export profiles/runs, fetch manifests and bundles. | Tenant required; read-only access. |
| `export.operator` | Export Center APIs | Trigger export runs, manage schedules, request verifications. | Tenant required; pair with `export.admin` for retention/encryption changes. |
| `export.admin` | Export Center administrative APIs | Configure retention policies, encryption keys, and scheduling defaults. | Tenant required; token requests must include `export_reason` + `export_ticket`; Authority audits denials. |
| `notify.viewer` | Notifier APIs, Console, CLI | Read notifier rules, channel configuration, and delivery history. | Tenant required; responses are redacted for cross-tenant data; no mutation rights. |
| `notify.operator` | Notifier APIs, automation hooks | Manage notifier rules, trigger tests, acknowledge/resolve incidents. | Tenant required; Authority enforces operator metadata (`notify_reason`, `notify_ticket`) when configured. |
| `notify.admin` | Notifier administrative APIs | Configure channels, secrets, quiet hours, and escalation policies. | Tenant required; Authority audits secret rotations and escalation changes. |
| `notify.escalate` | Notifier ack/escalation bridge | Issue escalation-bearing ack tokens and honour escalation acknowledgements. | Tenant required; Authority enforces pairing with `notify.admin` when escalation mutates platform state. |
| `orch:read` | Orchestrator dashboards/API | Read queued jobs, worker state, and rate-limit telemetry. | Tenant required; never grants mutation rights. |
| `orch:operate` | Orchestrator control actions | Execute pause/resume, retry, sync-now, and backfill operations. Requires tenant assignment **and** `operator_reason`/`operator_ticket` parameters when requesting tokens. |
| `orch:quota` | Orchestrator quota administration | Adjust per-tenant quotas, burst ceilings, and backfill allowances. Requires tenant assignment and `quota_reason` (≤256 chars); optional `quota_ticket` (≤128 chars) is recorded for audit. |
| `packs.read` | Packs Registry, Task Runner | Discover Task Packs, download manifests, and inspect metadata. | Tenant claim required; Authority rejects cross-tenant tokens and tags violations with `authority.pack_scope_violation`. |
| `packs.write` | Packs Registry APIs | Publish or update Task Packs (requires signed bundles). | Tenant claim required; typically restricted to registry automation; violations surface via `authority.pack_scope_violation`. |
| `packs.run` | Task Runner | Execute Task Packs via CLI or Task Runner APIs. | Tenant claim required; Task Runner enforces tenant isolation; Authority emits `authority.pack_scope_violation` when missing. |
| `packs.approve` | Task Runner approvals | Fulfil Task Pack approval gates and resume runs. | Tenant claim required; approval events audited with run ID and Pack scope violations tagged as `authority.pack_scope_violation`. |
| `exceptions:read` | Exception service APIs, Console | Enumerate exception definitions, routing templates, and approval state. | Tenant and approval routing metadata required for audit replay. |
| `exceptions:write` | Policy Engine → Authority bridge | Persist exception evaluations, lifecycle events, and status changes. | Tenant required; only service principals should hold this scope. |
| `exceptions:approve` | Console fresh-auth flows, delegated admins | Approve or reject exception requests routed through Authority. | Tenant required; Authority enforces MFA when any bound routing template has `requireMfa=true`. |
| `ui.read` | Console base APIs | Retrieve tenant catalog, profile metadata, and token introspection results. | Tenant header required; responses are DPoP-bound and audit logged. |
| `authority:tenants.read` | Console admin workspace | Enumerate configured tenants, default roles, and isolation metadata. | Tenant claim must match header; access audited via `authority.console.tenants.read`. |
| Existing scopes | (e.g., `policy:*`, `concelier.jobs.trigger`) | Unchanged. | `concelier.merge` is retired — clients must request `advisory:ingest`/`advisory:read`; requests continue to fail with `invalid_client`. Review `/docs/security/policy-governance.md` for policy-specific scopes. |
### 1.1Scope bundles (roles)
- **`role/concelier-ingest`** → `advisory:ingest`, `advisory:read`.
- **`role/excititor-ingest`** → `vex:ingest`, `vex:read`.
- **`role/signals-uploader`** → `signals:write`, `signals:read`, `aoc:verify`.
- **`role/aoc-operator`** → `aoc:verify`, `advisory:read`, `vex:read`.
- **`role/policy-engine`** → `effective:write`, `findings:read`.
- **`role/cartographer-service`** → `graph:write`, `graph:read`.
- **`role/graph-gateway`** → `graph:read`, `graph:export`, `graph:simulate`.
- **`role/console`** → `ui.read`, `advisory:read`, `vex:read`, `exceptions:read`, `aoc:verify`, `findings:read`, `airgap:status:read`, `orch:read`, `vuln:read`.
- **`role/ui-console-admin`** → `ui.read`, `authority:tenants.read`, `authority:roles.read`, `authority:tokens.read`, `authority:clients.read` (paired with write scopes where required).
- **`role/orch-viewer`** *(Authority role: `Orch.Viewer`)*`orch:read`.
- **`role/orch-operator`** *(Authority role: `Orch.Operator`)*`orch:read`, `orch:operate`.
- **`role/orch-admin`** *(Authority role: `Orch.Admin`)*`orch:read`, `orch:operate`, `orch:quota`.
- **`role/packs-runner`** → `packs.read`, `packs.run`.
- **`role/packs-publisher`** → `packs.read`, `packs.write`.
- **`role/packs-approver`** → `packs.read`, `packs.approve`.
- **`role/policy-author`** → `policy:author`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/policy-reviewer`** → `policy:review`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/policy-approver`** → `policy:approve`, `policy:review`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/policy-operator`** → `policy:operate`, `policy:run`, `policy:activate`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/policy-auditor`** → `policy:audit`, `policy:read`, `policy:simulate`, `findings:read`.
- **`role/export-viewer`** *(Authority role: `Export.Viewer`)*`export.viewer`.
- **`role/export-operator`** *(Authority role: `Export.Operator`)*`export.viewer`, `export.operator`.
- **`role/export-admin`** *(Authority role: `Export.Admin`)*`export.viewer`, `export.operator`, `export.admin`.
- **`role/notify-viewer`** *(Authority role: `Notify.Viewer`)*`notify.viewer`.
- **`role/notify-operator`** *(Authority role: `Notify.Operator`)*`notify.viewer`, `notify.operator`.
- **`role/notify-admin`** *(Authority role: `Notify.Admin`)*`notify.viewer`, `notify.operator`, `notify.admin`.
- **`role/observability-viewer`** *(Authority role: `Observability.Viewer`)*`obs:read`, `timeline:read`, `evidence:read`, `attest:read`.
- **`role/observability-investigator`** *(Authority role: `Observability.Investigator`)*`obs:read`, `timeline:read`, `timeline:write`, `evidence:read`, `evidence:create`, `attest:read`.
- **`role/observability-legal`** *(Authority role: `Observability.Legal`)*`evidence:read`, `evidence:hold`.
- **`role/observability-incident-commander`** *(Authority role: `Observability.IncidentCommander`)*`obs:read`, `obs:incident`, `timeline:read`, `timeline:write`, `evidence:create`, `evidence:read`, `attest:read`.
- **`role/airgap-viewer`** → `airgap:status:read`.
- **`role/airgap-operator`** → `airgap:status:read`, `airgap:import`.
- **`role/airgap-admin`** → `airgap:status:read`, `airgap:import`, `airgap:seal`.
- **`role/exceptions-service`** → `exceptions:read`, `exceptions:write`.
- **`role/exceptions-approver`** → `exceptions:read`, `exceptions:approve`.
Roles are declared per tenant in `authority.yaml`:
```yaml
tenants:
- name: default
roles:
concelier-ingest:
scopes: [advisory:ingest, advisory:read]
signals-uploader:
scopes: [signals:write, signals:read, aoc:verify]
aoc-operator:
scopes: [aoc:verify, advisory:read, vex:read]
orch-viewer:
scopes: [orch:read]
orch-operator:
scopes: [orch:read, orch:operate]
policy-author:
scopes: [policy:author, policy:read, policy:simulate, findings:read]
policy-reviewer:
scopes: [policy:review, policy:read, policy:simulate, findings:read]
policy-approver:
scopes: [policy:approve, policy:review, policy:read, policy:simulate, findings:read]
policy-operator:
scopes: [policy:operate, policy:run, policy:activate, policy:read, policy:simulate, findings:read]
policy-auditor:
scopes: [policy:audit, policy:read, policy:simulate, findings:read]
policy-engine:
scopes: [effective:write, findings:read]
exceptions-service:
scopes: [exceptions:read, exceptions:write]
exceptions-approver:
scopes: [exceptions:read, exceptions:approve]
notify-viewer:
scopes: [notify.viewer]
notify-operator:
scopes: [notify.viewer, notify.operator]
notify-admin:
scopes: [notify.viewer, notify.operator, notify.admin]
observability-viewer:
scopes: [obs:read, timeline:read, evidence:read, attest:read]
observability-investigator:
scopes: [obs:read, timeline:read, timeline:write, evidence:read, evidence:create, attest:read]
observability-legal:
scopes: [evidence:read, evidence:hold]
observability-incident-commander:
scopes: [obs:read, obs:incident, timeline:read, timeline:write, evidence:create, evidence:read, attest:read]
```
> **MFA requirement:** When any `exceptions.routingTemplates` entry sets `requireMfa: true`, Authority refuses to mint tokens containing `exceptions:approve` unless the authenticating identity provider advertises MFA support. Password/OIDC flows produce `authority.password.grant` audit events with `reason="Exception approval scope requires an MFA-capable identity provider."` when the requirement is violated.
---
## 2·Tenancy enforcement
### 2.1Token claims
Tokens now include:
- `tenant` claim (string) — required for all ingestion and verification scopes.
- `service_identity` (optional) — e.g., `policy-engine`, `cartographer`. Required when requesting `effective:write` or `graph:write`.
- `delegation_allowed` (boolean) — defaults `false`. Prevents console tokens from delegating ingest scopes.
Authority rejects requests when:
- `tenant` is missing while requesting `advisory:ingest`, `advisory:read`, `vex:ingest`, `vex:read`, or `aoc:verify` scopes.
- `aoc:verify` is absent while tokens request `advisory:read`, `vex:read`, or any `signals:*` scope (`invalid_scope` with deterministic message).
- `service_identity != policy-engine` but `effective:write` is present (`ERR_AOC_006` enforcement).
- `service_identity != cartographer` but `graph:write` is present (graph pipeline enforcement).
- Tokens attempt to combine `advisory:ingest` with `effective:write` (separation of duties).
- `exceptions:approve` is requested by a client without a tenant assignment or via an identity provider lacking MFA when `RequireMfaForApprovals=true`.
### 2.2Propagation
- API Gateway forwards `tenant` claim as header (`X-Stella-Tenant`). Services refuse requests lacking the header.
- Concelier/Excititor stamp tenant into raw documents and structured logs.
- Policy Engine copies `tenant` from tokens into `effective_finding_*` collections.
- Exception lifecycle services persist tenant and the selected routing template identifier alongside approval decisions. Authority audit events (`authority.password.grant`, `authority.client_credentials.grant`) surface `audit.scopes` and, on denials, a `scope.invalid` metadata entry so operators can trace exception approval attempts without inspecting downstream services.
### 2.3Cross-tenant scenarios
- Platform operators with `tenant:admin` can assume other tenants via `/authority/tenant/switch` if explicitly permitted.
- CLI commands accept `--tenant <id>` to override environment default; Authority logs tenant switch events (`authority.tenant.switch`).
- Console tenant picker uses delegated token exchange (`/token/exchange`) to obtain scoped tenant tokens without exposing raw credentials.
---
## 3·Configuration changes
### 3.1Authority configuration (`authority.yaml`)
Add new scopes and optional claims transformations:
```yaml
security:
scopes:
- name: advisory:ingest
description: Concelier raw ingestion (append-only)
- name: advisory:read
description: Read Concelier advisories and guard verdicts
- name: vex:ingest
description: Excititor raw ingestion
- name: vex:read
description: Read Excititor VEX records
- name: aoc:verify
description: Run AOC verification
- name: airgap:status:read
description: Read air-gap sealing status and staleness indicators
- name: airgap:import
description: Import offline bundles into the air-gapped catalog
- name: airgap:seal
description: Seal or unseal the installation during change control
- name: effective:write
description: Policy Engine materialisation
- name: findings:read
description: Read derived findings
- name: graph:write
description: Cartographer build submissions
- name: graph:read
description: Read graph overlays
- name: graph:export
description: Export graph artefacts
- name: graph:simulate
description: Run graph what-if simulations
- name: vuln:read
description: Read Vuln Explorer data
claimTransforms:
- match: { scope: "effective:write" }
require:
serviceIdentity: policy-engine
- match: { scope: "graph:write" }
require:
serviceIdentity: cartographer
```
### 3.2Client registration
Update service clients:
- `Concelier.WebService` → request `advisory:ingest`, `advisory:read`.
- `Excititor.WebService` → request `vex:ingest`, `vex:read`.
- `Policy.Engine` → request `effective:write`, `findings:read`; set `properties.serviceIdentity=policy-engine`.
- `Cartographer.Service` → request `graph:write`, `graph:read`; set `properties.serviceIdentity=cartographer`.
- `Graph API Gateway` → request `graph:read`, `graph:export`, `graph:simulate`; tenant hint required.
- `Console` → request `advisory:read`, `vex:read`, `aoc:verify`, `findings:read`, `vuln:read` plus existing UI scopes.
- `CLI automation` → request `aoc:verify`, `advisory:read`, `vex:read` as needed.
Client definition snippet:
```yaml
clients:
- clientId: concelier-web
grantTypes: [client_credentials]
scopes: [advisory:ingest, advisory:read]
tenants: [default]
- clientId: policy-engine
grantTypes: [client_credentials]
scopes: [effective:write, findings:read]
properties:
serviceIdentity: policy-engine
- clientId: cartographer-service
grantTypes: [client_credentials]
scopes: [graph:write, graph:read]
properties:
serviceIdentity: cartographer
```
---
## 4·Operational safeguards
- **Audit events:** Authority emits `authority.scope.granted` and `authority.scope.revoked` events with `scope` and `tenant`. Monitor for unexpected grants.
- **Rate limiting:** Apply stricter limits on `/token` endpoints for clients requesting `advisory:ingest` or `vex:ingest` to mitigate brute-force ingestion attempts.
- **Incident response:** Link AOC alerts to Authority audit logs to confirm whether violations come from expected identities.
- **Rotation:** Rotate ingest client secrets alongside guard deployments; add rotation steps to `ops/authority-key-rotation.md`.
- **Testing:** Integration tests must fail if tokens lacking `tenant` attempt ingestion; add coverage in Concelier/Excititor smoke suites (see `CONCELIER-CORE-AOC-19-013`).
---
## 5·Offline & air-gap notes
- Offline Kit bundles include tenant-scoped service credentials. Ensure ingest bundles ship without `advisory:ingest` scopes unless strictly required.
- CLI verification in offline environments uses pre-issued `aoc:verify` tokens; document expiration and renewal processes.
- Authority replicas in air-gapped environments should restrict scope issuance to known tenants and log all `/token` interactions for later replay.
---
## 6·References
- [Aggregation-Only Contract reference](../ingestion/aggregation-only-contract.md)
- [Architecture overview](../modules/platform/architecture-overview.md)
- [Concelier architecture](../modules/concelier/architecture.md)
- [Excititor architecture](../modules/excititor/architecture.md)
- [Policy governance](policy-governance.md)
- [Authority key rotation playbook](../modules/authority/operations/key-rotation.md)
---
## 7·Compliance checklist
- [ ] Scope catalogue updated in Authority configuration templates.
- [ ] Role mappings documented for each tenant profile.
- [ ] Claim transforms enforce `serviceIdentity` for `effective:write`.
- [ ] Claim transforms enforce `serviceIdentity` for `graph:write`.
- [ ] Concelier/Excititor smoke tests cover missing tenant rejection.
- [ ] Offline kit credentials reviewed for least privilege.
- [ ] Audit/monitoring guidance validated with Observability Guild.
- [ ] Authority Core sign-off recorded (owner: @authority-core, due 2025-10-28).
---
*Last updated: 2025-10-27 (Sprint19).*
---
## 7·Compliance checklist
- [ ] Scope catalogue updated in Authority configuration templates.
- [ ] Role mappings documented for each tenant profile.
- [ ] Claim transforms enforce `serviceIdentity` for `effective:write`.
- [ ] Claim transforms enforce `serviceIdentity` for `graph:write`.
- [ ] Concelier/Excititor smoke tests cover missing tenant rejection.
- [ ] Offline kit credentials reviewed for least privilege.
- [ ] Audit/monitoring guidance validated with Observability Guild.
- [ ] Authority Core sign-off recorded (owner: @authority-core, due 2025-10-28).
---
*Last updated: 2025-10-27 (Sprint19).*

View File

@@ -52,14 +52,16 @@ The console client is registered in Authority as `console-ui` with scopes:
| Policy approvals | `policy:read`, `policy:review`, `policy:approve`, `policy:operate`, `policy:simulate` | `policy:operate` (promote/activate/run) requires fresh-auth. |
| Observability panes (status ticker, telemetry) | `ui.telemetry`, `scheduler:runs.read`, `advisory:read`, `vex:read` | `ui.telemetry` drives OTLP export toggles. |
| Orchestrator dashboard (queues, workers, rate limits) | `orch:read` | Provision via `Orch.Viewer` role; read-only access to job state and telemetry. |
| Orchestrator control actions (pause/resume, retry, sync-now, backfill) | `orch:operate` (plus `orch:read`) | CLI/Console must request tokens with `operator_reason` and `operator_ticket`; Authority denies issuance when either value is missing. |
| Orchestrator control actions (pause/resume, retry, sync-now, backfill) | `orch:operate` (plus `orch:read`) | CLI/Console must request tokens with `operator_reason` and `operator_ticket`; Authority denies issuance when either value is missing. |
| Orchestrator quota & burst controls | `orch:quota` (plus `orch:read`, `orch:operate`) | Tokens must include `quota_reason` (≤256 chars); optional `quota_ticket` (≤128 chars) is captured for audit. |
| Downloads parity (SBOM, attestation) | `downloads:read`, `attestation:verify`, `sbom:export` | Console surfaces digests only; download links require CLI parity for write operations. |
Guidance:
- **Role mapping**: Provision Authority role `role/ui-console-admin` encapsulating the admin scopes above.
- **Orchestrator viewers**: Assign Authority role `role/orch-viewer` (Authority role string `Orch.Viewer`) to consoles that require read-only access to Orchestrator telemetry.
- **Orchestrator operators**: Assign Authority role `role/orch-operator` (Authority role string `Orch.Operator`) to identities allowed to pause/resume or backfill. Tokens must include `operator_reason` (≤256 chars) and `operator_ticket` (≤128 chars); Authority records the values in audit logs.
- **Role mapping**: Provision Authority role `role/ui-console-admin` encapsulating the admin scopes above.
- **Orchestrator viewers**: Assign Authority role `role/orch-viewer` (Authority role string `Orch.Viewer`) to consoles that require read-only access to Orchestrator telemetry.
- **Orchestrator operators**: Assign Authority role `role/orch-operator` (Authority role string `Orch.Operator`) to identities allowed to pause/resume or backfill. Tokens must include `operator_reason` (≤256 chars) and `operator_ticket` (≤128 chars); Authority records the values in audit logs.
- **Orchestrator admins**: Assign Authority role `role/orch-admin` (Authority role string `Orch.Admin`) to the handful of identities permitted to raise/lower quotas or trigger bulk backfills. Tokens must include `quota_reason` (≤256 chars); provide `quota_ticket` (≤128 chars) when available so Authority audit streams capture the change record.
- **Tenant enforcement**: Gateway injects `X-Stella-Tenant` from token claims. Requests missing the header must be rejected by downstream services (Concelier, Excititor, Policy Engine) and logged.
- **Separation of duties**: Never grant `ui.admin` and `policy:approve`/`policy:operate` to the same human role without SOC sign-off; automation accounts should use least-privilege dedicated clients.

View File

@@ -1,165 +1,165 @@
> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.
# Pack Signing & RBAC Controls
This document defines signing, verification, and authorization requirements for Task Packs across the CLI, Packs Registry, Task Runner, and Offline Kit. It aligns with Authority sprint tasks (`AUTH-PACKS-41-001`, `AUTH-PACKS-43-001`) and security guild expectations.
---
## 1·Threat Model Highlights
| Threat | Mitigation |
|--------|------------|
| Unsigned or tampered pack uploaded to registry | Mandatory cosign/DSSE verification before acceptance. |
| Unauthorized user publishing or promoting packs | Authority scopes (`Packs.Write`) + registry policy checks. |
| Privilege escalation during approvals | Approval gates require `Packs.Approve` + audit logging; fresh-auth recommended. |
| Secret exfiltration via pack steps | Secrets injection sandbox with redaction, sealed-mode network guardrails, evidence review. |
| Replay of old approval tokens | Approval payloads carry plan hash + expiry; Task Runner rejects mismatches. |
| Malicious pack in Offline Kit | Mirror verification using signed manifest and DSSE provenance. |
---
## 2·Signing Requirements
- **Cosign** signatures required for all bundles. Keys can be:
- Keyless (Fulcio OIDC).
- KMS-backed (HSM, cloud KMS).
- Offline keys stored in secure vault (air-gapped mode).
- **DSSE Attestations** recommended to embed:
- Manifest digest.
- Build metadata (repo, commit, CI run).
- CLI version (`stella/pack`).
- Signatures stored alongside bundle in registry object storage.
- `stella pack push` refuses to publish without signature (unless `--insecure-publish` used in dev).
- Registry enforces trust policy:
| Policy | Description |
|--------|-------------|
| `anyOf` | Accepts any key in configured trust store. |
| `keyRef` | Accepts specific key ID (`kid`). |
| `oidcIssuer` | Accepts Fulcio certificates from allowed issuers (e.g., `https://fulcio.sigstore.dev`). |
| `threshold` | Requires N-of-M signatures (future release). |
---
## 3·RBAC & Scopes
Authority exposes pack-related scopes:
| Scope | Description |
|-------|-------------|
| `Packs.Read` | View packs, download manifests/bundles. |
| `Packs.Write` | Publish, promote, deprecate packs. |
| `Packs.Run` | Execute packs (Task Runner, CLI). |
| `Packs.Approve` | Approve pack gates, override tenant visibility. |
### 3.1 Role Mapping
| Role | Scopes | Use Cases |
|------|--------|-----------|
| `pack.viewer` | `Packs.Read` | Inspect packs, plan runs. |
| `pack.publisher` | `Packs.Read`, `Packs.Write` | Publish new versions, manage channels. |
| `pack.operator` | `Packs.Read`, `Packs.Run` | Execute packs, monitor runs. |
| `pack.approver` | `Packs.Read`, `Packs.Approve` | Fulfil approvals, authorize promotions. |
| `pack.admin` | All | Full lifecycle management (rare). |
Roles are tenant-scoped; cross-tenant access requires explicit addition.
### 3.2 CLI Enforcement
- CLI requests scopes based on command:
- `stella pack plan``Packs.Read`.
- `stella pack run``Packs.Run`.
- `stella pack push``Packs.Write`.
- `stella pack approve``Packs.Approve`.
- Offline tokens must include same scopes; CLI warns if missing.
---
## 4·Approvals & Fresh Auth
- Approval commands require recent fresh-auth (<5minutes). CLI prompts automatically; Console enforces via Authority.
- Approval payload includes:
- `runId`
- `gateId`
- `planHash`
- `approver`
- `timestamp`
- Task Runner logs approval event and verifies plan hash to prevent rerouting.
---
## 5·Secret Management
- Secrets defined in pack manifest map to Authority secret providers (e.g., HSM, Vault).
- Task Runner obtains secrets using service account with scoped access; CLI may prompt or read from profile.
- Secret audit trail:
- `secretRequested` event with reason, pack, step.
- `secretDelivered` event omitted (only aggregate metrics) to avoid leakage.
- Evidence bundle includes hashed secret metadata (no values).
Sealed mode requires secrets to originate from sealed vault; external endpoints blocked.
---
## 6·Audit & Evidence
- Registry, Task Runner, and Authority emit audit events to central timeline.
- Required events:
- `pack.version.published`
- `pack.version.promoted`
- `pack.run.started/completed`
- `pack.approval.requested/granted`
- `pack.secret.requested`
- Evidence Locker stores DSSE attestations and run bundles for 90days (configurable).
- Auditors can use `stella pack audit --run <id>` to retrieve audit trail.
---
## 7·Offline / Air-Gap Policies
- Offline Kit includes:
- Pack bundles + signatures.
- Trusted key store (`trust-bundle.pem`).
- Approval workflow instructions for manual signing.
- Air-gapped approvals:
- CLI generates approval request file (`.approval-request.json`).
- Approver uses offline CLI to sign with offline key.
- Response imported to Task Runner.
- Mirror process verifies signatures prior to import; failure aborts import with `ERR_PACK_SIGNATURE_INVALID`.
---
## 8·Incident Response
- Compromised pack signature:
- Revoke key via Authority trust store.
- Deprecate affected versions (`registry deprecate`).
- Notify consumers via Notifier (`pack.security.alert`).
- Forensically review run evidence for impacted tenants.
- Unauthorized approval:
- Review audit log for `Packs.Approve` events.
- Trigger `pack.run.freeze` (pauses run pending investigation).
- Rotate approver credentials and require fresh-auth.
- Secret leak suspicion:
- Quarantine evidence bundles.
- Rotate secrets referenced by pack.
- Run sealed-mode audit script to confirm guardrails.
---
## 9·Compliance Checklist
- [ ] Signing requirements (cosign/DSSE, trust policies) documented.
- [ ] Authority scope mapping and CLI enforcement captured.
- [ ] Approval workflow + fresh-auth expectations defined.
- [ ] Secret lifecycle (request, injection, audit) described.
- [ ] Audit/evidence integration noted (timeline, Evidence Locker).
- [ ] Offline/air-gap controls outlined.
- [ ] Incident response playbook provided.
- [ ] Imposed rule reminder retained at top.
---
*Last updated: 2025-10-27 (Sprint43).*
> **Imposed rule:** Work of this type or tasks of this type on this component must also be applied everywhere else it should be applied.
# Pack Signing & RBAC Controls
This document defines signing, verification, and authorization requirements for Task Packs across the CLI, Packs Registry, Task Runner, and Offline Kit. It aligns with Authority sprint tasks (`AUTH-PACKS-41-001`, `AUTH-PACKS-43-001`) and security guild expectations.
---
## 1·Threat Model Highlights
| Threat | Mitigation |
|--------|------------|
| Unsigned or tampered pack uploaded to registry | Mandatory cosign/DSSE verification before acceptance. |
| Unauthorized user publishing or promoting packs | Authority scopes (`packs.write`) + registry policy checks. |
| Privilege escalation during approvals | Approval gates require `packs.approve` + audit logging; fresh-auth recommended. |
| Secret exfiltration via pack steps | Secrets injection sandbox with redaction, sealed-mode network guardrails, evidence review. |
| Replay of old approval tokens | Approval payloads carry plan hash + expiry; Task Runner rejects mismatches. |
| Malicious pack in Offline Kit | Mirror verification using signed manifest and DSSE provenance. |
---
## 2·Signing Requirements
- **Cosign** signatures required for all bundles. Keys can be:
- Keyless (Fulcio OIDC).
- KMS-backed (HSM, cloud KMS).
- Offline keys stored in secure vault (air-gapped mode).
- **DSSE Attestations** recommended to embed:
- Manifest digest.
- Build metadata (repo, commit, CI run).
- CLI version (`stella/pack`).
- Signatures stored alongside bundle in registry object storage.
- `stella pack push` refuses to publish without signature (unless `--insecure-publish` used in dev).
- Registry enforces trust policy:
| Policy | Description |
|--------|-------------|
| `anyOf` | Accepts any key in configured trust store. |
| `keyRef` | Accepts specific key ID (`kid`). |
| `oidcIssuer` | Accepts Fulcio certificates from allowed issuers (e.g., `https://fulcio.sigstore.dev`). |
| `threshold` | Requires N-of-M signatures (future release). |
---
## 3·RBAC & Scopes
Authority exposes pack-related scopes:
| Scope | Description |
|-------|-------------|
| `packs.read` | View packs, download manifests/bundles. |
| `packs.write` | Publish, promote, deprecate packs. |
| `packs.run` | Execute packs (Task Runner, CLI). |
| `packs.approve` | Approve pack gates, override tenant visibility. |
### 3.1 Role Mapping
| Role | Scopes | Use Cases |
|------|--------|-----------|
| `pack.viewer` | `packs.read` | Inspect packs, plan runs. |
| `pack.publisher` | `packs.read`, `packs.write` | Publish new versions, manage channels. |
| `pack.operator` | `packs.read`, `packs.run` | Execute packs, monitor runs. |
| `pack.approver` | `packs.read`, `packs.approve` | Fulfil approvals, authorize promotions. |
| `pack.admin` | All | Full lifecycle management (rare). |
Roles are tenant-scoped; cross-tenant access requires explicit addition.
### 3.2 CLI Enforcement
- CLI requests scopes based on command:
- `stella pack plan``packs.read`.
- `stella pack run``packs.run`.
- `stella pack push``packs.write`.
- `stella pack approve``packs.approve`.
- Offline tokens must include same scopes; CLI warns if missing.
---
## 4·Approvals & Fresh Auth
- Approval commands require recent fresh-auth (<5minutes). CLI prompts automatically; Console enforces via Authority.
- Approval payload includes:
- `runId`
- `gateId`
- `planHash`
- `approver`
- `timestamp`
- Task Runner logs approval event and verifies plan hash to prevent rerouting.
---
## 5·Secret Management
- Secrets defined in pack manifest map to Authority secret providers (e.g., HSM, Vault).
- Task Runner obtains secrets using service account with scoped access; CLI may prompt or read from profile.
- Secret audit trail:
- `secretRequested` event with reason, pack, step.
- `secretDelivered` event omitted (only aggregate metrics) to avoid leakage.
- Evidence bundle includes hashed secret metadata (no values).
Sealed mode requires secrets to originate from sealed vault; external endpoints blocked.
---
## 6·Audit & Evidence
- Registry, Task Runner, and Authority emit audit events to central timeline.
- Required events:
- `pack.version.published`
- `pack.version.promoted`
- `pack.run.started/completed`
- `pack.approval.requested/granted`
- `pack.secret.requested`
- Dashboards should track the `authority.pack_scope_violation` tag alongside `authority.aoc_scope_violation` to highlight mis-scoped automation clients. Break down counts by `authority.client_id` to surface stale Task Runner or registry configurations quickly.
- Evidence Locker stores DSSE attestations and run bundles for 90days (configurable).
- Auditors can use `stella pack audit --run <id>` to retrieve audit trail.
---
## 7·Offline / Air-Gap Policies
- Offline Kit includes:
- Pack bundles + signatures.
- Trusted key store (`trust-bundle.pem`).
- Approval workflow instructions for manual signing.
- Air-gapped approvals:
- CLI generates approval request file (`.approval-request.json`).
- Approver uses offline CLI to sign with offline key.
- Response imported to Task Runner.
- Mirror process verifies signatures prior to import; failure aborts import with `ERR_PACK_SIGNATURE_INVALID`.
---
## 8·Incident Response
- Compromised pack signature:
- Revoke key via Authority trust store.
- Deprecate affected versions (`registry deprecate`).
- Notify consumers via Notifier (`pack.security.alert`).
- Forensically review run evidence for impacted tenants.
- Unauthorized approval:
- Review audit log for `packs.approve` events.
- Trigger `pack.run.freeze` (pauses run pending investigation).
- Rotate approver credentials and require fresh-auth.
- Secret leak suspicion:
- Quarantine evidence bundles.
- Rotate secrets referenced by pack.
- Run sealed-mode audit script to confirm guardrails.
---
## 9·Compliance Checklist
- [ ] Signing requirements (cosign/DSSE, trust policies) documented.
- [ ] Authority scope mapping and CLI enforcement captured.
- [ ] Approval workflow + fresh-auth expectations defined.
- [ ] Secret lifecycle (request, injection, audit) described.
- [ ] Audit/evidence integration noted (timeline, Evidence Locker).
- [ ] Offline/air-gap controls outlined.
- [ ] Incident response playbook provided.
- [ ] Imposed rule reminder retained at top.
---
*Last updated: 2025-10-27 (Sprint43).*