CloudTrail trails should have logs encrypted using a customer managed KMS key
CloudTrail logs record every API call in your AWS account, including authentication events, resource changes, and privilege escalations. Default SSE-S3 encryption means anyone with S3 bucket access can read those logs. A KMS CMK adds an independent authorization layer: even if an attacker gains S3 read access, they still need kms:Decrypt permission on the specific key to read log contents.
CMK encryption also gives you key rotation control, the ability to revoke access instantly by disabling the key, and a CloudTrail event on every decrypt operation against your audit logs. That last point matters: accessing the logs themselves leaves an auditable trace.
Retrofit consideration
Changing encryption on an existing trail requires the KMS key policy to grant the CloudTrail service principal cloudtrail.amazonaws.com the kms:GenerateDataKey* and kms:DescribeKey actions. Existing log files stay encrypted with their original method; only new log deliveries use the CMK.
Implementation
Choose the approach that matches how you manage Terraform.
Use AWS provider resources directly. See docs for the resources involved: aws_cloudtrail.
resource "aws_cloudtrail" "this" {
advanced_event_selector {
field_selector {
equals = ["Data"]
field = "eventCategory"
}
field_selector {
equals = ["AWS::S3::Object"]
field = "resources.type"
}
name = "Log all S3 data events"
}
cloud_watch_logs_group_arn = local.cloudtrail_log_group_arn
cloud_watch_logs_role_arn = "arn:aws:iam::123456789012:role/example-role"
name = "pofix-abc123"
s3_bucket_name = "example-bucket-abc123"
kms_key_id = "arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012"
}
What this control checks
The aws_cloudtrail resource must have kms_key_id set to a CMK ARN. When kms_key_id is omitted or empty, the trail falls back to default SSE-S3 encryption and the control fails. The referenced KMS key must have a key policy granting cloudtrail.amazonaws.com the required permissions. A typical passing configuration sets kms_key_id = aws_kms_key.cloudtrail.arn on the aws_cloudtrail resource. AWS-managed keys (alias aws/s3) do not satisfy this control because the requirement is specifically for a customer-managed key where you control the key policy and rotation schedule.
Common pitfalls
KMS key policy missing CloudTrail permissions
The KMS key policy must explicitly allow
cloudtrail.amazonaws.comto callkms:GenerateDataKey*andkms:DescribeKey. Without these statements, CloudTrail cannot encrypt logs and log delivery silently fails. Theaws_kms_keyresource'spolicyargument must include this service principal grant.Multi-region trails need key in each region
KMS keys are regional. A multi-region trail (
is_multi_region_trail = true) uses the CMK from the trail's home region, but if you consolidate logs into a central S3 bucket in a different region, cross-region KMS permissions and S3 bucket policies must align. Mismatched regions cause delivery failures with no obvious error.Using AWS-managed key instead of CMK
Pointing
kms_key_idat an AWS-managed key (for example, theaws/s3alias) won't pass this control. You need a customer-managed key where you own the key policy, control rotation, and can disable or revoke access independently of AWS.Key deletion orphans log access
Schedule a KMS key for deletion and every CloudTrail log encrypted with it becomes permanently unreadable once the waiting period expires. There is no recovery path. Monitor the referenced key using the related
kms_key_not_pending_deletioncontrol.
Audit evidence
Auditors check the CloudTrail console or aws cloudtrail describe-trails output for the KmsKeyId field populated with a CMK ARN on every trail. Confirm the key is active (not disabled or pending deletion) via aws kms describe-key. The Config rule cloud-trail-encryption-enabled provides continuous compliance evidence.
Supporting artifacts include the KMS key policy document showing cloudtrail.amazonaws.com service principal grants, and CloudTrail event history showing Encrypt and GenerateDataKey calls against the CMK, confirming encryption is being applied to new log deliveries.
Framework-specific interpretation
SOC 2: The Confidentiality and Security trust service criteria both expect layered access controls on sensitive operational data. Encrypting audit logs with a CMK means S3-layer access is not sufficient to read log contents, which is what examiners check when evaluating logical access controls over audit records.
PCI DSS v4.0: Requirement 10.3.1 calls for protecting audit log integrity from unauthorized modification, and CMK encryption puts cryptographic access control in front of those logs. Requirement 3.5 also applies: the CMK needs documented rotation and access control processes to satisfy key management requirements.
HIPAA Omnibus Rule 2013: API call metadata, user identifiers, and resource names in CloudTrail logs can carry ePHI references, making those logs PHI-adjacent data subject to the Security Rule's encryption addressable specification. CMK encryption satisfies that specification and gives covered entities direct control over key access, including the ability to revoke decryption rights without touching S3 bucket policies.
GDPR: Article 32 requires appropriate technical measures for security of processing. CloudTrail logs can carry personal data identifiers in API call parameters, and CMK encryption protects those records at rest while giving the data controller the ability to revoke decryption access independently of S3 permissions.
NIST SP 800-53 Rev 5: SC-28 (Protection of Information at Rest) and AU-9 (Protection of Audit Information) both apply. CMK encryption means log contents require explicit kms:Decrypt authorization, which S3 bucket access alone does not provide. That separation between storage access and decryption authorization is exactly what AU-9 is asking for.
NIST Cybersecurity Framework v2.0: KMS decrypt events on CloudTrail logs create a secondary detection signal that feeds directly into DE.AE anomaly detection for anything touching audit trail data. The encryption itself covers the PR.DS data-at-rest requirement. Two framework boxes, one control.
FedRAMP Moderate Baseline Rev 4: At the Moderate baseline, SC-28 requires FIPS 140-validated encryption for data at rest. AWS KMS uses FIPS 140-validated cryptographic modules, so a CMK-encrypted trail satisfies that requirement directly. This is the standard approach for FedRAMP-authorized environments.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
cloudtrail_trail_logs_encrypted_with_kms_cmkAWS Config Managed Rule:
CLOUD_TRAIL_ENCRYPTION_ENABLEDCheckov Check:
CKV_AWS_35Powerpipe Control:
aws_compliance.control.cloudtrail_trail_logs_encrypted_with_kms_cmkProwler Check:
cloudtrail_kms_encryption_enabledAWS Security Hub Control:
CloudTrail.2KICS Query:
5d9e3164-9265-470c-9a10-57ae454ac0c7Trivy Check:
AWS-0015
Last reviewed: 2026-03-09