Detection on cloud infrastructure requires understanding a completely different log format from Windows events. The principles are the same (who, what, where, when, why), but the schema, the data, and the attack surface all differ.
Why Cloud Logs Are Different
On-premises logs describe OS operations — processes, files, network connections. Cloud audit logs describe API operations — because in cloud environments, everything (creating a VM, attaching a role, reading an S3 bucket) goes through an API.
The adversary goal is the same: gain access, escalate privilege, persist, exfiltrate. But the actions look like:
iam:CreateAccessKeyinstead of adding a user to a local admin groups3:GetObjectin a loop instead ofrobocopy /eec2:CreateSecurityGroup --ingress 0.0.0.0/0instead of disabling the Windows firewall
AWS CloudTrail
CloudTrail is AWS’s primary audit trail. Every API call made to AWS services generates a CloudTrail event — regardless of how the call was made (Console, CLI, SDK, Lambda function).
{
"eventVersion": "1.08",
"userIdentity": {
"type": "AssumedRole",
"principalId": "AROAEXAMPLEID:session-name",
"arn": "arn:aws:sts::123456789012:assumed-role/AdminRole/session-name",
"accountId": "123456789012",
"sessionContext": {
"sessionIssuer": {
"type": "Role",
"arn": "arn:aws:iam::123456789012:role/AdminRole",
"accountId": "123456789012",
"userName": "AdminRole"
},
"webIdFederationData": {},
"attributes": {
"creationDate": "2024-03-15T08:00:00Z",
"mfaAuthenticated": "false"
}
}
},
"eventTime": "2024-03-15T09:23:14Z",
"eventSource": "iam.amazonaws.com",
"eventName": "CreateAccessKey",
"awsRegion": "us-east-1",
"sourceIPAddress": "203.0.113.55",
"userAgent": "aws-cli/2.13.0",
"requestParameters": {
"userName": "backup-user"
},
"responseElements": {
"accessKey": {
"accessKeyId": "AKIAEXAMPLEKEYID",
"status": "Active",
"userName": "backup-user",
"createDate": "Mar 15, 2024 9:23:14 AM"
}
},
"eventID": "12345678-1234-1234-1234-123456789012",
"readOnly": false,
"eventType": "AwsApiCall"
} Key CloudTrail fields for detection
| Field | Detection use |
|---|---|
userIdentity.type | Is this a User, Role session, Service, or Root? |
userIdentity.arn | The specific principal (account + role + session) |
eventName | The API action called — this is your “what” |
eventSource | Which AWS service (iam.amazonaws.com, s3.amazonaws.com) |
sourceIPAddress | Where the call originated |
errorCode | Present on failed calls — AccessDenied sequences are reconnaissance patterns |
readOnly | True for read operations; false for writes/mutations |
Azure Activity Log
The Azure Activity Log records control-plane operations across an Azure subscription — resource creation, role assignments, policy changes. It is distinct from Entra ID (Azure AD) sign-in and audit logs.
{
"time": "2024-03-15T09:23:14.882Z",
"operationName": {
"value": "Microsoft.Authorization/roleAssignments/write",
"localizedValue": "Create role assignment"
},
"status": {
"value": "Succeeded"
},
"caller": "attacker@victim.onmicrosoft.com",
"tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"subscriptionId": "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
"resourceId": "/subscriptions/.../resourceGroups/prod-rg/providers/Microsoft.Compute/virtualMachines/web-01",
"properties": {
"requestbody": "{\"properties\":{\"roleDefinitionId\":\"...Owner...\",\"principalId\":\"...\"}}",
"statusCode": "Created"
}
}
The most important Activity Log events for detection:
| Operation | Why it matters |
|---|---|
roleAssignments/write | Privilege escalation — someone assigned a role |
policyAssignments/write | Policy bypass — attacker exempting resources |
virtualMachines/runCommand/action | Code execution via Azure Run Command |
managedIdentities/write | Persistence via managed identity |
deployments/write | Infrastructure changes (backdoor via ARM template) |
GCP Audit Logs
GCP organizes audit logs into three types that you must treat differently:
| Type | What it records | Default | Cost |
|---|---|---|---|
| Admin Activity | Control plane changes — creating VMs, modifying IAM | Always on | Free |
| Data Access | Reading/writing data — GCS GetObject, BigQuery reads | Off | Billable |
| System Event | GCP-initiated operations — live migration | Always on | Free |
{
"logName": "projects/my-project/logs/cloudaudit.googleapis.com%2Factivity",
"resource": {
"type": "iam_role",
"labels": { "project_id": "my-project" }
},
"timestamp": "2024-03-15T09:23:14.123Z",
"protoPayload": {
"@type": "type.googleapis.com/google.cloud.audit.AuditLog",
"authenticationInfo": {
"principalEmail": "attacker@compromised.iam.gserviceaccount.com"
},
"requestMetadata": {
"callerIp": "203.0.113.55",
"callerSuppliedUserAgent": "google-cloud-sdk/456.0.0"
},
"serviceName": "iam.googleapis.com",
"methodName": "google.iam.admin.v1.CreateServiceAccountKey",
"resourceName": "projects/my-project/serviceAccounts/victim-sa@my-project.iam.gserviceaccount.com",
"status": {}
}
}
For detection: protoPayload.methodName is your “what”, protoPayload.authenticationInfo.principalEmail is your “who”, and protoPayload.requestMetadata.callerIp is your “where.”