245 lines
7.8 KiB
Markdown
245 lines
7.8 KiB
Markdown
---
|
|
id: canon-iam-profile
|
|
type: standard
|
|
title: "IAM Profile v0.1"
|
|
domain: custodian
|
|
status: superseded
|
|
version: "0.1"
|
|
created: "2026-05-02"
|
|
updated: "2026-05-22"
|
|
scope: all-hubs
|
|
superseded_by: net-kingdom/canon/standards/iam-profile_v0.2.md
|
|
---
|
|
|
|
# IAM Profile v0.1
|
|
|
|
> Superseded 2026-05-22. The canonical core/platform IAM Profile is now
|
|
> owned by net-kingdom at `canon/standards/iam-profile_v0.2.md`, with
|
|
> ownership and version governance recorded in
|
|
> `docs/adr/ADR-0011-iam-profile-ownership-and-version-governance.md`.
|
|
> This v0.1 all-hubs draft remains historical Custodian context only;
|
|
> hub-specific scopes such as `hub:*`, `ops:*`, and `fin:*` are downstream
|
|
> extensions of the NetKingdom core profile.
|
|
|
|
## Purpose
|
|
|
|
This standard defines the identity and access-management contract shared by
|
|
Custodian hubs and services. It gives hub-core, dev-hub, ops-hub, fin-hub, and
|
|
domain services one predictable OIDC profile without binding them to one
|
|
deployment topology.
|
|
|
|
The reference provider is NetKingdom SSO: Keycloak as the OIDC provider, with
|
|
privacyIDEA-backed MFA for human authentication. Local development may use a
|
|
file-backed OIDC provider if it exposes the same contract.
|
|
|
|
## Design Principles
|
|
|
|
- Hubs trust OIDC tokens, not provider-specific session state.
|
|
- Human and service identities are distinct.
|
|
- Authorization decisions use explicit claims and scopes.
|
|
- Local development degrades gracefully without weakening production rules.
|
|
- Emergency access is auditable, time-bounded, and never silent.
|
|
|
|
## Discovery Contract
|
|
|
|
Every IAM profile implementation MUST expose standard OIDC discovery:
|
|
|
|
```text
|
|
GET /.well-known/openid-configuration
|
|
```
|
|
|
|
The discovery response MUST include:
|
|
|
|
- `issuer`
|
|
- `authorization_endpoint`
|
|
- `token_endpoint`
|
|
- `jwks_uri`
|
|
- `userinfo_endpoint`
|
|
- `end_session_endpoint` when supported
|
|
- `scopes_supported`
|
|
- `response_types_supported`
|
|
- `grant_types_supported`
|
|
- `id_token_signing_alg_values_supported`
|
|
|
|
Services MUST validate tokens against the advertised `issuer` and `jwks_uri`.
|
|
Key material MUST be cacheable, but services MUST tolerate key rotation.
|
|
|
|
## Required Flows
|
|
|
|
### Human Interactive Flow
|
|
|
|
Human users authenticate through Authorization Code + PKCE.
|
|
|
|
Required properties:
|
|
|
|
- PKCE is mandatory for browser or CLI login.
|
|
- MFA is mandatory for privileged roles in production.
|
|
- Access tokens are short-lived.
|
|
- Refresh tokens are allowed only for trusted clients with explicit rotation.
|
|
|
|
### Service Account Flow
|
|
|
|
Hub-to-hub and service-to-service traffic uses client credentials or a
|
|
provider-supported service-account equivalent.
|
|
|
|
Required properties:
|
|
|
|
- Service accounts are named after the service and environment.
|
|
- Service credentials are stored through the credential-management standard,
|
|
not in plaintext config.
|
|
- Tokens include an audience that identifies the target hub or service.
|
|
- Service accounts receive only the scopes required for their role.
|
|
|
|
## Required Claims
|
|
|
|
Access tokens accepted by hubs MUST provide:
|
|
|
|
| Claim | Meaning |
|
|
|---|---|
|
|
| `iss` | OIDC issuer URL |
|
|
| `sub` | Stable subject identifier |
|
|
| `aud` | Intended audience; MUST include the receiving hub/service |
|
|
| `exp` | Expiry timestamp |
|
|
| `iat` | Issued-at timestamp |
|
|
| `scope` or `scp` | Granted scopes |
|
|
| `preferred_username` | Human-readable username for human identities |
|
|
| `roles` or `realm_access.roles` | Role names used for hub authorization |
|
|
|
|
Recommended claims:
|
|
|
|
| Claim | Meaning |
|
|
|---|---|
|
|
| `email` | Contact identity for humans |
|
|
| `name` | Display name |
|
|
| `groups` | Organization/group membership |
|
|
| `azp` | Authorized party/client id |
|
|
|
|
Services MUST NOT infer privilege from `email`, display name, or group naming
|
|
conventions alone. Privilege comes from explicit roles and scopes.
|
|
|
|
## Required Scopes
|
|
|
|
The following scopes form the shared vocabulary:
|
|
|
|
| Scope | Purpose |
|
|
|---|---|
|
|
| `openid` | Required for OIDC login |
|
|
| `profile` | Basic user profile |
|
|
| `email` | Email claim where appropriate |
|
|
| `hub:read` | Read hub state |
|
|
| `hub:write` | Mutate ordinary hub state |
|
|
| `hub:admin` | Administrative hub operations |
|
|
| `hub:message` | Send and manage inter-agent/hub messages |
|
|
| `hub:capability` | Request, accept, and update capability requests |
|
|
| `hub:repo` | Register and update managed repository metadata |
|
|
| `ops:read` | Read operational state |
|
|
| `ops:write` | Mutate operational records |
|
|
| `fin:read` | Read financial state |
|
|
| `fin:write` | Mutate financial records |
|
|
|
|
High-impact scopes such as `hub:admin`, `ops:write`, and `fin:write` MUST be
|
|
issued only to MFA-authenticated humans or narrowly scoped service accounts.
|
|
|
|
## Role Vocabulary
|
|
|
|
The minimum shared roles are:
|
|
|
|
| Role | Meaning |
|
|
|---|---|
|
|
| `viewer` | Read-only orientation |
|
|
| `operator` | Operational changes within an assigned domain |
|
|
| `steward` | Cross-domain governance and escalation |
|
|
| `admin` | IAM and hub administration |
|
|
| `service` | Non-human service identity |
|
|
| `emergency` | Temporary break-glass identity |
|
|
|
|
Hubs MAY define local roles, but shared integrations MUST map them back to this
|
|
vocabulary when communicating across hubs.
|
|
|
|
## Token Lifecycle
|
|
|
|
Recommended production defaults:
|
|
|
|
| Token | Lifetime | Notes |
|
|
|---|---|---|
|
|
| Access token | 5-15 minutes | Short-lived; bearer token |
|
|
| Refresh token | 8-12 hours | Rotated; revoked on logout or suspicion |
|
|
| Service token | 5-30 minutes | Reissued by client credentials |
|
|
|
|
Services MUST reject expired tokens and tokens with invalid issuer, audience, or
|
|
signature. Clock skew tolerance SHOULD be small, normally no more than 60
|
|
seconds.
|
|
|
|
## Hub-to-Hub Service Account Pattern
|
|
|
|
Each hub receives one service account per environment:
|
|
|
|
```text
|
|
svc-dev-hub-prod
|
|
svc-ops-hub-prod
|
|
svc-fin-hub-prod
|
|
svc-dev-hub-dev
|
|
```
|
|
|
|
Service accounts:
|
|
|
|
- authenticate with client credentials or equivalent workload identity
|
|
- carry the `service` role
|
|
- carry only the scopes required by the calling hub
|
|
- are rotated through the credential-management standard
|
|
- are never shared between environments
|
|
|
|
Example: dev-hub forwarding a deployment event to ops-hub should use a
|
|
dev-hub service account with `ops:write` scoped to the event-ingestion endpoint,
|
|
not an all-purpose admin token.
|
|
|
|
## Local Development Profile
|
|
|
|
A local file-backed provider MAY be used when Keycloak/privacyIDEA is
|
|
unavailable. It MUST:
|
|
|
|
- expose OIDC discovery
|
|
- issue signed JWTs
|
|
- support deterministic test users and service accounts
|
|
- use local-only issuer URLs by default
|
|
- clearly mark tokens as development tokens through issuer or audience
|
|
- never be accepted by production hubs
|
|
|
|
This profile exists to keep hub development possible without cluster
|
|
dependency; it is not a production identity system.
|
|
|
|
## Human Override and Emergency Access
|
|
|
|
Emergency access is allowed only as a break-glass path.
|
|
|
|
Requirements:
|
|
|
|
- Emergency identities are disabled by default.
|
|
- Activation requires a human-recorded decision or incident reference.
|
|
- Tokens are short-lived and carry the `emergency` role.
|
|
- Every emergency action emits a progress event or ops incident timeline entry.
|
|
- Emergency access is reviewed after use and then disabled again.
|
|
|
|
Emergency access MUST NOT bypass audit logging.
|
|
|
|
## Validation Checklist
|
|
|
|
A service conforms to this profile when:
|
|
|
|
- It reads OIDC discovery rather than hardcoding endpoints.
|
|
- It validates issuer, audience, expiry, and signature.
|
|
- It checks explicit roles/scopes for authorization.
|
|
- It supports Authorization Code + PKCE for human login.
|
|
- It supports service-account tokens for hub-to-hub calls.
|
|
- It rejects local-development issuers in production.
|
|
- It logs emergency access with a durable audit trail.
|
|
|
|
## Open Questions
|
|
|
|
- Whether `roles` or `realm_access.roles` becomes the canonical role claim for
|
|
all hubs, or whether adapters normalize both.
|
|
- Whether hub-to-hub event forwarding should use audience-per-hub or
|
|
audience-per-endpoint.
|
|
- Whether production service accounts eventually move from client credentials
|
|
to Kubernetes workload identity.
|