Join our Newsletter — 33% off our NHI Course
Home› Guides› How to detect AWS access key creation for…
Guide Identity Visibility, Posture & Threat Detection

How to detect AWS access key creation for another user: CloudTrail logic, alerts and triage steps

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 11 November 2026 13 min read
On this page

When one AWS principal creates an access key for a different IAM user, it has just minted a permanent credential that it controls but that is attributed to someone else. That is the persistence move MITRE ATT&CK records as T1098.001 Additional Cloud Credentials, and in most accounts it looks almost identical to a user rotating their own key. This runbook shows how to tell the two apart in CloudTrail, how to hunt the last 90 days and older history, how to build a near real-time alert with EventBridge, and how to triage and contain a hit without breaking a production integration. It is for cloud security engineers and detection engineers in single accounts or AWS Organizations. For the wider picture of key risk, see the AWS Access Keys Security Guide.

This is an independent guide from NHI Mgmt Group, based on AWS's public documentation as of November 2026. It is not sponsored or reviewed by AWS. Product features change, so confirm settings against AWS's current documentation.

Key takeaways

  • The signal is caller not equal to target. CreateAccessKey takes an optional UserName; if it is omitted, IAM creates the key for the identity that signed the request. A present requestParameters.userName that differs from the caller is the event to examine.
  • Role callers are always "another user". Roles cannot own access keys, so any CreateAccessKey from an AssumedRole session creates a key for someone else. Allow-list the provisioning roles that legitimately do this and alert on the rest.
  • Look in us-east-1. IAM events are recorded in US East (N. Virginia), and your multi-Region trail must have IncludeGlobalServiceEvents set to true. An EventBridge rule in any other Region never sees them.
  • Pattern languages cannot compare two fields. EventBridge patterns and CloudWatch metric filters compare a field with a literal. Narrow with the pattern, then do the caller versus target comparison in a Lambda function or in SQL.
  • Contain by deactivating, not deleting. update-access-key --status Inactive stops the key at once and is reversible if the key turns out to be a legitimate integration; deletion destroys evidence and cannot be undone.

When you need this

  • Any account that still has IAM users: as long as long-term keys exist, the ability to create one for another user is a privilege escalation and persistence path. A low-privileged principal with iam:CreateAccessKey on an administrator user becomes that administrator.
  • After a suspected key compromise: attackers who hold one key often create a second on a different user so that rotating the first key does not remove them. The How to Investigate CloudTrail for a Compromised Access Key runbook treats every key created this way as a new anchor.
  • Building a cloud identity detection baseline: this is one of the highest-value, lowest-volume IAM detections, because legitimate cross-user key creation is rare and should come from a small set of known automation.
  • Audit evidence: NIST SP 800-53 AC-2(4) Automated Audit Actions asks for automatic auditing of account creation and modification; credential additions to an existing account fall squarely within it.

Before you start

RequirementWhy it mattersHow to check
A multi-Region trail with global service eventsIAM events have been recorded in us-east-1 since 22 November 2021; a multi-Region trail must have IncludeGlobalServiceEvents trueaws cloudtrail describe-trails and get-trail-status; confirm IsMultiRegionTrail, IncludeGlobalServiceEvents and that logging is on
Management events loggedCreateAccessKey is a write management event; trails log management events by defaultCheck the trail's event selectors have not excluded write events
Athena table over the trail bucketEvent history covers only 90 days; older hunting needs the S3 logsCreate the CloudTrail table with partition projection, pointing the location at the us-east-1 prefix
A list of approved key creatorsThe only way to separate a provisioning pipeline from an attackerAsk platform teams which roles or users create keys for others, and why
Read permissionsHunting must not change anythingcloudtrail:LookupEvents, Athena and S3 read, iam:ListAccessKeys, iam:GetAccessKeyLastUsed

CloudTrail Lake is an option for existing customers, but AWS states it is no longer open to new customers from 31 May 2026, so this runbook uses Athena and EventBridge. See the AWS CloudTrail Guide for trail design.

Step-by-step

Steps 1 to 5 are read-only or create detection resources only. Step 6 changes a credential and is reversible.

Step 1: Understand the fields that decide the case

Caller userIdentity.typeWhere the caller's name isKey created forDefault verdict
IAMUser, no requestParameters.userNameuserIdentity.userNameThe caller itselfSelf-service; normal, but watch key count and age
IAMUser, userName equal to calleruserIdentity.userNameThe caller itselfSelf-service
IAMUser, userName different from calleruserIdentity.userNameAnother userAlert: rare for humans, common in attacks
AssumedRolesessionContext.sessionIssuer.arn (top-level userName is absent)Always another userAlert unless the issuer role is on the approved list
Root, no userNameAccount alias at mostThe root userCritical: a root access key
Root, with userNameAccount alias at mostAn IAM userAlert: root use for IAM administration
FederatedUsersessionContext.sessionIssuerAnother user if userName is presentAlert: GetFederationToken sessions are unusual

