AWS CloudTrail - Audit Logging
AWS CloudTrail provides governance, compliance, and audit capabilities for your AWS account. CloudTrail logs, continuously monitors, and retains account activity related to actions across your AWS infrastructure.
Security Best Practice: Per O'Reilly "Security as Code" - "Log all API calls with CloudTrail. This is non-negotiable for security monitoring."
Quick Start
#r "../src/bin/Release/net8.0/publish/Amazon.JSII.Runtime.dll"
#r "../src/bin/Release/net8.0/publish/Constructs.dll"
#r "../src/bin/Release/net8.0/publish/Amazon.CDK.Lib.dll"
#r "../src/bin/Release/net8.0/publish/FsCDK.dll"
open FsCDK
open Amazon.CDK
open Amazon.CDK.AWS.CloudTrail
open Amazon.CDK.AWS.Logs
Basic CloudTrail (Secure Defaults)
Create a CloudTrail with all security best practices enabled by default.
stack "BasicCloudTrail" {
cloudTrail "SecurityAudit" {
// All secure defaults are automatically applied:
// - Multi-region trail (captures all regions)
// - Global service events included (IAM, STS, CloudFront)
// - Log file validation enabled (integrity checking)
// - CloudWatch Logs integration enabled
// - S3 bucket auto-created with encryption
()
}
}
Production CloudTrail
Production-ready configuration with custom retention and monitoring.
stack "ProductionCloudTrail" {
cloudTrail "ProductionAudit" {
// Multi-region and global events (defaults)
isMultiRegionTrail true
includeGlobalServiceEvents true
// Log integrity validation (detect tampering)
enableFileValidation true
// CloudWatch Logs for real-time monitoring
sendToCloudWatchLogs true
cloudWatchLogsRetention RetentionDays.THREE_MONTHS
// Log all management events (default)
managementEvents ReadWriteType.ALL
}
}
Organization Trail
For AWS Organizations, create an organization-wide trail that logs events for all accounts.
stack "OrganizationCloudTrail" {
cloudTrail "OrgSecurityAudit" {
isOrganizationTrail true
isMultiRegionTrail true
includeGlobalServiceEvents true
enableFileValidation true
cloudWatchLogsRetention RetentionDays.SIX_MONTHS
}
}
Custom S3 Bucket
Use a custom S3 bucket for CloudTrail logs (with lifecycle rules for cost optimization).
stack "CustomBucketCloudTrail" {
// Create custom S3 bucket with lifecycle rules
let! trailBucket =
s3Bucket "CloudTrailLogs" {
versioned true // Enable versioning for audit trail integrity
lifecycleRule {
transitions
[ transition {
storageClass Amazon.CDK.AWS.S3.StorageClass.GLACIER
transitionAfter (Duration.Days(90.0))
}
transition {
storageClass Amazon.CDK.AWS.S3.StorageClass.DEEP_ARCHIVE
transitionAfter (Duration.Days(365.0))
} ]
}
}
cloudTrail "CustomBucketAudit" {
s3Bucket trailBucket
isMultiRegionTrail true
includeGlobalServiceEvents true
}
}
Compliance Trail (Long Retention)
For compliance requirements (HIPAA, PCI-DSS, SOC2), use longer retention periods.
stack "ComplianceCloudTrail" {
cloudTrail "ComplianceAudit" {
isMultiRegionTrail true
includeGlobalServiceEvents true
enableFileValidation true
// Extended retention for compliance
cloudWatchLogsRetention RetentionDays.ONE_YEAR
// All management events
managementEvents ReadWriteType.ALL
}
}
Read-Only Trail (Cost Optimization)
For read-only monitoring, log only read operations (reduces volume and cost).
stack "ReadOnlyCloudTrail" {
cloudTrail "ReadOnlyAudit" {
isMultiRegionTrail true
includeGlobalServiceEvents true
// Only log read operations
managementEvents ReadWriteType.READ_ONLY
// Shorter retention for cost savings
cloudWatchLogsRetention RetentionDays.ONE_WEEK
}
}
Write-Only Trail (Security Focus)
For security monitoring, focus on write operations (changes to infrastructure).
stack "SecurityFocusCloudTrail" {
cloudTrail "SecurityMonitoring" {
isMultiRegionTrail true
includeGlobalServiceEvents true
enableFileValidation true
// Only log write/delete operations
managementEvents ReadWriteType.WRITE_ONLY
cloudWatchLogsRetention RetentionDays.ONE_MONTH
}
}
Single Region Trail (Cost Optimization)
For single-region applications, save costs with a single-region trail.
stack "SingleRegionCloudTrail" {
cloudTrail "RegionalAudit" {
// Single region only (cost optimization)
isMultiRegionTrail false
// Still include global service events
includeGlobalServiceEvents true
enableFileValidation true
cloudWatchLogsRetention RetentionDays.TWO_WEEKS
}
}
Disabling CloudWatch Logs (S3 Only)
For cost-conscious deployments, disable CloudWatch Logs and use S3 only.
stack "S3OnlyCloudTrail" {
cloudTrail "S3OnlyAudit" {
isMultiRegionTrail true
includeGlobalServiceEvents true
enableFileValidation true
// Disable CloudWatch Logs (S3 only)
sendToCloudWatchLogs false
}
}
Best Practices
Security
- ✅ Always enable multi-region trails - Capture events from all regions
- ✅ Include global service events - Monitor IAM, STS, CloudFront changes
- ✅ Enable log file validation - Detect if logs have been tampered with
- ✅ Use CloudWatch Logs - Enable real-time monitoring and alerting
- ✅ Enable for all accounts - Use organization trails for centralized logging
- ✅ Monitor CloudTrail health - Set up CloudWatch alarms for delivery failures
- ✅ Restrict S3 bucket access - Only CloudTrail service should write logs
Compliance
CloudTrail is required for most compliance frameworks:
- HIPAA - Audit trail of all access to ePHI
- PCI-DSS - Requirement 10.2 - Audit trail for all system components
- SOC2 - CC7.2 - Monitoring of system components
- GDPR - Article 32 - Security of processing (audit logs)
- FedRAMP - AU-2 - Audit Events
- ISO 27001 - A.12.4.1 - Event logging
Cost Optimization
- First trail is FREE - Management events in primary region
- Additional trails - $2.00 per 100,000 events
- CloudWatch Logs - $0.50 per GB ingested (optional)
- S3 storage - Standard S3 rates
- Data events - $0.10 per 100,000 events (S3, Lambda)
Cost Reduction Strategies: 1. Use read-only or write-only trails if appropriate 2. Disable CloudWatch Logs for low-priority environments 3. Use S3 lifecycle policies to transition to Glacier 4. Use single-region trails for region-specific applications 5. Filter out high-volume, low-value events
Monitoring & Alerting
Set up CloudWatch alarms for:
- Failed log delivery - Alert if CloudTrail can't write logs
- Log file validation failures - Alert if log integrity is compromised
- Unauthorized API calls - Alert on suspicious activity
- IAM policy changes - Alert on privilege escalation attempts
- Security group changes - Alert on network exposure changes
- Root account usage - Alert on root account API calls
Incident Investigation
CloudTrail is essential for security incident response:
- Who - Identity of the caller (IAM user, role, federated user)
- What - The action that was attempted
- When - Date and time of the request
- Where - Source IP address and region
- Why - Event outcome (success or failure)
Data Events (Advanced)
For S3 and Lambda, you can enable data event logging (additional cost):
// Note: Data events require additional configuration
// and are not included in the free tier
Default Settings
FsCDK CloudTrail applies these security best practices by default:
- Multi-Region Trail: ✅ true (captures all regions)
- Global Service Events: ✅ true (IAM, STS, CloudFront, etc.)
- Log File Validation: ✅ true (integrity checking)
- Management Events: ✅ ReadWriteType.ALL (all API calls)
- CloudWatch Logs: ✅ true (real-time monitoring)
- CloudWatch Retention: 📅 ONE_MONTH (balance cost/security)
- S3 Bucket: 🪣 Auto-created with encryption
- Organization Trail: ❌ false (opt-in for AWS Organizations)
What is Logged?
Management Events (Always Logged)
- IAM user/role creation, deletion, policy changes
- EC2 instance start/stop/terminate
- VPC creation, security group changes
- S3 bucket creation, policy changes
- Lambda function creation, updates
- RDS instance creation, configuration changes
- CloudFormation stack operations
- And thousands of other AWS API calls
Global Service Events
- IAM - User, role, policy changes
- AWS STS - Temporary credential requests
- CloudFront - Distribution changes
- Route53 - DNS changes (global operations)
- AWS Organizations - Account management
NOT Logged by Default
- S3 object-level operations (GET, PUT, DELETE) - Requires data events
- Lambda invocations - Requires data events
- DynamoDB operations - Requires data events
- CloudWatch Logs data - Not logged
- Service-specific logs (RDS query logs, VPC Flow Logs, etc.)
Log Format Example
|
Integration with Other Services
CloudWatch Logs Insights
Query CloudTrail logs using CloudWatch Logs Insights:
|
AWS Config
CloudTrail + AWS Config = Complete compliance solution: - CloudTrail - Who did what, when - AWS Config - Current and historical configuration state
Amazon Athena
Query CloudTrail logs in S3 using SQL:
|
AWS Security Hub
CloudTrail findings are automatically sent to Security Hub for centralized security management.
Resources
- AWS CloudTrail Documentation
- CloudTrail Best Practices
- CloudTrail Log File Validation
- CloudTrail Pricing
- Analyzing CloudTrail Logs with Athena
Summary
CloudTrail is non-negotiable for: - ✅ Security incident investigation - ✅ Compliance requirements - ✅ Operational troubleshooting - ✅ Detecting unauthorized access - ✅ Audit trails for regulated industries
FsCDK makes it easy with secure-by-default settings. Simply add cloudTrail "name" { } to your stack!
<summary>Creates an AWS CDK Stack construct.</summary>
<param name="name">The name of the stack.</param>
<code lang="fsharp"> stack "MyStack" { lambda myFunction bucket myBucket } </code>
<summary> Creates a CloudTrail configuration with AWS security best practices. CloudTrail logs all AWS API calls for security monitoring and compliance. </summary>
<param name="name">The trail name.</param>
<code lang="fsharp"> cloudTrail "SecurityAuditTrail" { isMultiRegionTrail true includeGlobalServiceEvents true enableFileValidation true } </code>
<summary> Sets whether this is a multi-region trail. **Security Best Practice:** Multi-region trails are enabled by default to capture events from all AWS regions. </summary>
<param name="config">The current CloudTrail configuration.</param>
<param name="enabled">Whether to enable multi-region (default: true).</param>
<code lang="fsharp"> cloudTrail "MyTrail" { isMultiRegionTrail false // Only if single-region monitoring is acceptable } </code>
<summary> Sets whether to include global service events (IAM, STS, CloudFront, etc.). **Security Best Practice:** Enabled by default to capture critical security events. </summary>
<param name="config">The current CloudTrail configuration.</param>
<param name="enabled">Whether to include global events (default: true).</param>
<summary> Sets whether to enable log file validation. **Security Best Practice:** Enabled by default for log integrity verification. This allows you to detect if log files were tampered with after delivery. </summary>
<param name="config">The current CloudTrail configuration.</param>
<param name="enabled">Whether to enable validation (default: true).</param>
<summary> Sets whether to send trail logs to CloudWatch Logs. **Note:** CloudWatch Logs integration enables real-time monitoring but adds cost. </summary>
<param name="config">The current CloudTrail configuration.</param>
<param name="enabled">Whether to send to CloudWatch (default: true).</param>
<summary> Sets the CloudWatch Logs retention period for the trail. </summary>
<param name="config">The current CloudTrail configuration.</param>
<param name="retention">The retention period (default: ONE_MONTH).</param>
<code lang="fsharp"> cloudTrail "MyTrail" { cloudWatchLogsRetention RetentionDays.THREE_MONTHS } </code>
<summary> Sets the management event logging type. </summary>
<param name="config">The current CloudTrail configuration.</param>
<param name="readWriteType">The type of events to log (default: ReadWriteType.ALL).</param>
<code lang="fsharp"> cloudTrail "MyTrail" { managementEvents ReadWriteType.WRITE_ONLY // Only log write events } </code>
<summary> Sets whether this is an organization trail (requires AWS Organizations). Organization trails log events for all accounts in the organization. </summary>
<param name="config">The current CloudTrail configuration.</param>
<param name="enabled">Whether this is an organization trail.</param>
<code lang="fsharp"> cloudTrail "OrgTrail" { isOrganizationTrail true } </code>
<summary> Creates a new S3 bucket builder with secure defaults. Example: s3Bucket "my-bucket" { versioned true } Alias for bucket builder. </summary>
<summary> Enables or disables versioning for the S3 bucket. **Security Best Practice:** Enable versioning for: - Critical data that requires audit trails - Data subject to compliance requirements (HIPAA, SOC2, etc.) - Production buckets storing business data **Cost Consideration:** Versioning stores all versions of objects, increasing storage costs. Only disable for: - Temporary/cache buckets - Build artifacts with short lifecycle - Development/testing buckets **Default:** false (opt-in for cost optimization) </summary>
<param name="value">True to enable versioning, false to disable.</param>
<param name="config">The current bucket configuration.</param>
<code lang="fsharp"> bucket "production-data" { versioned true // Enable for production } bucket "cache-bucket" { versioned false // Disable for temp data } </code>
<summary> Creates an S3 lifecycle transition rule for moving objects to different storage classes. Transitions reduce storage costs by automatically moving objects to cheaper storage tiers. </summary>
<code lang="fsharp"> transition { storageClass StorageClass.GLACIER transitionAfter (Duration.Days(90.0)) } </code>
<summary> Sets the storage class to transition to. Common classes: GLACIER (low-cost archival), DEEP_ARCHIVE (lowest cost, rare access), INTELLIGENT_TIERING (automatic cost optimization), GLACIER_IR (instant retrieval). </summary>
<param name="storageClass">The target storage class.</param>
type StorageClass = inherit DeputyBase new: value: string -> unit member ToString: unit -> string member Value: string static member DEEP_ARCHIVE: StorageClass static member GLACIER: StorageClass static member GLACIER_INSTANT_RETRIEVAL: StorageClass static member INFREQUENT_ACCESS: StorageClass static member INTELLIGENT_TIERING: StorageClass static member ONE_ZONE_INFREQUENT_ACCESS: StorageClass
--------------------
AWS.S3.StorageClass(value: string) : AWS.S3.StorageClass
<summary> Sets when objects transition after creation (use Duration.Days()). Example: transitionAfter (Duration.Days(90.0)) moves objects after 90 days. </summary>
<param name="duration">Time after object creation to transition.</param>
<summary> Sets a custom S3 bucket for CloudTrail logs. If not specified, CDK will create a bucket with appropriate security settings. </summary>
<param name="config">The current CloudTrail configuration.</param>
<param name="bucket">The S3 bucket interface.</param>
FsCDK