All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 37s
Closes the local protocol surface of gap G01 from the scope assessment (KEY-WP-0016). The browser grant validated PKCE, client id and scopes but left four bindings unenforced, and UserInfo verified less than the caller CLI does. Authorization-code path: bind the exchange to the redirect URI the code was issued for, refuse clients whose registration does not permit the grant, and authenticate confidential clients with a digest-based constant-time comparison over the same credential sources as the service grant. An empty grantTypes stays an implicit authorization-code client, matching config validation. Code consumption: SessionStore.Consume reads and deletes under one lock. The previous Get/Delete pair spanned JWT signing, and the added test reproduces the race against that version -- 9 of 16 concurrent exchanges succeeded, and a failed exchange left the code replayable. UserInfo: check the JOSE header algorithm before trusting the signature, require the configured issuer, and require an access token rather than accepting an ID token of the right shape. Purpose is decided on the scope claim so the issued token contract, which consumers pin exactly, does not change. SCOPE.md and the assessment record which bindings are now enforced and that the Authelia upstream-trust assumption remains open, so G01 is not fully closed and no profile-conformance claim is made. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NV9oijZukGyGbRQGGKnK4P Assistant: claude-code Assistant-Model: opus Assistant-Process: 713576@bnt-lap001 Assistant-Session: 384c511d-9bce-4cb8-a676-2aef6c0c8df6
116 lines
7.4 KiB
Markdown
116 lines
7.4 KiB
Markdown
# SCOPE
|
|
|
|
Reviewed 2026-09-05 against source revision `b989de4`.
|
|
|
|
## Purpose and boundary
|
|
|
|
KeyCape is Go identity **Tooling** for NetKingdom's lightweight IAM deployment.
|
|
It runs its own OIDC-style issuer, uses Authelia for upstream browser
|
|
authentication, reads identities from LLDAP, and delegates factor checks to
|
|
privacyIDEA. It also provides caller authentication commands, directory snapshot
|
|
validation, and migration artifact generators.
|
|
|
|
It issues identity, role, scope and assurance claims. Resource authorization
|
|
belongs to access-engine and consuming services; secret custody and OpenBao
|
|
policy/token enforcement belong to their platform owners. The implemented subset
|
|
supports NetKingdom integrations, but complete profile conformance and drop-in
|
|
Keycloak interchangeability are not established.
|
|
|
|
## Implemented capabilities
|
|
|
|
| Surface | What the current source provides |
|
|
| --- | --- |
|
|
| Issuer HTTP API | Discovery, `/authorize` and its callback/registration-return routes, `/token`, `/jwks`, `/userinfo`, local `/logout`, and `/healthz`. |
|
|
| Human authentication | Authorization code with S256 PKCE, exact registered redirects, scope allow-lists, Authelia login, privacyIDEA MFA challenges, client-specific assurance requirements, browser session reuse, step-up/fresh-login handling, and configured registration/enrollment handoffs. |
|
|
| Service authentication | Static confidential `client_credentials` clients authenticated with form-encoded `client_secret_basic`; configured subject, tenant, roles, scopes and per-client token lifetime. Secrets are resolved from environment references at startup. |
|
|
| Tokens and identity | Locally signed RS256 JWTs; configurable access-token resource audience while ID tokens retain the client audience; human/service principal types, tenant, groups, roles, scope and assurance claims. UserInfo resolves canonical directory subjects and filters profile/email/groups by scope. |
|
|
| Caller commands | `keycape login` for public-client browser PKCE login and `keycape service-token` for service exchange. HTTPS discovery/JWKS verification and private JSON token-file delivery outside Git; no token output on stdout. |
|
|
| Validation and migration | Canonical snapshot checks; LLDAP user/group/membership export; basic Keycloak realm JSON; LDIF generation for OpenLDAP, 389 Directory Server and AD targets. These generate artifacts rather than execute a complete migration. |
|
|
| Diagnostics and packaging | Structured authentication/enforcement/migration events, a process health response, Go build/test/vet targets, a container containing the KeyCape binary, and development/CI scaffolding. |
|
|
|
|
## Material limits
|
|
|
|
- Client registrations, service secrets and the signing key are loaded at startup.
|
|
Login, authorization and handoff state are process-local. There is no shared
|
|
session store, general refresh-token flow, token introspection/revocation API,
|
|
or automatic signing-key/client-secret rotation service. Logout clears the
|
|
local KeyCape session, not every upstream or downstream session/token.
|
|
- The optional tenant-engine `tenant_roles` adapter and handler support exist,
|
|
but the server entry point does not configure them. That claim is not an
|
|
enabled capability of the stock executable.
|
|
- The Keycloak CLI exports users/groups through the basic transformer and has
|
|
no client-list input. Library-level client mapping does not preserve the full
|
|
current service-identity, audience, tenant/role, MFA and lifetime contract.
|
|
Password and MFA credential migration is not supplied.
|
|
- Snapshot validation is a limited Go rule set, not full machine-readable schema
|
|
enforcement. The canonical YAML model and discovery metadata lag newer runtime
|
|
capabilities. The authorization-code grant now binds the redirect URI,
|
|
enforces grant-type eligibility, authenticates confidential clients and
|
|
consumes codes atomically, and UserInfo enforces algorithm, issuer and
|
|
access-token purpose (KEY-WP-0016). Upstream provider tokens from Authelia are
|
|
still accepted on a transport-trust assumption without signature or
|
|
issuer/audience verification; that gap remains open. Enforcing these bindings
|
|
is not complete profile conformance. See the assessment below.
|
|
- Tests cover local handlers, adapters, transformations and CLI protocol behavior.
|
|
They do not establish complete replacement against a running Keycloak/full-LDAP
|
|
stack. The Scenario B/C shell harnesses are incomplete.
|
|
- The server listens on HTTP; HTTPS termination is deployment-owned.
|
|
`/healthz` reports process status without probing dependencies. Development
|
|
Compose needs configuration/key material absent from the checkout. Production
|
|
deployment and custody are external; a source implementation or example client
|
|
fragment does not prove live registration or consumer cutover.
|
|
- Approval-client provisioning, coordinated Qonto rotation, native consumer
|
|
handoffs and notification receipt closure remain open in KEY-WP-0009/0013/0014.
|
|
|
|
## Deliberate exclusions
|
|
|
|
General-purpose IAM, dynamic client registration, implicit/password grants,
|
|
wildcard redirects, arbitrary identity brokering, resource authorization policy,
|
|
OpenBao credential custody, and Keycloak operations are outside this repository's
|
|
ownership. Registration/enrollment handoffs do not implement user provisioning
|
|
or factor enrollment themselves.
|
|
|
|
## Entry points and verification
|
|
|
|
Run the issuer with `keycape --config PATH`; `keycape server` and
|
|
`keycape migrate` are not implemented subcommands. Caller commands are
|
|
`keycape login` and `keycape service-token`.
|
|
|
|
Separate binaries under `src/cmd/` are `validator`, `lldap-export`,
|
|
`keycape-to-keycloak`, and `lldap-to-ldap`. `make -C src build` places binaries in
|
|
root `bin/`; the container packages only `keycape`. Tests live under `src/tests/`
|
|
and alongside packages in `src/internal/`.
|
|
|
|
`make test`, `make lint` (Go vet), `make build`, and `make contract-test` are the
|
|
root checks. The capability-contract check requires the sibling NetKingdom
|
|
validator. These checks passed for the reviewed revision in the preceding
|
|
implementation session; the scope assessment is a source/documentation review.
|
|
|
|
Use this repo for its bounded issuer, caller JWT acquisition, identity adapters
|
|
and migration preparation. Consult [INTENT.md](INTENT.md) for the architectural
|
|
target, [native authentication](docs/native-authentication.md) for caller
|
|
constraints, and the [scope/intent assessment](history/2026-09-05-011726-scope-intent-assessment.md)
|
|
for evidence, priorities and remaining gaps.
|
|
|
|
## Provided capabilities
|
|
|
|
```capability
|
|
type: security
|
|
title: Bounded OIDC and service-token issuance
|
|
description: Implements static-client browser PKCE and client-credentials authentication with RS256 identity claims through Authelia, LLDAP and privacyIDEA; complete Keycloak interchangeability remains unproven.
|
|
keywords: [oidc, pkce, authentication, iam, sso, mfa, identity, service-token]
|
|
```
|
|
|
|
```capability
|
|
type: security
|
|
title: Verified caller JWT acquisition
|
|
description: Provides native browser login and service-token exchange commands with HTTPS discovery, JWKS verification and private token-file delivery.
|
|
keywords: [oidc, pkce, jwt, cli, authentication, jwks]
|
|
```
|
|
|
|
```capability
|
|
type: security
|
|
title: Directory validation and migration artifact generation
|
|
description: Checks canonical snapshots and produces LLDAP exports, basic Keycloak realm JSON and target-specific LDIF; does not perform or prove a complete live migration.
|
|
keywords: [migration, identity, lldap, keycloak, ldif, validation]
|
|
```
|