Post

AWS CloudTrail and AWS Config — Audit Logging and Compliance

SCS-C03 Domain 1 — CloudTrail organisation trails, log integrity validation, Athena analysis, Config rules, conformance packs, and automated remediation

AWS CloudTrail and AWS Config — Audit Logging and Compliance

AWS CloudTrail

CloudTrail records every API call made in your AWS account — who did what, when, from where. It is the primary audit trail for AWS. Every action in the console, CLI, SDK, or any AWS service that calls another AWS service creates a CloudTrail event.


Trail Types

TypeScopeUse Case
Single-region trailOne region onlyLegacy, avoid
Multi-region trailAll current and future regionsStandard — always use this
Organisation trailAll accounts in an AWS OrganizationSecurity baseline — enables centralised logging

Organisation Trail

An organisation trail is created in the management account or delegated admin account. It automatically applies to all existing and new member accounts. Member accounts cannot modify or delete it. This is the correct way to centralise audit logs at scale.

1
2
3
4
5
6
7
8
9
10
11
# Create an organisation multi-region trail
aws cloudtrail create-trail \
  --name org-audit-trail \
  --s3-bucket-name org-cloudtrail-logs \
  --is-multi-region-trail \
  --is-organization-trail \
  --enable-log-file-validation \
  --kms-key-id arn:aws:kms:us-east-1:123456789012:key/mrk-abc123

# Start logging
aws cloudtrail start-logging --name org-audit-trail

CloudTrail is global for the management events of global services (IAM, STS, CloudFront) regardless of region. Always enable log file validation and KMS encryption.

📸 SCREENSHOT: CloudTrail → Trails → select trail → General details. Show the multi-region toggle enabled, organisation trail toggle enabled, log file validation enabled, and the S3 bucket destination.


Event Types

Event TypeWhat It CapturesDefault?
Management eventsControl plane — create, modify, delete resourcesEnabled (free)
Data eventsData plane — S3 object reads/writes, Lambda invocations, DynamoDB GetItemDisabled (costs extra)
Insights eventsAnomalous API activity — unusual call volumesDisabled (costs extra)

For the exam: Data events are critical for S3 forensics and detecting data exfiltration. Enable them on sensitive buckets (at minimum) or account-wide.


Log File Integrity Validation

CloudTrail creates a digest file every hour that contains hashes of all log files delivered in that period. Each digest file is signed with CloudTrail’s private key. If a log file is modified, deleted, or forged, the validation fails.

1
2
3
4
5
# Validate log integrity (checks all digest files in a time range)
aws cloudtrail validate-logs \
  --trail-arn arn:aws:cloudtrail:us-east-1:123456789012:trail/org-audit-trail \
  --start-time 2026-06-01T00:00:00Z \
  --end-time 2026-06-13T23:59:59Z

Exam gotcha: Log integrity validation only works if the trail was configured with --enable-log-file-validation from the start. Enabling it later only validates future logs.


Protecting CloudTrail Logs

The S3 bucket storing CloudTrail logs must be protected:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "Statement": [
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:DeleteObject",
      "Resource": "arn:aws:s3:::org-cloudtrail-logs/*"
    },
    {
      "Effect": "Deny",
      "Principal": "*",
      "Action": "s3:PutBucketPolicy",
      "Resource": "arn:aws:s3:::org-cloudtrail-logs",
      "Condition": {
        "ArnNotLike": {
          "aws:PrincipalArn": "arn:aws:iam::123456789012:role/CloudTrailRole"
        }
      }
    }
  ]
}

Also enable S3 Object Lock (WORM) with Compliance mode on the log bucket for tamper-proof retention. Enable MFA Delete on the bucket versioning so deletions require MFA.


Querying CloudTrail with Athena

CloudTrail logs are stored as JSON in S3. Use Athena to query them with SQL — far faster than searching raw JSON.

CloudTrail can automatically create an Athena table for you.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-- Find all actions by a specific user
SELECT eventtime, eventname, sourceipaddress, requestparameters
FROM cloudtrail_logs
WHERE useridentity.arn = 'arn:aws:iam::123456789012:user/alice'
  AND eventtime BETWEEN '2026-06-01' AND '2026-06-13'
