skip to content

How do you encrypt an Amazon CloudWatch Logs log group with a customer managed KMS key, and what must that key's policy contain for it to work?

level: middleimportance: nice to knowfreq 26%

answer

  1. it is already encrypted by default
  2. the key policy, not your IAM policy
  3. a regional service principal calls KMS
  4. encryption context scopes the grant
  5. disable the key, lose the log group

basics

~20 s

Associate a symmetric KMS key with the log group at creation or with AssociateKmsKey. The key policy must let the logs.<region>.amazonaws.com service principal use the key, normally scoped by a condition on the kms:EncryptionContext:aws:logs:arn context key.

solid answer

~40 s

Log data is already encrypted at rest by default with an AWS-owned key; a customer managed key is about control and auditability, not about turning encryption on. You associate one per log group — `CreateLogGroup --kms-key-id`, or `AssociateKmsKey` on an existing group — and it must be a **symmetric** key, since asymmetric keys are not supported. The part people get wrong is the key policy: CloudWatch Logs calls KMS as the service principal `logs.<region>.amazonaws.com`, so that principal needs `kms:Encrypt*`, `kms:Decrypt*`, `kms:ReEncrypt*`, `kms:GenerateDataKey*` and `kms:Describe*`. Best practice scopes it with an `ArnLike` condition on `kms:EncryptionContext:aws:logs:arn` so the key can only be used for your log groups. Without that grant the association call itself fails. And if the key is later disabled or scheduled for deletion, the group's data becomes unreadable and ingestion breaks.

code

json · 23 lines
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudWatchLogs",
      "Effect": "Allow",
      "Principal": { "Service": "logs.us-east-1.amazonaws.com" },
      "Action": [
        "kms:Encrypt*",
        "kms:Decrypt*",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:Describe*"
      ],
      "Resource": "*",
      "Condition": {
        "ArnLike": {
          "kms:EncryptionContext:aws:logs:arn": "arn:aws:logs:us-east-1:111122223333:log-group:*"
        }
      }
    }
  ]
}

go deeper

for a junior

Know that CloudWatch Logs data is encrypted at rest by default, and that using your own KMS key is an optional per-log-group association made at creation or with AssociateKmsKey.

for a middle

Explain that CloudWatch Logs calls KMS as the logs.<region>.amazonaws.com service principal, so the key policy — not the caller's IAM policy — must grant the encrypt and decrypt actions, and that only symmetric keys work.

for a senior

Show the operational angle: scope the grant with the aws:logs:arn encryption-context condition, treat the key as a production dependency because disabling it blocks both reads and ingestion, and guard against accidental scheduled deletion.

for a principal

Own the key strategy across the estate — which log groups genuinely need customer managed keys, who administers those keys versus who uses them, how rotation and revocation are exercised, and the cost and blast radius of one shared key backing many log groups.

