CloudWatch Logsのログデータを暗号化する

はじめに

AWS Key Management Service (AWS KMS) カスタマーマスターキー (CMK) を使用して CloudWatch Logs でログデータを暗号化する方法を紹介します。

ポイント

  • AWS KMS CMKを利用したサーバーサイド暗号
  • CloudWatch LogsにCMKの暗号・復号を許可
  • CMKの許可を取りやめたり、CMKを削除すると、CloudWatch Logs 内の暗号化されたデータを取得できなくなる
  • ロググループレベルで暗号化
  • 暗号化は解除可能。解除後も、暗号化して取り込んだログは暗号化されたまま
  • コンソールからは暗号化出来ない。SDK/CLIを利用

AWS KMS CKMの作成

AWSマネージドキーではCloudWatch Logsを暗号化できません。

CMKを作成し、CloudWatch Logsがその鍵で暗号・復号できるように許可します。

  • 新規鍵を作成
  • 既存の作成済み鍵を更新

の2パターンで手順を確認します。

ポリシー

AWS KMSの運用では

  • 鍵の管理者
  • 鍵の利用者

の2種類のポリシーが必要です。

CW Logsの暗号化では鍵の利用者向けポリシーが該当します。

このポリシーの Principal に "Service": "logs.AWS-REGION.amazonaws.com" を追加します。リージョンを含める必要がある点に注意ください。

以下のサンプルポリシーでは

  • 鍵の管理者
    • IAM ユーザー arn:aws:iam::123456789012:user/kms-admin
  • 鍵の利用者
    • IAMユーザー arn:aws:iam::123456789012:user/kms-user
    • CloudWatch Logs "Service": "logs.ap-northeast-1.amazonaws.com"

となっています。

{
  "Version": "2012-10-17",
  "Id": "clouwatch-logs-kms-policy",
  "Statement": [
    {
      "Sid": "Enable IAM User Permissions",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:root"
      },
      "Action": "kms:*",
      "Resource": "*"
    },
    {
      "Sid": "Allow access for Key Administrators",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:user/kms-admin"
      },
      "Action": [
        "kms:Create*",
        "kms:Describe*",
        "kms:Enable*",
        "kms:List*",
        "kms:Put*",
        "kms:Update*",
        "kms:Revoke*",
        "kms:Disable*",
        "kms:Get*",
        "kms:Delete*",
        "kms:TagResource",
        "kms:UntagResource",
        "kms:ScheduleKeyDeletion",
        "kms:CancelKeyDeletion"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Allow use of the key",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::123456789012:user/kms-user"
        ],
        "Service": "logs.ap-northeast-1.amazonaws.com"
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "*"
    },
    {
      "Sid": "Allow attachment of persistent resources",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::123456789012:user/kms-user"
        ]
      },
      "Action": [
        "kms:CreateGrant",
        "kms:ListGrants",
        "kms:RevokeGrant"
      ],
      "Resource": "*",
      "Condition": {
        "Bool": {
          "kms:GrantIsForAWSResource": "true"
        }
      }
    }
  ]
}

AWS KMS CMKの作成

管理コンソールから作成する場合、鍵を作成後、ポリシーの Principal を修正してください。

AWS CLI経由で作成する場合、以下の様になります。

# 鍵の作成
$ aws kms create-key \
  --description 'kms key for CW Logs' \
  --policy file://policy.json  # 先程作成したポリシー
{
    "KeyMetadata": {
        "AWSAccountId": "123456789012",
        "KeyId": "f1221273-b490-4492-991a-fb2a23b8e62a",
        "Arn": "arn:aws:kms:eu-central-1:123456789012:key/f1221273-b490-4492-991a-fb2a23b8e62a",
        "CreationDate": 1545239736.178,
        "Enabled": true,
        "Description": "kms key for CW Logs",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER"
    }
}

# エイリアスの設定
$ aws kms create-alias \
  --alias-name alias/cmk-for-cwlogs \
  --target-key-id arn:aws:kms:eu-central-1:123456789012:key/f1221273-b490-4492-991a-fb2a23b8e62a

# CMKの確認
$ aws kms describe-key --key-id f1221273-b490-4492-991a-fb2a23b8e62a
{
    "KeyMetadata": {
        "AWSAccountId": "123456789012",
        "KeyId": "f1221273-b490-4492-991a-fb2a23b8e62a",
        "Arn": "arn:aws:kms:eu-central-1:123456789012:key/f1221273-b490-4492-991a-fb2a23b8e62a",
        "CreationDate": 1545239736.178,
        "Enabled": true,
        "Description": "kms key for CW Logs",
        "KeyUsage": "ENCRYPT_DECRYPT",
        "KeyState": "Enabled",
        "Origin": "AWS_KMS",
        "KeyManager": "CUSTOMER"
    }
}

