# Every identifier the account has issued, with the date it was assigned and the AWS-generated unique id behind it; the workforce identifiers issued through IAM Identity Center and the external issuer each one came from; and the CloudTrail record of identifiers being deleted, which is the only dated evidence of a name becoming free to reuse

> FedRAMP Consolidated Rules for 2026 v2026.07.14.01 · updated 2026-07-14
> Canonical page: /collect/identifier-assignment-and-reuse-prevention

Recipe id: `identifier-assignment-and-reuse-prevention` · cadence continuous · partial

> **Authored opinion.** AWS overlay v3.0.0, written
> against dataset 2026.07.14.01. The upstream
> FedRAMP rules name none of these tools; this mapping is ours.

## What it proves

- KSI `KSI-IAM-ELP`
- KSI `KSI-IAM-JIT`
- control `ia-4`

## Collection

Kind: `cli`

```sh
# get-account-authorization-details
aws iam get-account-authorization-details --filter User Role Group
# list-instances
aws sso-admin list-instances
# list-users
aws identitystore list-users --identity-store-id <IDENTITY_STORE_ID>
# lookup-events-delete-user
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=DeleteUser --start-time <T0> --end-time <T1>
```

## Expected output

From get-account-authorization-details, UserDetailList[], RoleDetailList[] and GroupDetailList[] — a group name is an identifier IA-04 covers and GroupDetail carries GroupId, the stable and unique string identifying the group, though NOT Tags — with UserName/RoleName/GroupName, the AWS-generated UserId/RoleId, Arn, Path, CreateDate as an ISO-8601 timestamp, Tags, and the attached and inline policy lists. This call rather than iam list-users is deliberate: list-users returns UserId, UserName, Arn, Path and CreateDate but AWS documents that it does NOT return Tags or PermissionsBoundary, and the tag is where an authorization reference can live. From sso-admin list-instances, Instances[] — a list whose minimum length is ZERO — each with InstanceArn, IdentityStoreId, Name, OwnerAccountId, CreatedDate, PrimaryRegion, Regions and a Status of CREATE_IN_PROGRESS, CREATE_FAILED, DELETE_IN_PROGRESS or ACTIVE. IdentityStoreId from that response is the argument the third call needs. From identitystore list-users, Users[] with the required IdentityStoreId and UserId and optional UserName, ExternalIds (a list of issuer/id pairs), Name, Emails, UserStatus (ENABLED or DISABLED), CreatedAt/CreatedBy and UpdatedAt/UpdatedBy. From lookup-events, Events[] with EventName DeleteUser, EventTime, and Username — which AWS documents as the user or role name of the REQUESTER that called the API, meaning the administrator who ran the deletion and NOT the identifier that was deleted. The deleted name is inside the CloudTrailEvent JSON, at requestParameters.userName, and that is the field the reuse comparison reads — bounded, as every lookup-events call is, to management events within the last 90 days.

## Assertions

- {"field":"get-account-authorization-details.UserDetailList[?!not_null(Tags[?Key=='IdentifierAuthorization'] | [0])]","op":"count_eq","value":0,"controls":["ia-4"],"description":"No IAM user is missing the tag naming the record that authorized its identifier — the first of IA-04's four verbs, as far as a field can carry it. Written as an offender list because a field projection drops the untagged rows rather than reporting them false, which is exactly the population being asked about. Your own tagging convention, so it is only as complete as the tagging behind it; zero on an account with no IAM users, which is the target state, so read it beside the length of UserDetailList. It cannot extend to groups, which carry no Tags."}

## GovCloud

IAM is global and partition-scoped: identifiers created in GovCloud carry arn:aws-us-gov and are entirely separate from the commercial partition's, so an identifier inventory taken in one partition says nothing about the other. IAM Identity Center operates in both AWS GovCloud (US) Regions over FIPS endpoints with NO multi-Region support, and its ARNs take the form arn:aws-us-gov:sso:::instance/<id> — so list-instances must be run in the Region the instance was enabled in, and PrimaryRegion in the response is what says which that is. CloudTrail management events are available in both GovCloud Regions, but note that CloudFront, IAM and STS events are delivered to us-gov-west-1 specifically: IAM is a global service, so the DeleteUser events this recipe reads land in US-West and a lookup-events call issued against US-East returns nothing while succeeding.

## Notes

IA-04 is four verbs — receive authorization for an identifier, select it, assign it to the intended party, and prevent its reuse for a defined period. AWS proves the third completely, gives real but bounded evidence for the fourth, and returns nothing at all for the first two.

Assignment is the easy half and it is genuinely complete: every identifier in the account is enumerable with the date it was assigned and the AWS-generated unique id behind it. Selection and authorization are records about a decision, not about a resource, and no call returns them.

Reuse is where this control is usually mis-evidenced, and AWS's own documentation is unusually direct about why. Within an account a friendly name for a user, group, role or policy must be unique — but only while it exists. AWS documents the exact failure IA-04's reuse clause exists to prevent: an employee named John leaves, the IAM user John is deleted, a new employee named John arrives, a new IAM user John is created, and a policy written against the friendly name grants the new John access to what the old John left behind. Nothing in AWS prevents that. There is no cooling-off period, no reserved-name list, no setting. What AWS guarantees instead is narrower and worth reading precisely: the unique id is never reused, so the old John's AIDA... and the new John's AIDA... differ, and a resource-based policy or an aws:userId condition written against the unique id cannot be inherited by a successor. The identifier that is protected from reuse is the one nobody uses in policy by default.

