ASSURED

Cloud and identity logs

The four endpoint surfaces share an assumption: there is a host, and the host records what ran on it. Control-plane activity breaks that assumption. When an attacker with stolen keys enumerates your S3 buckets, no process tree exists anywhere you can see. The only record is the audit log of the cloud provider or identity provider, so parsing that record is the investigation. This page uses AWS CloudTrail Records and logs API activity within an AWS account, the audit trail for security and forensic work. and the major IdPs as the worked vocabulary; Azure Activity Logs and GCP audit logs differ in field names, not in concept.

Anatomy of a CloudTrail record

Every management API call becomes one JSON event. Most fields are noise for triage; these are the ones that decide verdicts:

{
  "eventTime": "2026-07-08T03:12:44Z",
  "eventSource": "s3.amazonaws.com",
  "eventName": "ListBuckets",
  "userIdentity": {
    "type": "AssumedRole",
    "arn": "arn:aws:sts::111122223333:assumed-role/ci-deploy/build-runner",
    "accessKeyId": "ASIA...",
    "sessionContext": {
      "sessionIssuer": { "userName": "ci-deploy" },
      "attributes": { "mfaAuthenticated": "false" }
    }
  },
  "sourceIPAddress": "203.0.113.50",
  "userAgent": "aws-cli/2.17.0 ...",
  "errorCode": "AccessDenied"
}

eventSource + eventName

The verb. Which service, which API call. Reads (List*, Describe*, Get*) are reconnaissance; writes (Create*, Put*, Attach*, Update*) change the environment. A burst of reads followed by a policy write is the cloud version of recon-then-privilege-escalation.

userIdentity

The actor, and the field juniors misread most. type tells you whether this was a long-lived IAM user, an assumed role, root, or a service. For AssumedRole, the ARN names both the role and the session; sessionContext.sessionIssuer names where the session came from.

accessKeyId prefix

AKIA means long-term IAM user credentials; ASIA means temporary credentials issued by STS AWS Security Token Service. The AWS service that issues temporary credentials when an identity assumes a role. STS credentials expire on a schedule (minutes to hours) and carry an ASIA key prefix, distinguishing them from long-term AKIA user keys. . Long-term keys showing up in new places are a bigger deal than short-lived ones, and stolen ASIA creds have a built-in expiry clock that shapes the attacker’s tempo.

sourceIPAddress + userAgent

Where the call physically came from and what tool made it. A role that normally acts from a VPC CIDR via an SDK suddenly acting from a residential IP via aws-cli is a story in two fields. Console sessions, SDKs, and Terraform all have recognizable agent strings.

errorCode

Failures are telemetry. A spray of AccessDenied across many services from one identity is permission enumeration: the attacker mapping what the stolen credential can do. Silence after the spray means they found what works.

mfaAuthenticated

Inside sessionContext.attributes. Whether this session was backed by Multi-Factor Authentication (MFA) Security system requiring two or more verification methods to grant access, combining something you know, have, or are. . Sensitive actions from non-MFA sessions deserve a harder look, especially where policy says they should be impossible.


Follow the identity chain, not the process tree

The cloud equivalent of parent-child lineage is role chaining. An identity assumes a role, that session assumes another role, and each hop is a separate AssumeRole event in the trail. Reconstructing the chain answers the question the process tree used to answer: who is actually acting here?

1

Start at the suspicious event. userIdentity.sessionContext.sessionIssuer names the role the session came from.

2

Search the trail for the AssumeRole call that created that session (match the role ARN and the session name; the session name is attacker-chosen and often a tell in itself).

3

That event’s own userIdentity is the previous link. Repeat until you reach a human, a long-term key, or a workload. That endpoint of the chain is your Subject-phase entity.

Parse from the organization trail

Each account’s local trail can be silenced by anyone with admin in that account, and attackers know it. The organization-level trail aggregates every member account into storage the compromised account cannot touch, which makes it both the tamper-resistant copy and the only place a cross-account role chain appears end to end. If your alert came from one account’s console, re-run the pivot against the org trail before trusting an absence.


The IMDS pattern

The instance metadata service (IMDS) at 169.254.169.254 hands every EC2 workload the temporary credentials for its instance role. That design makes one intrusion shape so common it deserves its own recognition pattern: an attacker who can make a server fetch a URL (SSRF) or who lands on the box reads the metadata endpoint, steals the role credentials, and replays them from infrastructure they control.

The shape

Web app receives a crafted request → server fetches 169.254.169.254/latest/meta-data/iam/… → role credentials exfiltrated → CloudTrail shows that role acting from an IP that is not the instance.

The tell in the trail

An instance role’s credentials used from outside the expected network path. That single discrepancy (role says “this EC2 instance,” source IP says “somewhere else”) is the highest-signal field comparison on this page. GuardDuty ships a finding class for exactly this.

Context that changes the read

IMDSv2 requires a session token first, which kills most SSRF variants of the theft. If the fleet enforces IMDSv2 and you still see off-box credential use, think on-host compromise rather than SSRF.


IdP sign-in logs

For identity-provider alerts ( Okta Identity platform with SSO, MFA, lifecycle management, and federation across thousands of apps. , Azure AD (Entra ID) Microsoft's cloud identity and access management; SSO, MFA, conditional access, and integration with SaaS apps. ), the sign-in record is the raw material. The fields rhyme with CloudTrail’s: who, from where, with what client, and did the second factor actually happen.

Outcome plus MFA result, together. A success with no MFA event behind it is the signature of session-token replay: the attacker stole a valid cookie (adversary-in-the-middle phishing) and never had to authenticate. The login “succeeded” without any credential being entered.

Denial patterns before an approval. A run of push-notification denials followed by a small-hours approval is MFA fatigue: the user gave in, not logged in. The timeline of factor events tells that story; the final “success” alone hides it.

Client, device, and network novelty. New device fingerprint, new OS, new ASN, or geography inconsistent with the user’s last sign-in. Any one alone is weak (VPNs and travel exist); novelty across several fields at once, against the user’s own baseline, is what earns escalation of attention.

What the session did next. The sign-in is only the entry. Follow the session ID forward: consent granted to a new OAuth app, a mail rule created, an API token minted. Those follow-on events are where a compromised session becomes a compromised account.

Where this shows up in the worked examples

The Uncover chapter’s worked example runs this exact surface end to end: a GuardDuty finding, the CloudTrail pivot, and the IdP cross-check. This page gives you the field-level anatomy that walkthrough assumes.

Key Takeaway

The control plane is a first-class parsing surface. Read the verb (eventName), identify the actor (userIdentity, and the role chain behind it), compare where the call came from against where it should come from, and treat failures and missing MFA events as signal. No process tree will come to save you here; the log is all there is.

Next up

Alert working example

Three cases worked side by side through the Alert phase: a real phishing intrusion, a developer-workstation false-positive, and a SaaS token theft read entirely from identity logs. All three threads continue on every later chapter's example.

See the worked examples