Skip to content
See how teams benefit
  • Security
  • Non-Human Identity
  • PCI DSS

Inventorying Non-Human Identities: A Practical Starting Point

Service accounts, tokens, and CI credentials now outnumber people. Where to find them, what to record about each one, and how to shrink the list.

Lionhouse Engineering · · 7 min read

Ask a security team how many people can access production and you will get a number within minutes. Ask how many service accounts, API tokens, and CI credentials can, and the answer is usually a guess. Those non-human identities (NHIs) rarely have an owner, an expiry date, or a recent review, which is why leaked machine credentials appear in so many breach reports.

Where to look

  • Cloud IAM: AWS IAM users and access keys, IAM roles assumed by workloads, GCP service accounts and their keys, Azure service principals and managed identities.
  • Kubernetes: service accounts and any long-lived tokens mounted into pods.
  • CI/CD: repository and organization secrets in GitHub Actions, GitLab CI variables, and deploy keys.
  • Source control and SaaS: GitHub Apps, personal access tokens used by automation, and API keys for third-party services.
  • Databases and queues: application users and shared credentials.
  • AI agents and MCP servers: the tokens agents use to call internal tools.
# AWS: access keys per user, and when each was last used
aws iam list-users --query 'Users[].UserName' --output text
aws iam list-access-keys --user-name deploy-bot
aws iam get-access-key-last-used --access-key-id AKIA...

# GCP: user-managed keys on a service account
gcloud iam service-accounts keys list \
  --iam-account=ci-runner@my-project.iam.gserviceaccount.com --managed-by=user

# Kubernetes: every service account in the cluster
kubectl get serviceaccounts --all-namespaces

# GitHub: secrets configured on a repository
gh secret list --repo my-org/payments-api
A few read-only commands to start the inventory

What to record for each identity

  • Owner: a team, not a person who might leave.
  • Purpose: what system uses it and why.
  • Scope: the permissions it actually has, compared with what it needs.
  • Created and last used: unused for 90 days usually means it can go.
  • Rotation: when it was last rotated, and whether rotation is automated.
  • Location: everywhere the secret is stored, including CI variables and config files.

Shrinking the list

The best credential is one that does not exist. Workload identity federation lets a CI job or a Kubernetes pod exchange a short-lived, signed identity token for cloud credentials, so there is no long-lived key to leak or rotate. GitHub Actions, GitLab CI, and Kubernetes all support OIDC federation with AWS, GCP, and Azure.

  1. Delete identities with no owner and no use in 90 days, after a short warning period.
  2. Replace long-lived CI cloud keys with OIDC federation.
  3. Cut each remaining identity down to the permissions it used in the last 90 days.
  4. Automate rotation for anything that must stay long-lived, and block new secrets in pull requests.

Why auditors care

PCI DSS v4.0 requirement 8.6 explicitly covers system and application accounts: no hard-coded passwords, controlled interactive use, and periodic credential changes. SOC 2 CC6 and ISO 27001 A.5.18 access reviews are increasingly expected to include machine identities too. An inventory with owners and last-used dates is the evidence.

More From the Blog