Also record sourceIPAddress, userAgent, sessionContext.attributes.mfaAuthenticated, errorCode and the new key ID from responseElements. AWS logs the full responseElements for mutating events, but the secret access key is only ever returned to the caller at creation. Console users signing in through IAM Identity Center appear as AssumedRole sessions, so the session name in userIdentity.arn identifies the person behind the role.

Step 2: Hunt the last 90 days in Event history

Event history needs no trail and covers 90 days of management events per Region. Query us-east-1 explicitly:

aws cloudtrail lookup-events --region us-east-1 \
  --lookup-attributes AttributeKey=EventName,AttributeValue=CreateAccessKey \
  --start-time 2026-08-13T00:00:00Z

Each result holds the raw event in CloudTrailEvent. Parse it and apply the Step 1 table. In an organisation, repeat per member account, or use the organisation trail in Step 3 instead.

Step 3: Hunt older history with Athena

In the Athena CloudTrail table, requestparameters and responseelements are strings, so extract fields with JSON functions. Always filter on the timestamp partition to limit the data scanned.

SELECT eventtime,
       useridentity.type AS caller_type,
       useridentity.arn AS caller_arn,
       useridentity.sessioncontext.sessionissuer.arn AS issuer_arn,
       json_extract_scalar(requestparameters, '$.userName') AS target_user,
       json_extract_scalar(responseelements, '$.accessKey.accessKeyId') AS new_key_id,
       sourceipaddress, useragent, errorcode
FROM cloudtrail_logs
WHERE eventsource = 'iam.amazonaws.com'
  AND eventname = 'CreateAccessKey'
  AND "timestamp" >= '2025/11/01'
  AND json_extract_scalar(requestparameters, '$.userName') IS NOT NULL
  AND (useridentity.type <> 'IAMUser'
       OR useridentity.username <> json_extract_scalar(requestparameters, '$.userName'))
ORDER BY eventtime;

Keep rows with an errorcode such as AccessDenied: a denied attempt to create a key for an administrator is a strong sign that someone is probing for escalation paths. Add the same query for UpdateAccessKey (an inactive key reactivated by another principal) and CreateLoginProfile (console password added to an API-only user), which serve the same purpose for an attacker.

Step 4: Build the real-time rule in us-east-1

EventBridge receives CloudTrail events on the default event bus with the detail type AWS API Call via CloudTrail, provided a trail is logging. Write management events are matched by rules in the normal ENABLED state. Create the rule in us-east-1 and narrow it to calls that name a target user:

{
  "source": ["aws.iam"],
  "detail-type": ["AWS API Call via CloudTrail"],
  "detail": {
    "eventSource": ["iam.amazonaws.com"],
    "eventName": ["CreateAccessKey"],
    "requestParameters": { "userName": [{ "exists": true }] }
  }
}

The pattern cannot test whether the target equals the caller, because EventBridge operators compare a field only with literal values. Send matches to a small Lambda function that:

  1. Drops events where userIdentity.type is IAMUser and userIdentity.userName equals requestParameters.userName.
  2. Drops events whose sessionContext.sessionIssuer.arn is on the approved creator list, but only when the target user also matches that creator's expected naming or path (a provisioning role creating keys for svc- users should not be creating one for admin- users).
  3. Raises everything else to your SIEM or on-call channel with the Step 1 fields, the new key ID and the target user's attached policies.

Add a second rule with no userName condition and "userIdentity": { "type": ["Root"] } so that any root access key creation pages immediately. For an organisation, forward the matched events from each member account's us-east-1 default bus to a central security account bus. See the Cloud Detection Engineering Guide for pipeline design.

Step 5: Add the layers that need no code

  • CloudWatch Logs metric filter: if the trail delivers to CloudWatch Logs, a filter such as { ($.eventName = "CreateAccessKey") && ($.userIdentity.type = "AssumedRole") } counts role-initiated key creation for a simple alarm. Like EventBridge, metric filter syntax compares fields with literals only.
  • GuardDuty: Persistence:IAMUser/AnomalousBehavior (default severity Medium) is raised when a persistence API such as CreateAccessKey is called in a way the machine learning model finds anomalous for that identity. It complements, not replaces, the deterministic rule, because a planned attacker action from a usual location may not look anomalous. See the Amazon GuardDuty Guide.

Step 6: Triage and contain a hit

  1. Find the approval: look for a change ticket or pipeline run that matches the caller, time and target. Ask the caller's owner, not the target user's owner.
  2. Check use of the new key: aws iam get-access-key-last-used --access-key-id <new key> shows the last service and Region; search CloudTrail for userIdentity.accessKeyId equal to the new key.
  3. Contain: if there is no approval, run aws iam update-access-key --user-name <target> --access-key-id <new key> --status Inactive. Then examine the caller: a role session needs its source credentials found, an IAM user caller needs its own keys reviewed.
  4. Scope: treat both the caller and the new key as compromised anchors and follow the Cloud Access Key Leak Playbook.
  5. Close: delete the key only after evidence is preserved and the owner of any affected integration has confirmed it is not in use.

