Files
git.stella-ops.org/docs/security/authority-scopes.md
root 68da90a11a
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
Restructure solution layout by module
2025-10-28 15:10:40 +02:00

262 lines
17 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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](../architecture/overview.md)
- [Concelier architecture](../ARCHITECTURE_CONCELIER.md)
- [Excititor architecture](../ARCHITECTURE_EXCITITOR.md)
- [Policy governance](policy-governance.md)
- [Authority key rotation playbook](../ops/authority-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).*