NK-WP-0054-T02: draft-1 of the Service Identity and Privilege standard
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

Thirteen rules (one identity one class, people and services never share a
credential, read-only per-service bind identities, one service-admin per
service, break-glass is not routine, assurance on privileged roles, custody
class, declaration, recovery, validation run by the operator identity), naming
svc-<service> and <short>-admin, five initial exceptions and six open questions.
Proposed; extends IAM Profile v0.3 and Credential Management v0.2. Hub decision
routes the review.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 328925@bnt-lap001
Assistant-Session: 14b795fd-c632-4c01-8d28-e7e490c7b0ed
This commit is contained in:
tegwick 2026-10-24 20:02:30 +02:00
parent 597ffbf111
commit 768e7252e8
3 changed files with 241 additions and 2 deletions

View file

@ -309,7 +309,7 @@
| task | NK-WP-0053-T03 | wait | — | workplans/NK-WP-0053-identity-restore-drill-cadence.md |
| task | NK-WP-0053-T04 | todo | — | workplans/NK-WP-0053-identity-restore-drill-cadence.md |
| task | NK-WP-0054-T01 | done | — | workplans/NK-WP-0054-service-identity-policy.md |
| task | NK-WP-0054-T02 | todo | — | workplans/NK-WP-0054-service-identity-policy.md |
| task | NK-WP-0054-T02 | wait | — | workplans/NK-WP-0054-service-identity-policy.md |
| task | NK-WP-0054-T03 | wait | — | workplans/NK-WP-0054-service-identity-policy.md |
| task | NK-WP-0054-T04 | wait | — | workplans/NK-WP-0054-service-identity-policy.md |
| task | NK-WP-0054-T05 | wait | — | workplans/NK-WP-0054-service-identity-policy.md |

View file

