generated from coulomb/repo-seed
Implement Topaz adapter
This commit is contained in:
107
docs/topaz-adapter-operations.md
Normal file
107
docs/topaz-adapter-operations.md
Normal file
@@ -0,0 +1,107 @@
|
||||
# Topaz Adapter Operations
|
||||
|
||||
Status: implemented for FLEX-WP-0004 P4.1.
|
||||
|
||||
## Role
|
||||
|
||||
The Topaz adapter is a delegated PDP and directory adapter behind the
|
||||
stable flex-auth API. Protected systems still send `CheckRequest`,
|
||||
`BatchCheckRequest`, registry snapshots, and Rego-in-Markdown policy
|
||||
packages to flex-auth. The adapter translates those into Topaz directory
|
||||
objects, relations, permission checks, and an OPA bundle, then wraps the
|
||||
result back into the same `DecisionEnvelope` used by standalone mode.
|
||||
|
||||
## Wire Protocol
|
||||
|
||||
The production recommendation remains gRPC because it is Topaz's native
|
||||
API and gives the strongest typed client surface for authorizer,
|
||||
reader, writer, and model operations. The implementation added in P4.1
|
||||
keeps that choice behind `internal/adapters/topaz.Client` and ships an
|
||||
HTTP REST client for the runnable `examples/topaz` topology.
|
||||
|
||||
This split is deliberate:
|
||||
|
||||
- `Client` is the stable flex-auth boundary.
|
||||
- `HTTPClient` speaks the same REST endpoints used by the spike
|
||||
(`/api/v3/directory/check`, `/object`, `/relation`, `/manifest`).
|
||||
- A future gRPC client can replace `HTTPClient` without changing
|
||||
protected-system contracts or CARING envelope behavior.
|
||||
- Embedded Topaz remains out of scope because it would couple
|
||||
flex-auth releases to Topaz internals.
|
||||
|
||||
## Startup
|
||||
|
||||
1. Start Topaz with the manifest and bundle paths mounted. The
|
||||
`examples/topaz/docker-compose.yml` file is the local reference.
|
||||
2. Create a `topaz.HTTPClient` with the directory REST gateway URL.
|
||||
3. Configure a `topaz.FileBundleSink` that points at the mounted bundle
|
||||
directory.
|
||||
4. Build a `topaz.Adapter` with the client and policy metadata.
|
||||
5. Call `ImportManifest`, `ImportDirectory`, and `ImportPolicy` before
|
||||
accepting delegated checks.
|
||||
|
||||
For local verification:
|
||||
|
||||
```sh
|
||||
cd examples/topaz
|
||||
docker compose up --abort-on-container-exit --exit-code-from probe
|
||||
```
|
||||
|
||||
The Go integration test is present but skipped by default. Run it with:
|
||||
|
||||
```sh
|
||||
FLEX_AUTH_RUN_TOPAZ_INTEGRATION=1 go test ./internal/adapters/topaz
|
||||
```
|
||||
|
||||
## Directory Consistency
|
||||
|
||||
`ImportDirectory` converts the canonical registry snapshot into Topaz
|
||||
objects and relations. Subjects and service accounts become Topaz
|
||||
`user` objects. Each subject also receives an `identity:<subject>` object
|
||||
with an `identifier` relation to the user. Groups and teams become Topaz
|
||||
`group` objects; teams keep the `team:` prefix. Resources keep their
|
||||
canonical type names, labels, trust zone, path, owner, and system in
|
||||
properties.
|
||||
|
||||
Relation writes return an optional etag. The adapter records the latest
|
||||
etag in `DecisionEnvelope.provenance.directory_etag` when Topaz returns
|
||||
one. Reads may be served from flex-auth's local registry for explanation
|
||||
or from Topaz for authorization. The decision envelope must say which
|
||||
backend produced the answer through `provenance.evaluator` and
|
||||
`provenance.mode`.
|
||||
|
||||
## Policy Import
|
||||
|
||||
`ImportPolicy` extracts the validated Rego module from a
|
||||
Rego-in-Markdown package without translation. `FileBundleSink` writes:
|
||||
|
||||
- `.manifest` with the package root.
|
||||
- `policy/<package/path>.rego` with the exact extracted module.
|
||||
|
||||
This matches the local-bundle mode used by the Topaz example. Clustered
|
||||
Topaz deployments can replace the bundle sink with a remote bundle
|
||||
publisher without changing the adapter contract.
|
||||
|
||||
## Fail-Closed Defaults
|
||||
|
||||
Delegated checks do not leak backend errors to protected systems as
|
||||
ambiguous success. The adapter returns a deny envelope for:
|
||||
|
||||
- Topaz unavailable: `reason=topaz_unavailable`.
|
||||
- Stale directory: `reason=topaz_directory_stale`.
|
||||
- Partial result: `reason=topaz_partial_result`.
|
||||
- Untranslatable request: `reason=topaz_request_incomplete`.
|
||||
|
||||
Each failure includes a CARING conformance finding and
|
||||
`diagnostics.topaz_failure`. This keeps delegated mode behavior
|
||||
compatible with standalone fail-closed decisions and makes backend
|
||||
health visible to audits.
|
||||
|
||||
## CARING Preservation
|
||||
|
||||
The adapter preserves CARING descriptors from the request or backend
|
||||
result. It copies descriptor, restrictions, exposure modes, derived
|
||||
capabilities, conformance findings, and exposure-event hooks into the
|
||||
decision envelope. If no descriptor is available, the decision still
|
||||
contains a `TOPAZ-CARING-DESCRIPTOR-MISSING` warning so conformance
|
||||
checks can distinguish an authorization deny from a metadata gap.
|
||||
Reference in New Issue
Block a user