So the honest evidence for the reuse limb is a comparison, not a field: DeleteUser events dated against the CreateDate of a live identifier bearing the same name — UserDetailList[].CreateDate is collected here and is the right side of that comparison, which is why no CreateUser lookup is listed. Note what to read on the left side: Username on a lookup-events entry is the REQUESTER, the administrator who ran the deletion, so the deleted identifier has to come out of the CloudTrailEvent JSON at requestParameters.userName. Reading Username as the deleted name is the easy mistake and it produces a comparison against the wrong string entirely. Three limits on the comparison, all hard. lookup-events reads management events for the last 90 DAYS only, so any reuse period your SSP states beyond 90 days cannot be evidenced from this call at all — a CloudTrail Lake event data store or an S3 trail with a longer retention is what closes that, and it is a different collection. The call is also Region-bound in a way that has nothing to do with GovCloud: IAM is a global service, its events are recorded in one Region, and lookup-events shows them in the Region where they occurred — so the same command run anywhere else returns an empty Events[] while succeeding, which is indistinguishable from a window in which nobody was deleted. And the comparison itself is a join between two commands' outputs, which the assertion grammar cannot express: it compares a field to a constant, never one response to another. Both of those are why the reuse limb is written into the notes as a manual reconciliation rather than dressed up as a clause below.

The IAM users this recipe enumerates are also, on a well-run estate, the smallest part of the answer. Workforce identifiers should be issued in an external identity provider and reach AWS through IAM Identity Center, where the identifier's authority is the ExternalIds pair naming the issuer — which is what the third call reads. An account with an empty UserDetailList and a populated identity store is in better shape than the reverse, and an assertion that ranges over IAM users will say almost nothing about it. Read the two together or read neither.

The identity-store calls are collected as EVIDENCE and deliberately carry no assertion. An earlier draft asserted that an Identity Center instance exists and that every identity-store user carries ExternalIds; both were withdrawn, because they fail an account that federates through an IAM SAML provider instead — which is a different architecture, not an IA-04 defect — and because the second is vacuous anyway on an instance with zero users, so the first does not guard it. An assertion that encodes an architectural preference as a control failure is worse than a paragraph saying which architecture this evidence reads best.

Emptiness traps to state rather than assert. list-instances returns a list whose documented minimum length is zero and whose maximum is ten, so an account with no instance returns an empty Instances[] rather than an error, and reading only the first entry misses up to nine. A DeleteUser lookup over a window in which nobody was deleted returns an empty Events[], indistinguishable from a window in which the trail was not recording. And GroupDetail carries no Tags, so the authorization-tag clause below cannot be extended to group identifiers at all; device and service identifiers are outside every call here.

Roles and groups are collected alongside users because their names are identifiers the control covers, and because the same reuse behaviour applies: RoleId and GroupId are never reused, while RoleName and GroupName are free the moment the resource is deleted.

## References

- {"title":"IAM User Guide: IAM identifiers — friendly names must be unique within an account, unique ids are never reused even when a deleted friendly name is re-created, and the worked example of a deleted user's name being re-created and inheriting policy access","url":"https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html"}
- {"title":"AWS CLI: iam list-users (Users[] always carries UserId, UserName, Arn, Path and CreateDate, and does NOT return Tags or PermissionsBoundary — use GetUser or GetAccountAuthorizationDetails for those)","url":"https://docs.aws.amazon.com/cli/latest/reference/iam/list-users.html"}
- {"title":"IAM API: RoleDetail — RoleId, RoleName, CreateDate and Tags as returned by GetAccountAuthorizationDetails","url":"https://docs.aws.amazon.com/IAM/latest/APIReference/API_RoleDetail.html"}
- {"title":"AWS CLI: sso-admin list-instances (Instances[] minimum length 0; InstanceArn, IdentityStoreId, OwnerAccountId, PrimaryRegion, Status ACTIVE | CREATE_IN_PROGRESS | CREATE_FAILED | DELETE_IN_PROGRESS)","url":"https://docs.aws.amazon.com/cli/latest/reference/sso-admin/list-instances.html"}
- {"title":"AWS CLI: identitystore list-users (requires --identity-store-id; Users[] with required IdentityStoreId and UserId, optional UserName, ExternalIds issuer/id pairs, UserStatus ENABLED | DISABLED, CreatedAt/CreatedBy)","url":"https://docs.aws.amazon.com/cli/latest/reference/identitystore/list-users.html"}
- {"title":"AWS CLI: iam get-account-authorization-details (--filter possible values User | Role | Group | LocalManagedPolicy | AWSManagedPolicy; the page describes the parameter as a comma-separated list while the CLI synopsis passes them space-separated, which is the form used here)","url":"https://docs.aws.amazon.com/cli/latest/reference/iam/get-account-authorization-details.html"}
- {"title":"AWS CLI: cloudtrail lookup-events — \"You can look up events that occurred in a Region within the last 90 days\"; Username is \"a user name or role name of the requester that called the API in the event returned\"; management events by default","url":"https://docs.aws.amazon.com/cli/latest/reference/cloudtrail/lookup-events.html"}
- {"title":"AWS GovCloud (US) User Guide: AWS CloudTrail — CloudFront, IAM and AWS STS events are recorded in us-gov-west-1, and Event history and lookup-events show these events in the Region where they occurred","url":"https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/govcloud-ct.html"}
- {"title":"AWS GovCloud (US) User Guide: IAM Identity Center — \"Multi-Region support is presently not available\", FIPS endpoints for console/SDK/CLI, and the arn:aws-us-gov:sso:::instance/<SSOInstanceId> pattern","url":"https://docs.aws.amazon.com/govcloud-us/latest/UserGuide/govcloud-sso.html"}
- {"title":"IAM API: GroupDetail — GroupId is \"the stable and unique string identifying the group\"; the type carries no Tags member","url":"https://docs.aws.amazon.com/IAM/latest/APIReference/API_GroupDetail.html"}
