mirror of
https://github.com/trustgraph-ai/trustgraph.git
synced 2026-05-19 12:25:13 +02:00
Adds `no-auth-svc`, a lightweight IAM service that permits all access unconditionally — no database, no bootstrap, no signing keys. Deploy it in place of `iam-svc` for development, demos, and single-user setups where authentication overhead is unwanted. The gateway no longer hard-codes a 401 on missing credentials. Instead it asks the IAM regime via a new `authenticate-anonymous` operation whether token-free access is allowed. This keeps the gateway regime-agnostic: `iam-svc` rejects anonymous auth (preserving existing security), while `no-auth-svc` grants it with a configurable default user and workspace. Includes a tech spec (docs/tech-specs/no-auth-regime.md) and tests that pin the safety boundary — malformed tokens never fall through to the anonymous path, and a contract test ensures the full iam-svc always rejects `authenticate-anonymous`.
186 lines
6.4 KiB
Markdown
186 lines
6.4 KiB
Markdown
---
|
|
layout: default
|
|
title: "No-Auth IAM Regime"
|
|
parent: "Tech Specs"
|
|
---
|
|
|
|
# No-Auth IAM Regime
|
|
|
|
## Overview
|
|
|
|
A minimal IAM regime that permits all access unconditionally.
|
|
Implements the same Pulsar request/response protocol as `iam-svc`
|
|
(see [iam-contract.md](iam-contract.md)) so it is a drop-in
|
|
replacement: swap `iam-svc` for `no-auth-svc` in the deployment
|
|
and the gateway, bootstrapper, and all other components continue
|
|
to work without modification.
|
|
|
|
Intended for development, testing, single-tenant self-hosted
|
|
deployments, and evaluation environments where authentication
|
|
overhead is unwanted.
|
|
|
|
## Motivation
|
|
|
|
The full IAM regime requires Cassandra tables, a bootstrap
|
|
sequence, API key management, and signing key rotation. For
|
|
many deployments this is unnecessary friction:
|
|
|
|
- Local development and CI/CD pipelines.
|
|
- Single-user or small-team self-hosted instances.
|
|
- Evaluation and demo environments.
|
|
- Deployments behind an external authentication proxy
|
|
(e.g. OAuth2 reverse proxy, VPN-gated access).
|
|
|
|
Today operators who want no auth must still deploy `iam-svc` and
|
|
complete the bootstrap ceremony. A purpose-built no-auth regime
|
|
eliminates that requirement entirely.
|
|
|
|
## Design
|
|
|
|
### Deployment
|
|
|
|
Replace `iam-svc` with `no-auth-svc` in the processor group or
|
|
container configuration. No other services change. The no-auth
|
|
service listens on the standard IAM Pulsar topics:
|
|
|
|
- Request: `request:<topicspace>:iam`
|
|
- Response: `response:<topicspace>:iam`
|
|
|
|
### Dependencies
|
|
|
|
None. No database, no config entries, no signing keys, no
|
|
bootstrap sequence.
|
|
|
|
### Operation responses
|
|
|
|
The service implements the IAM contract
|
|
([iam-contract.md](iam-contract.md)) with the following
|
|
behaviour for each operation:
|
|
|
|
| Operation | Behaviour |
|
|
|---|---|
|
|
| `authenticate-anonymous` | Returns a default identity: `user_id="anonymous"`, `workspace="default"`, `roles=["admin"]`. This is the key operation that distinguishes no-auth from the full regime. |
|
|
| `resolve-api-key` | Accepts any token. Returns the same default identity as `authenticate-anonymous`. |
|
|
| `authorise` | Always allows. Returns `decision_allow=True`, `decision_ttl_seconds=3600`. |
|
|
| `authorise-many` | Always allows all checks. |
|
|
| `get-signing-key-public` | Returns an empty string. The gateway skips JWT validation when no key is available. |
|
|
| `bootstrap` | No-op. Returns empty admin user/key. |
|
|
| `bootstrap-status` | Returns `bootstrap_available=False`. |
|
|
| `whoami` | Returns a stub user record for the actor. |
|
|
| `login` | Returns empty JWT (not supported under no-auth). |
|
|
| `create-user`, `list-users`, `get-user`, `update-user`, `delete-user`, `disable-user`, `enable-user` | Return empty/stub responses. User management is meaningless without auth. |
|
|
| `create-workspace`, `list-workspaces`, `get-workspace`, `update-workspace`, `disable-workspace` | Return empty/stub responses. |
|
|
| `create-api-key`, `list-api-keys`, `revoke-api-key` | Return empty/stub responses. |
|
|
| `change-password`, `reset-password` | No-op. |
|
|
| `rotate-signing-key` | No-op. |
|
|
| Unknown operation | Returns an error response (same as `iam-svc`). |
|
|
|
|
### Workspace resolution
|
|
|
|
When `resolve-api-key` is called, the returned workspace
|
|
determines which workspace the request operates against. The
|
|
no-auth service defaults to `"default"`.
|
|
|
|
A configurable `--default-workspace` flag allows operators to
|
|
change this without code changes.
|
|
|
|
### Anonymous authentication
|
|
|
|
A new `authenticate-anonymous` operation is added to the IAM
|
|
protocol. This is a small, backward-compatible addition to the
|
|
contract:
|
|
|
|
**Gateway change** (`auth.py`): when `authenticate()` receives a
|
|
request with no `Authorization` header (or an empty bearer
|
|
token), instead of immediately returning 401, it sends an
|
|
`authenticate-anonymous` request to the IAM service. If the
|
|
regime returns a valid identity, the request proceeds. If the
|
|
regime returns an error, the gateway returns 401 as before.
|
|
|
|
**`iam-svc` (full regime)**: returns `auth-failed` for
|
|
`authenticate-anonymous`. Behaviour is unchanged — unauthenticated
|
|
requests are rejected exactly as they are today.
|
|
|
|
**`no-auth-svc`**: returns the default identity (`anonymous` /
|
|
`default` workspace). No token required.
|
|
|
|
This keeps the policy decision ("is anonymous access allowed?")
|
|
in the IAM regime, not in the gateway. The gateway is a generic
|
|
enforcement point that asks and respects the answer.
|
|
|
|
**Wire format**: uses the existing `IamRequest` / `IamResponse`
|
|
schema with `operation="authenticate-anonymous"`. No new fields
|
|
required — the response uses `resolved_user_id`,
|
|
`resolved_workspace`, and `resolved_roles`, same as
|
|
`resolve-api-key`.
|
|
|
|
Requests that do carry a bearer token follow the existing
|
|
`resolve-api-key` / JWT paths unchanged.
|
|
|
|
## Implementation
|
|
|
|
### Service structure
|
|
|
|
The service is a standard `AsyncProcessor` that consumes IAM
|
|
requests and produces IAM responses, identical in shape to the
|
|
existing `iam-svc` processor:
|
|
|
|
```
|
|
trustgraph-flow/
|
|
trustgraph/
|
|
iam/
|
|
noauth/
|
|
__init__.py
|
|
__main__.py
|
|
service.py # AsyncProcessor wiring
|
|
handler.py # Operation dispatch, always-allow logic
|
|
```
|
|
|
|
### Handler
|
|
|
|
The handler is a single `handle(request) -> response` function
|
|
with a dispatch table. Each operation returns a pre-built
|
|
`IamResponse` with the appropriate fields set. No database
|
|
access, no crypto, no state.
|
|
|
|
### Configuration
|
|
|
|
| Flag | Default | Description |
|
|
|---|---|---|
|
|
| `--default-workspace` | `"default"` | Workspace returned by `resolve-api-key` |
|
|
| `--default-user-id` | `"anonymous"` | User ID returned by `resolve-api-key` |
|
|
|
|
### Entry point
|
|
|
|
```
|
|
tg-no-auth-svc
|
|
```
|
|
|
|
Or via processor group:
|
|
|
|
```yaml
|
|
- class: trustgraph.iam.noauth.Processor
|
|
params:
|
|
<<: *defaults
|
|
id: no-auth-svc
|
|
```
|
|
|
|
## Security considerations
|
|
|
|
This regime provides **no security whatsoever**. Any caller with
|
|
network access to the API gateway has full admin access to all
|
|
workspaces.
|
|
|
|
Operators must ensure that network-level controls (firewall,
|
|
VPN, private network) provide adequate protection when deploying
|
|
this regime. The regime is explicitly not suitable for multi-
|
|
tenant or internet-facing deployments.
|
|
|
|
## Testing
|
|
|
|
- Unit: verify each operation returns the expected stub response.
|
|
- Integration: deploy `no-auth-svc` in place of `iam-svc`, confirm
|
|
the gateway starts, accepts requests with a dummy bearer token,
|
|
and routes them to the default workspace.
|
|
- E2E: run the standard e2e test suite with `no-auth-svc` to
|
|
confirm no regressions.
|