CloudWatch Logsの暗号化

作成したAWS KMS CMKを利用してCloudWatch Logsを暗号化します。

この操作は管理コンソールからは行えません。AWS CLI/SDK から行います。

暗号化された新規ロググループを作成する場合

logs:create-log-group API を利用して、ロググループの作成とCMKの関連付けを同時に行います。

引数で

  • ロググループ名
  • CMKのARN

を指定します。

$ aws logs create-log-group \
  --log-group-name foo \
  --kms-key-id arn:aws:kms:eu-central-1:123456789012:key/f1221273-b490-4492-991a-fb2a23b8e62a

既存のロググループを暗号化する場合

logs:associate-kms-key API を利用してロググループとCMKの関連付けを行います。

引数で

  • ロググループ名
  • CMKのARN

を指定します。

$ aws logs associate-kms-key \
  --log-group-name bar \
  --kms-key-id arn:aws:kms:eu-central-1:123456789012:key/f1221273-b490-4492-991a-fb2a23b8e62a

ロググループの設定を確認

$ aws logs describe-log-groups --log-group-name-prefix bar
{
    "logGroups": [
        {
            "logGroupName": "bar",
            "creationTime": 1545258975724,
            "metricFilterCount": 0,
            "arn": "arn:aws:logs:eu-central-1:123456789012:log-group:bar:*",
            "storedBytes": 0,
            "kmsKeyId": "arn:aws:kms:eu-central-1:123456789012:key/f1221273-b490-4492-991a-fb2a23b8e62a"
        }
    ]
}

ロググループに kmsKeyId が設定されているのがわかります。

暗号を無効化する

logs:disassociate-kms-key API を利用します。

引数で

  • ロググループ名

を指定します。

$ aws logs disassociate-kms-key \
  --log-group-name foo
$ aws logs describe-log-groups --log-group-name-prefix foo
{
    "logGroups": [
        {
            "logGroupName": "foo",
            "creationTime": 1545258975724,
            "metricFilterCount": 0,
            "arn": "arn:aws:logs:eu-central-1:123456789012:log-group:foo:*",
            "storedBytes": 0
        }
    ]
}

ロググループから kmsKeyId の設定が消えています。

CMKと過去の暗号済みデータとの関係を確認

CloudWatch Logsに関連付けられたCMKへアクセスできなくなると、CloudWatch Logs 内の暗号化されたデータを取得できなくなります。

具体的には、以下の様なケースが考えられます。

  • CMKのポリシーが変更され、CloudWatch LogsがCMKを利用できなくなった
  • CMKが削除された

一方で、CloudWatch LogsとCMKの関連付けが解除されても、CloudWatch Logsが暗号に利用したCMKにアクセスできる限りは、復号可能です。

この動作を確認してみましょう。

CloudWatch LogsとCMKの関係を解除してログにアクセス

関連付けを解除しただけでは、CMKを利用して暗号化したログにもアクセス可能です。

# 関連付けを解除
$ aws logs disassociate-kms-key \
  --log-group-name foo
# CW Logsにアクセス
$ aws logs get-log-events \
  --log-group-name test \
  --log-stream-name xxx
{
    "events": [
        {
            "timestamp": 1545240920366,
            "message": "...",
            "ingestionTime": 1545240920412
        }
    ],
    "nextForwardToken": "f/34460024035425115495930233232501593720702418250723426304",
    "nextBackwardToken": "b/34460024035425115495930233232501593720702418250723426304"
}

CMKのポリシーを変更

CMK利用者の Principal から CloudWatch Logs("Service": "logs.AWS-REGION.amazonaws.com") を除外します。

    ...
    {
      "Sid": "Allow use of the key",
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::123456789012:user/kms-user"
        ]
      },
      "Action": [
        "kms:Encrypt",
        "kms:Decrypt",
        "kms:ReEncrypt*",
        "kms:GenerateDataKey*",
        "kms:DescribeKey"
      ],
      "Resource": "*"
    },
    ...

管理コンソールからイベントログを確認

この状態で暗号化したイベントログが含まれる CloudWatch Logsを確認します。

ログの代わりにエラーメッセージが表示されています。

CLI からイベントログを確認

$ aws logs get-log-events \
  --log-group-name test \
  --log-stream-name xxx

An error occurred (InvalidParameterException) when calling the GetLogEvents operation: Unable to validate if specified KMS key is valid.

エラーが発生します。

参考