ORDER BY eventtime DESC;

-- Find all failed API calls (access denied)
SELECT eventtime, eventname, errorcode, errormessage, useridentity.arn
FROM cloudtrail_logs
WHERE errorcode = 'AccessDenied'
ORDER BY eventtime DESC
LIMIT 100;

-- Find root account usage
SELECT eventtime, eventname, sourceipaddress
FROM cloudtrail_logs
WHERE useridentity.type = 'Root'
ORDER BY eventtime DESC;

-- Find IAM changes
SELECT eventtime, eventname, useridentity.arn, requestparameters
FROM cloudtrail_logs
WHERE eventsource = 'iam.amazonaws.com'
  AND eventname IN ('CreateUser','AttachUserPolicy','CreateAccessKey','PutUserPolicy')
ORDER BY eventtime DESC;

CloudWatch Logs Integration

Stream CloudTrail logs to CloudWatch Logs to create metric filters and alarms for real-time alerting.

Security-critical alarms to configure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Alarm: root account login
aws logs put-metric-filter \
  --log-group-name CloudTrail/DefaultLogGroup \
  --filter-name RootAccountUsage \
  --filter-pattern '{ $.userIdentity.type = "Root" && $.userIdentity.invokedBy NOT EXISTS && $.eventType != "AwsServiceEvent" }' \
  --metric-transformations MetricName=RootAccountUsage,MetricNamespace=CloudTrailMetrics,MetricValue=1

# Alarm: CloudTrail disabled
--filter-pattern '{ ($.eventName = StopLogging) }'

# Alarm: S3 bucket policy change
--filter-pattern '{ ($.eventSource = s3.amazonaws.com) && (($.eventName = PutBucketAcl) || ($.eventName = PutBucketPolicy) || ($.eventName = DeleteBucketPolicy)) }'

# Alarm: IAM policy change
--filter-pattern '{ ($.eventName = DeleteGroupPolicy) || ($.eventName = DeleteRolePolicy) || ($.eventName = DeleteUserPolicy) || ($.eventName = PutGroupPolicy) || ($.eventName = PutRolePolicy) || ($.eventName = PutUserPolicy) }'

# Alarm: security group changes
--filter-pattern '{ ($.eventName = AuthorizeSecurityGroupIngress) || ($.eventName = AuthorizeSecurityGroupEgress) || ($.eventName = RevokeSecurityGroupIngress) || ($.eventName = RevokeSecurityGroupEgress) }'

📸 SCREENSHOT: CloudWatch → Log groups → CloudTrail log group → Metric filters. Show the list of metric filters with their filter patterns and the corresponding CloudWatch alarms linked to SNS.


AWS Config

AWS Config records the configuration state of your AWS resources over time. It answers: “What did this resource look like at a specific point in time?” and “Has this resource drifted from its required configuration?”

Config is complementary to CloudTrail — CloudTrail records API calls (events), Config records resource state (snapshots and history).

Config Components

ComponentPurpose
Configuration recorderRecords resource configuration changes
Delivery channelWhere Config sends snapshots and history (S3 + SNS)
Config rulesEvaluate resources against desired configuration
Remediation actionsAutomatically fix non-compliant resources via SSM Automation
AggregatorView compliance across multiple accounts and regions
Conformance packA bundle of Config rules deployed together
1
2
3
4
5
6
7
8
9
# Enable Config (create recorder + delivery channel)
aws configservice put-configuration-recorder \
  --configuration-recorder name=default,roleARN=arn:aws:iam::123456789012:role/ConfigRole \
  --recording-group allSupported=true,includeGlobalResourceTypes=true

aws configservice put-delivery-channel \
  --delivery-channel name=default,s3BucketName=my-config-bucket,snsTopicARN=arn:aws:sns:...:config-notifications

aws configservice start-configuration-recorder --configuration-recorder-name default

Config Rules

Config rules evaluate your resources against a desired state. AWS provides managed rules (pre-built) and you can write custom rules using Lambda.

Key Managed Rules for the Exam

