Guide 100 checklist

How to audit service credentials separately from human accounts

Audit service credentials separately from human accounts by checking issuance, renewal, actual scope, secret rotation, and the inventory's explicit boundaries.

Audit machine credentials as independent principals with their own owner, purpose, scope, lifetime, storage, rotation and revocation path. A bot token, CI identity, webhook secret or service account is not a person with a long password. Distinguish API bearer credentials from webhook signing secrets: the latter authenticate messages, so their validation and rotation checks concern accepted signatures and delivery overlap rather than login sessions. Machine credentials can remain usable after their creator leaves and may reach APIs a browser never uses. They cannot satisfy a human MFA requirement. Start with a bounded inventory of credentials and where each is accepted, verify server-enforced limits, then exercise revocation with designated validation credentials or a planned handover. Reconcile issuing systems and consumers before calling the inventory complete. OWASP's Secrets Management Cheat Sheet covers creation, rotation, revocation, expiration and CI service-account scope.

The answer changes with the purpose of the automation. An employee's personal API token should usually die with that employee's access. A separately approved production service account may need to keep operating during offboarding, but it still needs an accountable current owner and an explicit reapproval or rotation decision. Do not solve availability by leaving former employees' broad tokens active under an informal “bot” label.

Illustrative case: the departed engineer's export token

Illustrative company and credential ledger. At Harbor Metrics, a nightly job exports one repository's vulnerability summary to an internal dashboard. Months ago, Eli created a personal token for it. Eli leaves on Tuesday. The human SSO account is disabled, but the job still succeeds because its token is accepted by the application's machine API and has no stated expiry. The token can also read full report details across every repository, even though the job only needs summary data from one.

The platform engineer faces two decisions: stop Eli's access and preserve a legitimate reporting job. Because Eli has already left, revoke the personal token now and verify denial at the accepting API, even if the nightly job pauses. Then create a reviewed automation principal whose authority matches the job, switch the consumer and verify a new run. For a scheduled departure, migrate the job before offboarding and revoke the personal token when access ends. The narrative does not assume that disabling SSO revoked the token; the audit must observe the token endpoint's decision.

Credential Principal and accountable owner Intended operation Actual scope found Lifetime and storage Decision
T-17 personal API token Eli; no current owner Nightly summary export All repositories, report detail reads No expiry; CI secret Revoke now; restore job with replacement
J-4 proposed automation credential Harbor reporting service; platform owner and security approver Read one repository's summary One repository and one read action Short-lived issuance from CI identity Validate, then adopt
S-8 provisioning token Identity team owner Deactivate users through SCIM User/group write for one tenant Vault-stored, expiring Review separately; never grant report reads

The table records metadata only. It should never contain token values, private keys, reset links or copied authentication headers. A secret inventory itself may be sensitive and should have controlled access.

Build the inventory from both ends

The issuing system knows what credentials exist; consumers reveal where they are used. Compare both. Start with service-account and API-token listings in the application, IdP, repository provider, cloud account, CI platform, secrets manager and integration settings. Then search deployment configuration, scheduled jobs and approved secret references for credentials that may no longer appear in a current owner's dashboard. Do not paste secret contents into a spreadsheet or logs. Record stable credential IDs or fingerprints supplied by the issuer.

For each entry, capture:

Field Question the audit must answer
Issuer, principal, account Who issued it, and to which exact customer or environment does it belong?
Accountable owner Which current team approves its purpose and receives expiry/incident notices?
Consumer and storage Which job or service obtains it, and can maintainers extract it?
Actions and resources What can it actually do at the API, including list, detail, export and admin routes?
Issue and expiry When was it created, when will it stop working, and is renewal automatic?
Rotation and revocation Who can rotate or disable it, and how will consumers switch safely?
Last observed use Does use match the intended job and source environment?

An empty “last used” field is not proof the credential is harmless: telemetry may be missing, the job may run monthly, or the credential may have been copied. Mark that uncertainty and use the issuer's authoritative status plus consumer review.

Reconcile issuer records with actual consumers

Harbor's issuer lists T-17, J-4 and S-8. The consuming-job inventory reveals another secret reference, monthly-finance-export, whose credential ID is T-29. T-29 has no usage event in the last seven days and no current owner. That is not evidence it is unused: the schedule runs on the first day of each month, and the API's credential-level telemetry is incomplete.

Issuer record Consumer record Interpretation Next decision
T-17 active, personal Eli token Nightly summary job Known orphaned human authority Revoke departed user's token; restore approved automation
J-4 proposed, repository-summary scope Replacement job configuration Intended match, not yet proven effective Verify permitted and forbidden actions
S-8 active provisioning credential Identity sync service Different purpose Retain separate scope review; no report access
T-29 active, owner missing Monthly finance job Incomplete ownership/telemetry, not unused Locate accountable service owner and scheduled dependency