## Start from what is already true CloudWatch Logs encrypts stored log data at rest by default, using an AWS-owned key you never see. So a customer managed key (CMK) does not add encryption where there was none — it changes **who controls the key**. What you gain is: an auditable key policy you own, CloudTrail records of every KMS use, independent rotation, and the ability to revoke access to the data by disabling the key. Those are compliance properties, and that is the honest reason to do it. ## Associating the key The association is per log group, at creation or afterwards: ```bash aws logs create-log-group \ --log-group-name /myapp/api \ --kms-key-id arn:aws:kms:us-east-1:111122223333:key/1234abcd-... # or on an existing group aws logs associate-kms-key \ --log-group-name /myapp/api \ --kms-key-id arn:aws:kms:us-east-1:111122223333:key/1234abcd-... ``` `DisassociateKmsKey` removes it. Two constraints: the key must be **symmetric** — asymmetric KMS keys are not supported — and it must be in the **same region** as the log group, because KMS keys are regional. ## The key policy is the whole exam question When CloudWatch Logs encrypts and decrypts your data, it calls KMS **as a service**, using the regional service principal `logs.<region>.amazonaws.com`. Your own IAM permissions are irrelevant to that call. So the key's resource policy must allow that principal: ```json { "Effect": "Allow", "Principal": { "Service": "logs.us-east-1.amazonaws.com" }, "Action": [ "kms:Encrypt*", "kms:Decrypt*", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:Describe*" ], "Resource": "*", "Condition": { "ArnLike": { "kms:EncryptionContext:aws:logs:arn": "arn:aws:logs:us-east-1:111122223333:log-group:*" } } } ``` Two details worth calling out in an interview: - `"Resource": "*"` inside a key policy means *this key*, not every key. Key policies are attached to one key; the wildcard is idiomatic, not a wildcard grant across KMS. - The **encryption context** condition is the security control that matters. CloudWatch Logs supplies `aws:logs:arn` as encryption context on every call, and the `ArnLike` condition confines the key's usability to log groups in your account. Grant the service principal unconditionally and any log group anywhere that knows the key ARN could, in principle, be pointed at it. Scoping the condition down to a specific group ARN rather than a wildcard is tighter still. If the grant is missing, the association fails immediately with an access-denied style error — a useful property, because the misconfiguration surfaces at configure time rather than silently later. ## Lifecycle traps **Disabling or deleting the key breaks the log group.** Existing data cannot be decrypted, so reads fail, and ingestion into the group stops working. KMS's mandatory waiting period before key deletion is your safety net, but a key disabled during an unrelated incident takes the log group down with it — which is exactly when you wanted the logs. Treat a key backing log groups as a production dependency: alarm on scheduled deletion and keep its policy under change control. **Rotation is transparent.** With automatic key rotation, KMS keeps prior key material so older data stays readable; the key ARN never changes, so nothing in CloudWatch Logs needs updating. **Association is not retroactive in an operational sense.** Associating a key encrypts subsequent data under it; disassociating stops using it for new data but does not rewrite what is already stored, so the key remains a dependency for reading history. **Cost.** Every encrypt/decrypt is a KMS API request with a charge, plus the monthly key fee. Immaterial for most log groups, worth knowing about for very high-volume ones. ## Where this sits The common interview version of this question is a scenario: "we created the key and the association call is denied." The answer is always the key policy and the `logs.<region>.amazonaws.com` service principal, not the caller's IAM permissions — the caller needs `logs:AssociateKmsKey` and typically `kms:DescribeKey`, but the encryption itself is done by the service on its own behalf.

  • If CloudWatch Logs already encrypts data at rest, why bother with a customer managed key?
    For control and evidence, not for encryption itself. A customer managed key gives you a policy you own, CloudTrail entries for every use, your own rotation schedule, and the ability to revoke access to the data by disabling the key. Those are compliance requirements. If none of them apply, the default AWS-owned key is simpler and free.
  • An operator disables the KMS key that a log group uses. What breaks?
    Both directions. Existing log data can no longer be decrypted, so reads fail, and ingestion into that group stops working because the service cannot encrypt new events. The failure typically surfaces during an incident, when the logs are most needed, which is why a key backing log groups should be treated as a production dependency under change control.
  • Why does the key policy use a condition on kms:EncryptionContext:aws:logs:arn?
    To confine the grant. CloudWatch Logs passes the log group's ARN as encryption context on every KMS call, so an ArnLike condition on that context key means the service principal may use the key only for log groups matching that ARN pattern. Without it you have granted an AWS service broad use of your key rather than use for your specific resources.

saying these in an interview costs you the question

  • Thinking CloudWatch Logs is unencrypted without a customer managed key
  • Granting the caller IAM permissions instead of fixing the key policy
  • Trying to use an asymmetric KMS key for a log group
  • Reading "Resource": "*" in a key policy as access to all KMS keys
  • Assuming a disabled key only blocks new writes, not reads

context