RuleWhat It Checks
s3-bucket-public-read-prohibitedNo S3 bucket allows public read
s3-bucket-server-side-encryption-enabledS3 buckets have encryption enabled
cloudtrail-enabledCloudTrail is enabled and logging
root-mfa-enabledRoot account has MFA enabled
iam-user-mfa-enabledAll IAM users have MFA
iam-password-policyAccount password policy meets requirements
restricted-sshNo security group allows SSH from 0.0.0.0/0
restricted-common-portsNo SG allows unrestricted access to common ports
rds-instance-public-access-checkRDS instances are not publicly accessible
encrypted-volumesAll EBS volumes are encrypted
guardduty-enabled-centralizedGuardDuty is enabled in all accounts
securityhub-enabledSecurity Hub is enabled
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Create a Config rule
aws configservice put-config-rule \
  --config-rule '{
    "ConfigRuleName": "s3-bucket-public-read-prohibited",
    "Source": {
      "Owner": "AWS",
      "SourceIdentifier": "S3_BUCKET_PUBLIC_READ_PROHIBITED"
    },
    "Scope": {
      "ComplianceResourceTypes": ["AWS::S3::Bucket"]
    }
  }'

# Check compliance
aws configservice get-compliance-details-by-config-rule \
  --config-rule-name s3-bucket-public-read-prohibited \
  --compliance-types NON_COMPLIANT

Automated Remediation

Config rules can trigger SSM Automation documents to automatically fix non-compliant resources.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
aws configservice put-remediation-configurations \
  --remediation-configurations '[{
    "ConfigRuleName": "s3-bucket-public-read-prohibited",
    "TargetType": "SSM_DOCUMENT",
    "TargetId": "AWS-DisableS3BucketPublicReadWrite",
    "Parameters": {
      "AutomationAssumeRole": {
        "StaticValue": {"Values": ["arn:aws:iam::123456789012:role/ConfigRemediationRole"]}
      },
      "S3BucketName": {
        "ResourceValue": {"Value": "RESOURCE_ID"}
      }
    },
    "Automatic": true,
    "MaximumAutomaticAttempts": 3,
    "RetryAttemptSeconds": 60
  }]'

Conformance Packs

A conformance pack is a collection of Config rules and remediation actions deployed as a single unit. AWS provides pre-built packs for common compliance frameworks.

1
2
3
4
5
6
7
8
9
# Deploy CIS AWS Foundations Benchmark conformance pack
aws configservice put-conformance-pack \
  --conformance-pack-name CIS-Benchmark \
  --template-s3-uri s3://aws-config-managed-rules/CISAwsFoundationsBenchmark.yaml

# Deploy across organisation (from delegated admin)
aws configservice put-organization-conformance-pack \
  --organization-conformance-pack-name CIS-Org-Wide \
  --template-s3-uri s3://aws-config-managed-rules/CISAwsFoundationsBenchmark.yaml

Config Aggregator

An aggregator collects compliance data from multiple accounts and regions into a single view.

1
2
3
4
5
6
7
# Create an organisation aggregator
aws configservice put-configuration-aggregator \
  --configuration-aggregator-name org-aggregator \
  --organization-aggregation-source '{
    "RoleArn": "arn:aws:iam::123456789012:role/ConfigAggregatorRole",
    "AllAwsRegions": true
  }'

CloudTrail vs Config — Exam Distinction

 CloudTrailConfig
RecordsAPI calls (who did what)Resource configuration state (what it looks like now)
Answers“Who deleted this security group rule?”“Was this S3 bucket ever publicly accessible?”
TimelineEvent-based logContinuous configuration snapshot
AlertingCloudWatch metric filtersConfig rules → SNS / EventBridge
ForensicsInvestigate what happenedInvestigate what state resources were in

Quick Reference

1
2
3
4
5
6
7
8
9
10
11
12
# CloudTrail
aws cloudtrail describe-trails
aws cloudtrail get-trail-status --name org-audit-trail
aws cloudtrail lookup-events --lookup-attributes AttributeKey=EventName,AttributeValue=DeleteBucket

# Config
aws configservice describe-configuration-recorders
aws configservice get-compliance-summary-by-resource-type
aws configservice list-discovered-resources --resource-type AWS::S3::Bucket
aws configservice get-resource-config-history \
  --resource-type AWS::EC2::SecurityGroup \
  --resource-id sg-abc123
This post is licensed under CC BY 4.0 by the author.