The reconciliation key is an issuer-provided identifier or safe fingerprint, not the secret itself. A vault path tells you where a value is stored, but does not prove which credential the current value represents or what the accepting API allows. Conversely, an issuer listing without consumer mapping cannot tell you what rotation will interrupt.

Validate the replacement's denied operations

J-4 is intended to read summary data for repository R-3. Its synthetic acceptance record should include:

J-4 → R-3 summary:          allow approved summary fields
J-4 → R-3 technical detail: deny
J-4 → R-4 summary:          deny
J-4 → account membership:  deny
revoked T-17 → old read:   deny

One successful nightly export proves availability for that path, not least privilege. The denied detail and wrong-repository cases establish the boundary the replacement was meant to improve. Inspect response projections and downstream artifacts as well as token scope labels.

For a planned migration, update the consumer, establish the intended behavior, then revoke the old credential under the change plan. In Eli's already-departed case, the example revokes first and accepts the job interruption while restoring service with J-4. If compromise is suspected, an owner must consider downstream credentials and copies separately; rotation cannot recall previously exported data.

Resolve the monthly orphan without guessing

The finance owner confirms T-29 drives a legitimate monthly process but cannot justify its all-repository detail access. The decision is to create a narrowly scoped service identity, schedule a controlled handover before the next run, and revoke T-29 after the approved transition. If no owner can be found, set a bounded investigation deadline and an authorized disablement plan; unknown availability impact is not a permanent grant.

A record with no last-use event remains “telemetry incomplete.” Do not fabricate a safe-to-delete date from an arbitrary seven-day window. If the issuer cannot identify calls by credential, improving attribution becomes an explicit audit gap.

All IDs and outcomes here are synthetic and unexecuted. OWASP's secrets lifecycle guidance supplies the broader creation/rotation/revocation principles; RFC7009 defines OAuth revocation behavior where applicable. The actual proof must come from the accepting API and current consumer, not the departed employee's disabled SSO screen.

Handle gaps without inventing certainty

If a credential has no owner, no scope record or unknown consumers, mark it unowned and set a deadline for investigation. Do not assume immediate deletion is always safe if it drives production; also do not let availability uncertainty become permanent authority. Reduce its scope if possible, monitor use, prepare a replacement, and escalate to the accountable service owner. Where no owner can be found, a controlled disablement window may be the only way to learn whether the credential is still needed.

If the issuer cannot revoke a long-lived access token promptly, document the remaining validity period, stop renewal, and restrict the resource server through its own authorization controls. If the accepting API has no way to identify which credential called it, improve attribution before claiming the audit can detect misuse. A human offboarding event and a machine credential review should be linked, but they should produce separate decisions with separate evidence.

Review renewal as part of the credential's real lifetime

J-4 is described as short-lived, but its effective exposure also depends on who can obtain the next credential. Inspect the CI identity, minting permission, and consumer configuration that renew it. A short expiry on one child token does not bound a workload that can continually request another with the same broad authority.

For Harbor's replacement, the renewal path should preserve repository R-3 and summary-read scope. A configuration update that omits the narrowing fields during rotation can change the authority even when the job name stays the same. Compare the intended scope with the actual issuance request and the receiving API's decision. Those are separate artifacts.

Also identify where the credential can be copied. A secrets-manager reference, a job environment, and a report log have different readers. The audit does not need to retrieve or print the secret to trace those access relationships. It needs to know which identities can extract the value or invoke the workload that uses it, and whether those identities match the approved purpose.

Keep signing-secret rotation in its own lane

S-8's provisioning API token and a webhook signing secret require different validation evidence. For an API bearer token, inspect whether the old credential can still invoke the protected action. For a webhook secret, inspect which signatures the receiver accepts during the planned overlap and after retirement. A successful outbound job does not answer either question for an unrelated inbound webhook.

The owner should record the intended transition, the consumers or senders involved, and how duplicate delivery is handled. Do not interpret a failed webhook delivery as proof that the old signing secret was rejected; the failure might occur before signature verification or for an unrelated reason. The relevant observation is the receiver's verified decision under the actual rotation policy.

Close the inventory gap with a bounded statement

At the end of Harbor's review, report the systems reconciled and the unresolved entries. For example, the issuer and two named CI consumers may be mapped while an older integration remains unexamined. That is useful progress, but it is not a complete inventory of every machine identity in the company.

Link the unresolved T-29 decision to an accountable service owner and a date that makes sense for its monthly schedule. Keep the distinction between “no observed recent use” and “confirmed retired.” This gives the next audit a concrete starting point and prevents a credential from becoming invisible merely because it runs less often than the reporting window.

This week, pick one CI integration and complete the inventory table using issuer records and the consuming job, then verify one least-privilege denial. Continue with how to review machine tokens with repository-scoped permissions and how to respond when a secret is committed to Git.