Skip to content

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.com to call kms:GenerateDataKey* and kms:DescribeKey. Without these statements, CloudTrail cannot encrypt logs and log delivery silently fails. The aws_kms_key resource's policy argument 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_id at an AWS-managed key (for example, the aws/s3 alias) 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_deletion control.

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.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: cloudtrail_trail_logs_encrypted_with_kms_cmk

  • AWS Config Managed Rule: CLOUD_TRAIL_ENCRYPTION_ENABLED

  • Checkov Check: CKV_AWS_35

  • Powerpipe Control: aws_compliance.control.cloudtrail_trail_logs_encrypted_with_kms_cmk

  • Prowler Check: cloudtrail_kms_encryption_enabled

  • AWS Security Hub Control: CloudTrail.2

  • KICS Query: 5d9e3164-9265-470c-9a10-57ae454ac0c7

  • Trivy Check: AWS-0015

Last reviewed: 2026-03-09