Verify it worked

  • Test in a sandbox account: from a test role, create a key for a test user. The event should appear in us-east-1 Event history within minutes, the EventBridge rule's invocation metric should increment, and the alert should arrive with the issuer role ARN and target user name filled in.
  • Test the suppression: have the test user create its own key without --user-name. No alert should fire.
  • Test the denial path: attempt creation from a principal without permission and confirm the Athena hunt returns the AccessDenied row.
  • Clean up: deactivate and delete the test keys.

Rollback and common errors

  • Rollback of containment: update-access-key --status Active restores a key that turned out to be legitimate. The secret was never changed, so the integration resumes without redeployment.
  • Rollback of the detection: disable the EventBridge rule rather than deleting it while you tune the allow-list.
  • Rule in the wrong Region: the most common reason the alert never fires. IAM events are recorded in us-east-1.
  • Trail missing global events: a single-Region trail outside us-east-1, or a trail with IncludeGlobalServiceEvents false, misses IAM entirely.
  • Allow-listing whole roles: approving a provisioning role without constraining its targets lets an attacker who reaches that role create keys for anyone. Constrain by target path or tag in both the detection and the role's IAM policy.
  • Ignoring management account and SCP blind spots: AWS states SCPs do not affect users or roles in the management account, so preventive SCPs cannot stand in for detection there.
  • Two-key ceiling surprises: IAM allows at most two access keys per user. A cross-user creation that fails with LimitExceeded is still an attempted persistence action and belongs in the hunt.

Hardening afterwards

ControlSettingEffect
Self-service only for humansGrant iam:CreateAccessKey on arn:aws:iam::*:user/${aws:username}, as in AWS's own self-management example policyUsers can rotate their own keys but not mint keys for others
Organisation guardrailSCP denying iam:CreateAccessKey unless aws:PrincipalARN matches the approved provisioning role; test in a non-production OU firstMember accounts cannot create keys outside the pipeline; SCPs grant nothing and do not cover the management account
Fewer IAM usersMove people to IAM Identity Center and workloads to roles or OIDC federationNo IAM users means no target for this technique
Escalation path reviewFind principals that hold iam:CreateAccessKey on *Removes the escalation before it is used; see How to Find IAM Privilege Escalation Paths in AWS

Small account or large organisation

A single account with a handful of IAM users can run the Event history hunt weekly and rely on the EventBridge rule with an email target. An organisation with hundreds of accounts should deploy the rule and Lambda through StackSets to every member account's us-east-1, forward to a central bus, keep the approved creator list in version control, and pair the detection with an SCP once the inventory of legitimate creators is complete. Applying the SCP first breaks unknown automation. See the AWS Organizations and SCPs Guide.

Metrics

  • Cross-user key creations per month, split into approved and unapproved (unapproved should be zero after triage).
  • Mean time from event to alert (target: minutes) and from alert to deactivation.
  • Accounts with the rule deployed in us-east-1, as a percentage of all accounts (target 100).
  • Principals holding iam:CreateAccessKey on resources other than themselves (trend down).
  • IAM users remaining (trend down, since each is a possible target).

Framework mapping

FrameworkReferenceRelevance
MITRE ATT&CKT1098.001 Additional Cloud Credentials; T1098 Account Manipulation; T1078.004 Cloud AccountsThe technique detected, its parent, and the use of the new key
NIST SP 800-53 Rev 5AC-2(4); AU-6; AU-12; SI-4; AC-6; IA-5Automated audit of account changes, log review, monitoring, least privilege over who can issue authenticators
NIST CSF 2.0DE.CM-03; DE.AE-02; PR.AA-05Monitoring identity activity, analysing adverse events, least privilege and separation of duties

Where identity fits: the target of this technique is almost always a non-human identity, an IAM user that exists only to hold keys for an integration, because nobody notices an extra key on it. Owners, expected creators and key counts for these users belong in your NHI inventory. See MITRE ATT&CK T1098.001 Additional Cloud Credentials for the same technique across Entra ID and Google Cloud.

Practitioner checklist

  • Confirm a multi-Region trail with global service events is logging.
  • Hunt 90 days of CreateAccessKey in us-east-1 Event history and classify caller against target.
  • Hunt older history in Athena, including denied attempts, UpdateAccessKey and CreateLoginProfile.
  • Write down the approved key creators and the targets each may create keys for.
  • Deploy the EventBridge rule in us-east-1 with a Lambda comparison and a separate root key rule.
  • Test both the alert and the self-service suppression in a sandbox account.
  • Contain unapproved keys by deactivation, preserve evidence, then delete.
  • Restrict human key creation to ${aws:username} and add an SCP once creators are known.

Standards and references

Related NHI Mgmt Group resources: AWS Access Keys Security Guide · How to Investigate CloudTrail for a Compromised Access Key · How to rotate an AWS IAM access key without downtime · How to find unused AWS IAM roles and access keys

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 11 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org