ADORSYS-GIS / ADORSYS-GIS/lightbridge-authz

[Story]: Authenticated multi-source ingest — source identity from credential, never payload

Aberta
#585 1 comentário 0 reações 1 responsável Reivindicada por @Guy-Ghis Ver no GitHub
user-story
Linguagem predominante
Rust
Estrelas
0
Forks
1
Merge médio
6h 42min
PRs com merge (30d)
246

Descrição

Parent epic: #581

### Story Statement

As a security owner, I know every non-gateway telemetry row in the usage store entered through an authenticated door whose credential names the collector — developer-attributed data never rides the unauthenticated listener.

### Real Intent

ADR-0027 Decision 4 makes authenticated ingest a **prerequisite** of any non-gateway source going live. This story builds that door: per-collector identity for in-cluster callers, the aiCliOtel collector path for laptop CLIs, and refusal tests for every pattern.

### Background and Context

The current ingest listener is unauthenticated by design — acceptable only because its sole emitter (the gateway's Envoy sink) is pinned by deployment topology and the data carries no developer attribution. #535 named this the strongest argument against consolidation; governance#169/#191 already scoped the fix pattern for in-cluster callers (per-collector projected ServiceAccount tokens, `kubernetesTokenReview` — in production use on this cluster), sidestepping the authz-idp M2M gap (#534). Laptop CLIs already have a path: the `aiCliOtel` collector OIDC-validates authz-issued tokens (once governance#84's wrong-issuer 401 is fixed) and can forward with workload identity.

### Source of truth (links)

ADR-0027 Decision 4 · #534 · governance#160 · governance#169 · governance#170 · governance#191 · governance#84 · governance ADR-0013 invariant 2

### Acceptance Criteria

1. A distinct authenticated ingest surface (listener or route class) for multi-source telemetry; the trusted source string is bound to the presented credential, not to any payload field.
2. In-cluster collectors authenticate with per-collector projected SA tokens (audience names the endpoint); the stored principal is the SA identity.
3. The aiCliOtel forwarding path presents workload identity to usage; end-to-end proven with a **live 200** from a real CLI push (governance#189's bar), not a clean collector start.
4. Refusal tests, each written to fail first: no credential; wrong audience; disallowed principal; auth-dependency unreachable ⇒ refusal, never accept (fail-closed). No env-var opt-out that can silently skip them in CI (governance#170).
5. The gateway's existing path is unchanged in this story and documented as the one deliberate exception, with its topology pinning stated.

### Out of Scope

authz-idp `client_credentials` (that's #534's own decision); rotating the gateway path onto workload identity; Codex/VS Code static-credential gap (governance#144).

### Dependencies and Blockers

governance#84 (issuer fix) for the CLI leg; coordination with governance#169 so the SA-token pattern is implemented once, consistently.

### Assumptions

TokenReview-based validation is reachable from the usage pod (same cluster). If usage ever runs outside the cluster, this decision reopens.

### Implementation Notes

Keep the fail-closed posture symmetrical with the rest of the platform: unavailable validator ⇒ refuse, never `unwrap_or(true)`. Constant-time comparisons where shared secrets appear transitionally — but no new shared secrets: governance#191 removes `X-Internal-Token`, it must not reappear here.

### Test Expectations

Per-pattern refusal tests (fail-first, then guard); a dependency-down test asserting refusal; live-push integration evidence.

### Verification evidence

To be attached on the implementing PR.

### Human accountable owner

Stephane Segning Lambou

### AI Usage
AI-assisted (Claude): research and drafting. Reviewed and owned by Stephane Segning Lambou.

### Design addendum (2026-08-31): collector fan-out is the canonical ingest topology

Settled with the repo owner: **everyone writes to the authenticated edge OTEL collector** (the `aiCliOtel` pattern), which stamps the trusted `source` after OIDC validation and fans out **at the edge**, in parallel legs: (1) Alloy → Mimir/Loki/Tempo (observability copy), (2) the authz-usage governed ingest, (3) the raw OTLP object-storage archive (see the raw-archive story, #589). Consequences for this story's ACs:

- AC 3's aiCliOtel forwarding path is not one option among several — it is the canonical door for push sources; the usage-side authenticated surface primarily trusts the collector's workload identity plus its stamped source.
- The authz leg attaches to the **edge collector**, not behind Alloy: the governed/billing path must not share fate with the observability pipeline, and the source stamp must not have to survive an extra hop.
- Pull sources may adopt the same door by emitting OTLP (see governance#196's addendum) — the per-collector SA-token leg (AC 2) then covers the collector itself and any caller that cannot ride it.

Guia de contribuição

Abrir o guia de contribuição

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.