# The mechanism that ends a temporary or emergency account without anyone deciding to: the AWS Config rule that measures how long an IAM credential has gone unused, the period it is configured with, the remediation configuration proving the revocation fires automatically, and an empty non-compliant set showing nothing has outlived the period

> FedRAMP Consolidated Rules for 2026 v2026.07.14.01 · updated 2026-07-14
> Canonical page: /collect/temporary-account-automatic-revocation

Recipe id: `temporary-account-automatic-revocation` · 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-AAM`
- KSI `KSI-IAM-SNU`
- control `ac-2.2`

## Collection

Kind: `config-rule`

```sh
# iam-user-unused-credentials-check-rule
aws configservice describe-config-rules --config-rule-names iam-user-unused-credentials-check
# iam-user-unused-credentials-check
aws configservice get-compliance-details-by-config-rule --config-rule-name iam-user-unused-credentials-check --compliance-types NON_COMPLIANT
# iam-user-unused-credentials-check-remediation
aws configservice describe-remediation-configurations --config-rule-names iam-user-unused-credentials-check
# get-account-authorization-details
aws iam get-account-authorization-details --filter User
```

## Expected output

The four responses are collected unprojected, so every field below is the name AWS returns and the name the assertions address. From describe-config-rules, ConfigRules[] with one entry: Source.SourceIdentifier IAM_USER_UNUSED_CREDENTIALS_CHECK, ConfigRuleState ACTIVE, and InputParameters as a JSON-formatted STRING (not an object) that must be parsed before maxCredentialUsageAge can be read from it — an int, a number of DAYS, defaulting to 90. From get-compliance-details-by-config-rule, an EvaluationResults array whose every entry is one IAM user still holding a password or an active access key unused beyond that period; empty is the passing shape. From describe-remediation-configurations, RemediationConfigurations[] — a list whose minimum length is ZERO, so a rule with no remediation attached returns an empty array rather than an error, which is why one assertion tests that the first entry exists at all before the others read Automatic, TargetType SSM_DOCUMENT and TargetId. From get-account-authorization-details, UserDetailList[] with one entry per IAM user carrying UserName, CreateDate as an ISO-8601 timestamp, and Tags as a list of key/value pairs.

## Assertions

- {"field":"iam-user-unused-credentials-check-rule.ConfigRules[].ConfigRuleState","op":"eq","value":"ACTIVE","controls":["ac-2.2"],"description":"The rule that measures credential dormancy is evaluating, not deleting or stopped."}
- {"field":"iam-user-unused-credentials-check-rule.ConfigRules[].InputParameters.maxCredentialUsageAge","op":"lte","value":90,"controls":["ac-2.2"],"description":"The configured period is no longer than the organization-defined maximum; 90 is the AWS default — substitute the shorter period if your SSP states one. InputParameters arrives as a JSON string and must be parsed before this field exists."}
- {"field":"iam-user-unused-credentials-check.EvaluationResults","op":"count_eq","value":0,"controls":["ac-2.2"],"description":"No IAM user holds a password or an active access key that has gone unused beyond that period."}
- {"field":"iam-user-unused-credentials-check-remediation.RemediationConfigurations[0].TargetId","op":"exists","controls":["ac-2.2"],"description":"A remediation configuration is attached to the rule at all — the list is empty when none is, and every clause below it passes vacuously over an empty list."}
- {"field":"iam-user-unused-credentials-check-remediation.RemediationConfigurations[].Automatic","op":"eq","value":true,"controls":["ac-2.2"],"description":"The revocation fires on non-compliance without a human starting it — the word 'automatically' in the control, as a field."}
- {"field":"iam-user-unused-credentials-check-remediation.RemediationConfigurations[].TargetId","op":"eq","value":"AWSConfigRemediation-RevokeUnusedIAMUserCredentials","controls":["ac-2.2"],"description":"What fires is the runbook that deactivates expired access keys and deletes expired login profiles, not an alert that someone has to read."}
- {"field":"get-account-authorization-details.UserDetailList[].CreateDate","op":"max_age_days","value":90,"where":[{"field":"Tags[?Key=='AccountType'].Value","op":"in","value":["temporary","emergency"]}],"controls":["ac-2.2"],"description":"No IAM user your tagging marks as temporary or emergency is older than the same organization-defined period — the still-active account the dormancy rule cannot see."}

## GovCloud

AWS Config and IAM_USER_UNUSED_CREDENTIALS_CHECK are available in both GovCloud (US) Regions — the rule's published exclusion list names no GovCloud Region — as is Systems Manager Automation. User and role ARNs, and the AutomationAssumeRole the runbook assumes, use partition arn:aws-us-gov. The rule reports on a global IAM resource type, so deploy it in exactly one Region: a periodic rule on a global type evaluates in every Region it is added to, and duplicating it duplicates the evaluations rather than the coverage.

## Notes

AC-02 (02) asks for something narrower than it looks: not that temporary and emergency accounts are reviewed, but that they END on their own after a stated period. Most of that sentence is in this output. The period is the rule's maxCredentialUsageAge. The ending is the remediation configuration — Automatic true and TargetId AWSConfigRemediation-RevokeUnusedIAMUserCredentials, a runbook whose documented behaviour is to deactivate expired access keys and delete expired login profiles. That nothing has outlived the period is the empty NON_COMPLIANT set. A screenshot of a console page proves none of those; these four calls prove all of them.

What they do not prove is the control's subject. The Config rule measures every IAM user in the account; nothing in this output says WHICH users are the temporary and emergency ones, and the control is about those. A human names that population — which is exactly why this recipe is partial and not full, and why the CreateDate assertion is written as a filter over your own tagging rather than as a claim over the account.

Two scope edges to write into the assessment rather than discover during it. The rule sees IAM users, so an account whose privileges live in an assumed role or an IAM Identity Center permission set is out of its reach — those expire by session duration instead, which is a different artifact (see the IA-11 recipe). And the rule measures INACTIVITY, not age: a temporary account that is used every day is compliant no matter how long ago it should have been closed. The fourth call is what narrows that gap, by reading CreateDate against your own tagging of which accounts were meant to be temporary.

That last check is only as complete as the tagging behind it, and no AWS Config rule can make it complete: REQUIRED_TAGS does not support AWS::IAM::User, so tag coverage over IAM users cannot be asserted from Config at all. Treat the tagging standard as a written control with a manual sample. Read the CreateDate assertion for what it is — a check over exactly the accounts your tagging labels, which passes without saying anything on an estate that labels none.

The first remediation assertion is not redundant with the two that follow it. describe-remediation-configurations returns a list whose minimum length is zero, so a rule with NO remediation attached returns an empty array, and a clause of the form 'every entry is Automatic' is true over it. Testing that the first entry exists is what turns 'the revocation fires by itself' from a claim into a field.

The 90 in the assertions is the AWS default, not a FedRAMP number. Replace it in both places with the period your SSP commits to, and keep the runbook's own MaxCredentialUsageAge parameter equal to the period of the rule that triggers it — AWS documents that discipline for the access-keys-rotated pairing (match MaxCredentialUsageAge to that rule's maxAccessKeyAge) rather than for this rule, but the failure it prevents is the same one: a mismatch means the detection window and the revocation window disagree silently. Re-evaluating the rule within 4 hours of its last evaluation returns the previous result, so collect on the rule's own cadence rather than on demand.

## References

- {"title":"AWS Config managed rule: iam-user-unused-credentials-check (IAM_USER_UNUSED_CREDENTIALS_CHECK; periodic; maxCredentialUsageAge default 90 days; re-evaluation within 4 hours has no effect)","url":"https://docs.aws.amazon.com/config/latest/developerguide/iam-user-unused-credentials-check.html"}
- {"title":"AWSConfigRemediation-RevokeUnusedIAMUserCredentials — revokes unused IAM passwords and active access keys, deactivates expired access keys, deletes expired login profiles; its documented parameter pairing is MaxCredentialUsageAge to the access-keys-rotated rule's maxAccessKeyAge","url":"https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-aws-revoke-iam-user.html"}
- {"title":"AWS CLI: configservice describe-remediation-configurations (Automatic, TargetType SSM_DOCUMENT, TargetId, MaximumAutomaticAttempts)","url":"https://docs.aws.amazon.com/cli/latest/reference/configservice/describe-remediation-configurations.html"}
- {"title":"AWS CLI: configservice describe-config-rules (InputParameters is a JSON-formatted string; ConfigRuleState; Source.SourceIdentifier)","url":"https://docs.aws.amazon.com/cli/latest/reference/configservice/describe-config-rules.html"}
- {"title":"AWS Config managed rule: required-tags (REQUIRED_TAGS) — its supported resource types do not include AWS::IAM::User","url":"https://docs.aws.amazon.com/config/latest/developerguide/required-tags.html"}
- {"title":"IAM API: UserDetail (CreateDate and Tags on every user returned by GetAccountAuthorizationDetails)","url":"https://docs.aws.amazon.com/IAM/latest/APIReference/API_UserDetail.html"}
