- 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-apiWhat 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.
- Delete identities with no owner and no use in 90 days, after a short warning period.
- Replace long-lived CI cloud keys with OIDC federation.
- Cut each remaining identity down to the permissions it used in the last 90 days.
- 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.