@ -0,0 +1,230 @@
---
id: netkingdom-service-identity-privilege
type: standard
title: "NetKingdom Service Identity and Privilege v0.1"
domain: netkingdom
status: proposed
version: "0.1"
created: "2026-10-24"
updated: "2026-10-24"
scope: service-account-governance
revision: "draft-1"
owner: net-kingdom
last_reviewed: "2026-10-24"
review_interval: 3m
standard_token: service-identity-privilege_v0.1
related:
- canon/standards/iam-profile_v0.3.md
- canon/standards/credential-management_v0.2.md
- canon/standards/tenancy-posture_v0.1.md
- canon/standards/security-zones_v0.1.md
- canon/standards/posture-feedback_v0.1.md
- docs/service-identity-inventory.md
- docs/crisis-custody-list.md
---
# NetKingdom Service Identity and Privilege v0.1
## 0. Status
**Proposed, draft-1.** It binds nothing until the founder ratifies it and each owner adopts it.
It was started on 2026-10-24 from the founder's direction and from the first inventory
(`docs/service-identity-inventory.md`, NK-WP-0054-T01). Its machine-readable declaration
(NK-WP-0054-T03) and conformance check (T04) do not exist yet.
The finding behind it: one LLDAP account, `uid=admin`, is at the same time the human platform
administrator, the directory super-admin and the bind credential of Authelia, KeyCape, the
privacyIDEA resolver and the identity-provisioner. One account has one password, so the human
login, four services and every backup bundle share one secret. The Credential Management
Standard §6 already calls rotating it "3-way coordinated"; the inventory found five consumers.
## 1. Purpose and scope
This standard says which identities, and which privileges, may exist inside the services that
are part of NetKingdom. It governs the **accounts** in a service's own store, directory or
policy engine. It does not replace:
- the **token profile**: human, service and agent principals in tokens belong to
[IAM Profile v0.3](iam-profile_v0.3.md);
- **credential storage and rotation procedure**: [Credential Management v0.2](credential-management_v0.2.md);
- **tenant isolation**: [Tenancy Posture](tenancy-posture_v0.1.md) and
[Security Zones](security-zones_v0.1.md).
In scope: LLDAP, Authelia, KeyCape, privacyIDEA, the identity-provisioner, user-engine and
tenant-engine at their boundary, OpenBao authentication roles and policies, and the platform
consumers of these services. Out of scope: accounts that a tenant creates inside its own
workloads, except where they cross into a NetKingdom service.
## 2. Vocabulary
An **identity** is any account, role, client or principal held in a service's own store. A
**credential** is what proves an identity. A **consumer** is a person or system that presents
the credential. Every identity has exactly one **class**.
| Class | Meaning | Examples today |
| --- | --- | --- |
| `human` | A person's attributable login | `tegwick`, `admin` |
| `break-glass` | Final authority held offline, not routine | `platform-root` (king credential) |
| `bind` | A service's own lookup in another service's directory | planned `svc-authelia` |
| `service-admin` | The administrative account of one service | `pi-admin`, planned `ld-admin` |
| `workload` | A service or agent that obtains tokens or secrets | KeyCape clients, `secrets-engine-openbao` |
| `infrastructure` | A role below the application | database role `privacyidea` |
## 3. Rules
Each rule has a stable id so that findings, exceptions and the health check can cite it.
**SI-1 One identity, one class.** An identity MUST have exactly one class. An account that is
both a person and a service is non-conformant.
**SI-2 People and services do not share credentials.** A person MUST NOT use a service
credential, and a service MUST NOT use a person's credential. A human's password MUST NOT be
stored in a Secret that a service reads.
**SI-3 Bind identities.** A `bind` identity MUST be read-only, limited to the least subtree and
operations its consumer needs, unable to sign in interactively, and used by exactly one
consuming service. Two services MUST NOT share a bind credential. Where a service must write
(for example the identity-provisioner creating users), it gets its own `workload` identity with
the narrowest working write scope and is never given the service-admin account.
**SI-4 Service-admin identities.** A service SHOULD have exactly one local administrative
identity, separate from every bind and every human. It MUST be named for its service (§4),
MUST require a second factor where the service can enforce one, and MUST NOT be used by
automation unless the declaration says so.
**SI-5 Attributed administration first.** Where a service supports administrative roles granted
to an attributed human identity (for example OpenBao policies bound to a group), day-to-day
administration SHOULD use that route. The local `service-admin` is the sealed fallback and is
listed in the crisis custody list. A service that has only a local administrator (privacyIDEA
today) records that as an exception, not as a norm.
**SI-6 Break-glass.** There MUST be a break-glass identity, held offline. Using it is an event
that MUST be recorded. It MUST NOT be used for routine operation, for backup validation or as the
test subject of a drill. It authorizes; it does not operate.
**SI-7 The developer identity.** The developer identity MUST NOT hold break-glass or recovery
custody items and MUST NOT hold a production service credential. It builds and tests.
**SI-8 Assurance.** Every `human` and `service-admin` identity MUST require a second factor
where the service can enforce one. A role that grants administrative policy SHOULD require the
assurance level itself (for example an `aal2` claim bound in the OpenBao role), not only rely on
an upstream service having checked. A role that does not MUST record why in an exception.
**SI-9 Custody class.** Every credential MUST declare a custody class: `offline-key`,
`personal-safe`, `openbao-lease`, `delivered-secret` (delivered into the workload by the
platform), or `none` (federated, no stored credential). A credential used by more than one
consumer is non-conformant under SI-3.
**SI-10 Ownership and rotation.** Every identity MUST name an owner, its consumers and a
rotation path with its coupling (what must change together). Static long-lived binds are a
stated gap under Tenancy Posture §9 (Decision 9.1 and 9.2), not a silent exclusion; their
compensating controls are SI-3 and a restricted network path.
**SI-11 Declaration and legacy.** Every identity that exists in a service MUST be declared.
An identity that exists and is not declared is non-conformant (`unknown`). A legacy identity
MUST have a disposition (retire, accept, or defer) with an owner and a date.
**SI-12 Recovery.** Every identity needed to recover a service MUST appear in the crisis custody
list with the answer to "does using it work when SSO and OpenBao are down?". An identity that
cannot be used while its own service is down MUST NOT be the only recovery path.
**SI-13 Validation is operated by the operator identity.** Restore drills and backup validation
MUST be run by the production operator identity, with that identity's own token as the test
subject, and MUST record which identity ran each stage.
## 4. Naming
| Class | Pattern | Notes |
| --- | --- | --- |
| `bind` | `svc-<service>` | One per consuming service; `svc-<service>-<function>` if one service needs several |
| `service-admin` | `<short>-admin` | The short form is registered per service (see §9): `pi-admin`; `ld-admin` proposed for LLDAP |
| `break-glass` | `platform-root` | The king credential |
| `human` | the person's own login | `tegwick`, `admin` |
| `workload` | the token subject form already in use | for example `service:secrets-engine`; IAM Profile v0.3 governs the token |
Names are reserved for their class. A `svc-` or `-admin` name MUST NOT be used for a human.
## 5. Target shape for today's services (informative)
This table shows where the rules lead. The authoritative state is the inventory, and the
steps are NK-WP-0054-T05 and T06.
| Service | `service-admin` | `bind` and write identities | Human route |
| --- | --- | --- | --- |
| LLDAP | `ld-admin` (the built-in super-admin, renamed or replaced after rehearsal) | `svc-authelia`, `svc-keycape`, `svc-privacyidea` read-only; a scoped provisioner identity | `admin` as a normal member of the admin group, no shared password |
| Authelia | none (LDAP backend only) | uses `svc-authelia` | none |
| privacyIDEA | `pi-admin` | resolver uses `svc-privacyidea` | none (local administrator only: exception) |
| KeyCape | none | uses `svc-keycape` | none |
| OpenBao | per its own policy | n/a | `net-kingdom-admins` group to `platform-admin` |
## 6. Declaration
Each service publishes one declaration of every identity it holds, in a machine-readable form
defined by NK-WP-0054-T03. For each identity: name, class, purpose, privileges, custody class,
consumers, owner, rotation path and coupling, second-factor requirement, status
(`active`, `legacy`, `planned`) and any exception id. A declaration holds no credential and no
secret-shaped value.
## 7. Conformance and the health check
For each identity the result is one of `conformant`, `non-conformant` (with the rule ids),
`excepted` (with the exception id) or `unknown`. Unknown is a finding, not a pass.
The health check (NK-WP-0054-T04) compares declared against observed state: for example,
which DN each service binds as, which groups the bind identities belong to, and which policies
an admin role carries. It uses read-only metadata that each owner provides and repository
manifests. It MUST NOT read a Secret. Its findings are proposals routed to the identity's owner
through [Posture Feedback](posture-feedback_v0.1.md), with an evidence-freshness bound. It
changes nothing.
## 8. Exceptions
An exception is time-boxed and records: the rule, the identity, the reason, the owner, an expiry
date and the compensating control. It is reviewed at the standard's review interval. A rule
without a recorded exception that is broken is non-conformant.
Initial exceptions at adoption:
| Id | Rule | Identity | Reason | Until |
| --- | --- | --- | --- | --- |
| SI-X1 | SI-1, SI-2, SI-3 | LLDAP `admin` | One account is the human, the super-admin and the shared bind of five consumers | NK-WP-0054-T05 completes |
| SI-X2 | SI-10 | LDAP binds | Static long-lived credential; LDAP has no lease | Tenancy Posture §9 gap review |
| SI-X3 | SI-11 | `trigger-admin` (privacyIDEA) | Legacy account with uninventoried consumers | NK-WP-0049-T22 disposition |
| SI-X4 | SI-8 | OpenBao `netkingdom-platform-admin` | Role binds on the group claim only in the repository file | Decision on §10 question 1 |
| SI-X5 | SI-5 | privacyIDEA | Only a local administrator is supported | Upstream capability |
## 9. Relationship to other documents
- **IAM Profile v0.3** defines the principal types in tokens. This standard governs the
accounts that exist behind them and does not change the token profile.
- **Credential Management v0.2 §6** lists `LLDAP_LDAP_USER_PASS` as a three-way coupling.
On adoption that row is corrected and replaced by the per-service bind accounts.
- **Tenancy Posture §9** treats long-lived credentials as a gap; SI-10 applies it to binds.
- **Security Layer Model v0.9** should be checked for an identity-layer statement this standard
must match; that reconciliation is part of ratification.
- **Crisis custody list** (`docs/crisis-custody-list.md`) is the recovery companion to SI-9 and SI-12.
- The registry of `<short>-admin` forms lives with the declarations (T03) and starts with
`pi-admin` and the proposed `ld-admin`.
## 10. Open questions
1. **OpenBao assurance.** Should the `platform-admin` role bind `aal2` itself (SI-8) or rely on
KeyCape's `requireForAll`? The other privileged roles already bind it.
2. **Renaming LLDAP's built-in admin.** The directory's super-admin name is configurable, but
renaming it on an existing directory is untested. It needs a rehearsal in isolation before
`ld-admin` is decided (T06).
3. **The human `admin` in LLDAP.** Does the human keep LLDAP admin-UI rights through group
membership, or administer users only through the governed provisioner path?
4. **The provisioner's narrowest scope.** What is the least privilege that still lets it create
users and groups? It must be tested against the pinned LLDAP image.
5. **Workload clients.** KeyCape's confidential clients are governed by IAM Profile v0.3. This
standard only requires that each is declared, owned and not shared. Is that enough?
6. **Where the declarations live.** In each service's repository (preferred, owners are
accountable) or in this repository (simpler to validate).
## 11. Adoption
Structure first, tooling second, as with Tenancy Posture. The order is: ratify the vocabulary and
rules; complete the declarations (T03); run the health check read-only (T04) and publish the
first report; then retire the exceptions one by one, starting with SI-X1 (T05). No exception is
closed by writing a declaration. Each is closed by the live change and an evidence run.

View file

@ -73,10 +73,13 @@ is an uninventoried legacy admin, and OpenBao `platform-admin` binds on a group
```task
id: NK-WP-0054-T02
status: todo
status: wait
priority: high
assignee: claude-code
needs_human: true
decision_id: "a3582e79-4ece-4902-9bfa-e962aef2b8f2"
depends_on: [NK-WP-0054-T01]
blocking_reason: "Draft-1 delivered 2026-10-24. Await the founder review and answers to the six open questions in section 10."
state_hub_task_id: "5830e2eb-334a-52fa-9c55-a8c00d89c09f"
```
@ -90,6 +93,12 @@ Profile v0.3, Credential Management v0.2 and the Security Zones standard.
**Done when:** the draft is reviewed by the founder and the service owners it names.
Draft-1 delivered 2026-10-24: `canon/standards/service-identity-privilege_v0.1.md` (proposed). Thirteen
rules (SI-1 to SI-13), naming, a target shape for today's services, the declaration fields, the
conformance result states, five initial exceptions (SI-X1 to SI-X5) and six open questions. It
extends IAM Profile v0.3 and Credential Management v0.2 without changing either. Review is the
founder's, then the service owners named in the inventory.
## Schema and offline conformance validator
```task