generated from coulomb/repo-seed
108 lines
4.2 KiB
Markdown
108 lines
4.2 KiB
Markdown
# 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.
|