猫キック

IT関連について投稿

【AWS】SSE-KMS カスタマーマスターキー(CMK)によって暗号化されたS3バケットのクロスリージョンレプリケーション

最近はまっていることは、Condition属性の中身をカオスにすることです。

タイトルの通りCMKによって暗号化されたS3バケットクロスリージョンレプリケーションを実施しました。 なるべく最小の権限且つ、CMKの利用を明示して指定する方法を調べたのでハマったことも踏まえて記載。 (むしろハマったことが本題のような気も。。)

構成

CMKでのクロスリージョンレプリケーション(ap-northeast-1 -> ap-northeast-3)を想定。

Setting

1. KMSキーを作成

  • ap-northeast-1上で、crr-tokyo
  • ap-northeast-3上で、crr-osaka

2. S3バケットを作成

  • ap-northeast-1上で、demo-tokyo-crr-01。バージョニングを有効(レプリケーションを実施する上で必須)
  • ap-northeast-3上で、demo-osaka-crr-01。バージョニングを有効

3. IAMロールを作成

  • 信頼エンティティをs3に指定。
  • 送信元のKMSキーで復号化し、送信先のKMSキーを利用してレプリケーションするポリシーを作成してIAMロールにアタッチ。
  • ポリシーは以下の通り。条件キーでKeyAliasとKeyIDをあえて別々で設定しているので実際に利用するならKeyIDで統一するように。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "GetObjectFromSrcBucket",
      "Action": [
        "s3:ListBucket",
        "s3:GetReplicationConfiguration",
        "s3:GetObjectVersionTagging",
        "s3:GetObjectVersionForReplication",
        "s3:GetObjectVersionAcl"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::demo-tokyo-crr-01",
        "arn:aws:s3:::demo-tokyo-crr-01/*"
      ]
    },
    {
      "Sid": "ReplicateToDestBucket",
      "Action": [
        "s3:ReplicateObject",
        "s3:ReplicateDelete",
        "s3:ReplicateTags"
      ],
      "Effect": "Allow",
      "Condition": {
        "StringLikeIfExists": {
          "s3:x-amz-server-side-encryption": [
            "aws:kms",
            "AES256"
          ],
          "s3:x-amz-server-side-encryption-aws-kms-key-id": [
            "arn:aws:kms:ap-northeast-3:${account_id}:key/[大阪のキーID]"
          ]
        }
      },
      "Resource": "arn:aws:s3:::demo-osaka-crr-01/*"
    },
    {
      "Sid": "DecryptSrcRegionKMSKey",
      "Action": [
        "kms:Decrypt"
      ],
      "Effect": "Allow",
      "Condition": {
        "StringLike": {
          "kms:ViaService": "s3.ap-northeast-1.amazonaws.com",
          "kms:EncryptionContext:aws:s3:arn": [
            "arn:aws:s3:::demo-tokyo-crr-01/*"
          ]
        }
      },
      "Resource": [
        "arn:aws:kms:ap-northeast-1:${account_id}:key/alias/crr-tokyo"
      ]
    },
    {
      "Sid": "EncryptDestRegionKMSKey",
      "Action": [
        "kms:Encrypt"
      ],
      "Effect": "Allow",
      "Condition": {
        "StringLike": {
          "kms:ViaService": "s3.ap-northeast-3.amazonaws.com",
          "kms:EncryptionContext:aws:s3:arn": [
            "arn:aws:s3:::demo-osaka-crr-01/*"
          ]
        }
      },
      "Resource": [
        "arn:aws:kms:ap-northeast-3:${account_id}:key/alias/crr-osaka"
      ]
    }
  ]
}

4. レプリケーション設定

送信元バケットレプリケーションルールを設定。設定内容は以下の通り。

{
    "ReplicationConfiguration": {
        "Role": "arn:aws:iam::${account_id}:role/demo-crr",    // IAMロールを指定
        "Rules": [
            {
                "ID": "crr-rule-01",    // レプリケーションルール名を指定
                "Priority": 0,
                "Filter": {
                    "And": {
                        "Prefix": "demo",    // プレフィックスを指定
                        "Tags": [                  // タグ条件を指定
                            {
                                "Key": "IS_REP",
                                "Value": "true"
                            }
                        ]
                    }
                },
                "Status": "Enabled",
                "SourceSelectionCriteria": {
                    "SseKmsEncryptedObjects": {
                        "Status": "Enabled"                      // 暗号化を有効
                    }
                },
                "Destination": {
                    "Bucket": "arn:aws:s3:::demo-osaka-crr-01",      // 送信先バケット
                    "EncryptionConfiguration": {
                        "ReplicaKmsKeyID": "arn:aws:kms:ap-northeast-3:${account_id}:key/alias/crr-osaka"      // 送信先で使用するKMSキーを使用
                    }
                },
                "DeleteMarkerReplication": {
                    "Status": "Disabled"
                }
            }
        ]
    }
}

(補足) IAMで設定した条件キーについての解説。

条件名 役割
s3:x-amz-server-side-encryption オブジェクトに対して暗号化を要求する。今回は条件演算子StringLikeIfExistsと組みわせてオブジェクトは全て暗号化される必要がある
s3:x-amz-server-side-encryption-aws-kms-key-id オブジェクトは特定のKMSキーでないと暗号化できない。(選択する際はkeyIDを指定すること。)
kms:ViaService 特定のサービスからのみアクセス許可
kms:EncryptionContext 暗号化コンテキストの使用。S3の場合はArnを指定。詳しくはこちら

Test

  • オブジェクトをアップロード。 オブジェクトに対してdemo/sample.txtにタグIS_REP : trueを付与する。

  • 送信元demo-tokyo-crr-01のオブジェクトを確認。ReplicationStatusがPENDING -> COMPLETEDになること。

aws s3api head-object --bucket demo-tokyo-crr-01 --key demo/sample.txt
  • 送信先demo-osaka-crr-01のオブジェクトを確認。ReplicationStatusがREPLICAであること。
aws s3api head-object --bucket demo-tokyo-crr-01 --key demo/sample.txt

ハマったこと

なんとなく実施した際にハマったことを記載。 条件キーs3:x-amz-server-side-encryption-aws-kms-key-idで指定するKMSキーはAliasじゃなくKeyIDで指定しないとうまくいかない。(s3系の条件キーでは、aliasからidへの参照権限がないから?) そのため、レプリケーションを実施した際、REPLICATE -> FAILEDの状態になってしまった。

             :
      "Condition": {
        "StringLikeIfExists": {
          "s3:x-amz-server-side-encryption": [
            "aws:kms",
            "AES256"
          ],
          "s3:x-amz-server-side-encryption-aws-kms-key-id": [
            "arn:aws:kms:ap-northeast-3:${account_id}:key/[大阪のキーID]"
          ]
        }
      },
             :

仕事とかではKMSキーIDを指定していましたが、IDかAliasかどちらを指定した方がいいかなんとなくな感じであったので、今回のようにAliasだと参照できないパターンもあるのでkmsキーで指定した方がいいことがわかったのでよかったです(小並感)

References