# Non-human identity register

One row per identity that is not a person: service accounts, workload identities, API keys and secrets, OAuth app registrations, and agents. Fill it from the systems, not from memory. Every column comes from the article's eight controls; the blanks record what you found on the date you looked.

**Scope (directory, tenant, or system reviewed):** ____________________

**Prepared by / date:** ____________________

## Two lists to reconcile

- [ ] List A: every non-human identity the directory or identity provider knows (service principals, app registrations, agent identities, agent blueprints, service accounts, workload identities).
- [ ] List B: every credential the firm's systems accept that is not a person's login (API keys in schedulers and integrations, static secrets in configuration, OAuth grants in SaaS admin consoles, tokens in CI, certificates for workloads).
- [ ] Every entry in List B that has no match in List A is written into the register below as an unowned identity and given a sponsor or disabled.
- [ ] Every entry in List A with no observed use in the review period is recorded, and its sponsor asked whether it is still needed.

**Count in List A / count in List B / unmatched:** ____________________

## Register

| Identity (name or id) | Kind | Sponsor (human) | Purpose (one sentence) | Credential type | Expiry | Roles or permissions | Acts for a person? | Logging destination | Last reviewed |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
|  |  |  |  |  |  |  |  |  |  |
|  |  |  |  |  |  |  |  |  |  |
|  |  |  |  |  |  |  |  |  |  |
|  |  |  |  |  |  |  |  |  |  |
|  |  |  |  |  |  |  |  |  |  |
|  |  |  |  |  |  |  |  |  |  |
|  |  |  |  |  |  |  |  |  |  |
|  |  |  |  |  |  |  |  |  |  |

Kind: service account, workload identity, API key or secret, OAuth app registration, agent. Credential type: password, static key or secret, client secret, certificate, federated credential, short-lived token, none (issued by a blueprint or role). Write "none" in Expiry only when the platform issues the credential per session; a static credential with no expiry is a finding.

## Inventory with a named owner and a purpose

- [ ] Every row has a named human sponsor, not a group alias or a departed person.
- [ ] Every row has a one-sentence purpose that the sponsor confirmed.
- [ ] Ten identities were sampled at random and their sponsors asked what each is for; the answers are recorded below.
- [ ] An identity whose sponsor could not answer, or has left, is disabled with a date recorded.

| Sampled identity | Sponsor asked on | Could explain purpose? | Action taken |
| --- | --- | --- | --- |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |

## Least privilege through roles, not standing admin

- [ ] Every identity holding an administrator role, an owner role, or a tenant-wide application permission is listed below with a written justification.
- [ ] No non-human identity holds a global administrator role or its equivalent.
- [ ] Where the identity acts for a person, delegated permissions are used rather than application permissions.
- [ ] Roles are granted through role assignments, app roles, or access packages, never by adding the identity to a role-assignable group.

| Identity | Elevated role or permission | Why it needs it | Narrower alternative considered | Decision |
| --- | --- | --- | --- | --- |
|  |  |  |  |  |
|  |  |  |  |  |
|  |  |  |  |  |

## Short-lived credentials and federation over static secrets

- [ ] Every static key, password, or client secret in the register has an expiry under 90 days and a named rotation owner.
- [ ] Where the platform offers a role, OIDC federation, a projected or bound token, or a blueprint-issued federated credential, the static credential has been replaced and deleted.
- [ ] Secrets with no expiry are counted below; the target is zero.
- [ ] No credential is shared across development, testing, and production, and none is reused across applications.

**Secrets with no expiry / rotated this period / replaced by federation:** ____________________

## Conditional access and step-up for elevated actions

- [ ] Access policies are scoped to workload and agent identities, not only to users, wherever the platform supports it.
- [ ] Risk-based blocking for non-human identities is enabled, first in report-only mode, then enforced; the dates are recorded.
- [ ] Actions that change roles, credentials, or policy require a second approval given by a human.
- [ ] An elevated action was attempted from a test identity and was blocked and logged; the record is referenced below.

**Policies in report-only / enforced / test attempted on and result:** ____________________

## Logging that names the identity and whom it acts for

- [ ] Every token issuance to a non-human identity is logged with the identity, the acting party where delegation occurs, the resource, and the result.
- [ ] Logs are shipped to a store the identity cannot write to.
- [ ] One tool call or API call was traced from the identity, through the token, to the audit record by identifiers alone; the trace is referenced below.
- [ ] For agents acting on behalf of a person, the record distinguishes the agent from the person.

| Identity | Log source | Store (append-only for the identity?) | Trace completed on | Gap found |
| --- | --- | --- | --- | --- |
|  |  |  |  |  |
|  |  |  |  |  |
|  |  |  |  |  |

## Lifecycle with an expiry and an offboarding test

- [ ] Every grant of access carries an end date, and the sponsor renews it or lets it lapse.
- [ ] When a person leaves, the identities they sponsored are reviewed the same day and reassigned or disabled.
- [ ] A test identity was disabled, and every system it used to reach was checked; each check is recorded below.
- [ ] Deleted or disabled identities are kept in the register with the date, so a later credential found in the wild can be matched.

| Test identity disabled on | System checked | Access ended? | Verified by |
| --- | --- | --- | --- |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |
|  |  |  |  |

## Kill switch tied to the incident plan

- [ ] For each class of identity, the control that stops the whole class at once is named: a blueprint disable, an access policy block, a revoked trust anchor, a rotated signing key.
- [ ] The incident plan names who may pull each control and how they are reached from a phone.
- [ ] A drill was run, and the time from decision to no token issued was measured and written in the runbook.

| Identity class | Control that stops the class | Who may pull it | Last drill | Minutes to no token issued |
| --- | --- | --- | --- | --- |
| Service accounts |  |  |  |  |
| Workload identities |  |  |  |  |
| API keys and secrets |  |  |  |  |
| OAuth app registrations |  |  |  |  |
| Agents |  |  |  |  |

## Quarterly review

- [ ] The two lists were reconciled again and the register updated.
- [ ] No row's last-reviewed date is older than one quarter.
- [ ] Findings from this review were carried into the service inventory and the access review.

**Rows added / rows disabled / rows still unowned at close:** ____________________

## Sign-off

**Reviewed by / date:** ____________________

**Next review date / change triggers (new agent platform, new integration, departure of a sponsor, new credential type):** ____________________

This register records the identities that exist and who owns them. It does not decide whether an agent should be connected to firm data in the first place; use the AI connector and data-flow review for that, and the agent observation and containment review once the agent runs.
