[アップデート] Amazon S3 Tables がSSE-KMS(カスタマーマネージドキー)暗号化に対応したので調べてみた
はじめに
みなさんどうもこんにちは、少し前にS3 Tablesでも「SSE-S3」に加えて「SSE-KMS」による暗号化がサポートされました。特徴は次の通りです。
- 「SSE-KMS」の使用によりキーローテーションやアクセスポリシーなど細かい制御が可能になった
- カスタマー管理キーのみ使用可能、AWS管理キーはサポート外
- KMSキーに対するアクセス権限を付与する必要あり
- テーブルバケット また 個々のテーブル に対してそれぞれ別のキーを使って暗号化設定を指定可能
- CloudTrailイベントログで暗号化操作に関する監視と監査が可能
- AWS CLIを用いてテーブルバケットに対するデフォルトの暗号化解除&再設定可能
 今回はそれら動作を詳しく検証していきたいと思います。
今回はS3 Tablesの詳しい説明は割愛します。以下の記事を参考にしてください。
動作検証
SSE-KMSのS3テーブルバケット検証
早速ですが、SSE-KMS対応のテーブルバケットを作成してみましょう。
- まずはAmazon S3マネジメントコンソールから「テーブルバケットを作成」を選択します

- テーブルバケット名を適宜入力し、デフォルトの暗号化タイプにに「AWS Key Management Service キーを使用したサーバー側の暗号化(SSE-KMS)」にチェックを入れ、「KMSキーを作成する」ボタンを押下すとKMSの作成画面へ飛びます

- 下記の条件でキーを作成します
- エイリアス: 「demo-sse-kms-table-bucket-key」
- キータイプ: 対称 ※非対称キーは「SSE-KMS」として設定不可能です
- キーの使用法: 暗号化および複合化
- キーマテリアルオリジン: KMS
- リージョン: 単一
※キー管理アクセス許可とキー使用法アクセス許可に関しては一旦何もせずスキップし、作成します



- 
テーブルバケットの作成画面に戻り、作成したKMSキーのARNを選択し、「テーブルバケットを作成」を押下します 
  
- 
続いてテーブルバケットの詳細から「Athenaでテーブルを作成」を選択し、名前空間を作成します 
- 名前空間: demo_namespace



名前空間の作成が成功した画面からもう一度「Athenaでテーブルを作成」を押下し、Athenaの画面へ飛びます

- Athenaの画面で以下を確認し、サンプルのCREATE文を実行します
- データソース: AwsDataCatalog
- カタログ: 作成したS3テーブルバケットのプレフィクス
- データベース: 作成した名前空間「demo_namespace」
するとエラーになりテーブルが作成できません。

ここが「SSE-S3」暗号化との作業工程の違いでKMSカスタマー管理キーを使用するための権限を付与する必要があります。
以下2つのPrincipalにKMSキーへのアクセス権限を追加してあげる必要があります。
- サービス統合で自動作成されたIAMロール: S3TableRoleForLakeFormation
- テーブルバケットのメンテナンスに必要なサービスプリンシパル: maintenance.s3tables.amazonaws.com

今回の場合は作成したカスタマー管理キー「demo-sse-kms-table-bucket-key」のキーポリシーに「maintenance.s3tables.amazonaws.com」プリンシパルへのアクセス権限を付与し、IAMロール「S3TableRoleForLakeFormation」のインラインポリシーとしてKMSキーへのアクセス権限を付与します。
実際の設定: KMSカスタマー管理キーポリシー

実際の設定: S3TableRoleForLakeFormationに対するインラインポリシー「kms-use-policy」

また他のIAMロールを使ってAthenaを通さずに直接操作したり、S3メタデータテーブルでKMS暗号化を使用する場合は別途そのIAMロールやサービスプリンシパルに対してもアクセス権を付与する必要があります。詳細は下記を確認してください。
ちなみに下記のようにキーポリシーにまとめて2つのプリンシパルに対する権限を与えてあげるだけでも操作可能です。この場合上記のようにIAMロールへKMSキーの使用権限を付与する必要はありません。
{
      "Sid": "EnableKeyUsage",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::{アカウントID}:role/service-role/S3TablesRoleForLakeFormation",
        "Service": "maintenance.s3tables.amazonaws.com"
      },
      "Action": [
        "kms:GenerateDataKey",
        "kms:Decrypt"
      ],
      "Resource": "{KMSキーのARN}",
      "Condition": {
        "StringLike": {
          "kms:EncryptionContext:aws:s3:arn": "{S3テーブルバケットのARN}"
        }
      }
}
- 
KMSキーに対する権限が設定できたのでもう一度サンプルのCREATE文を試してみます 
 名前空間: 「demo_namespace」配下にテーブル「daily_sales」が作成されました。
  
- 
INSERT文でデータを追加しSELECTで確認します 
  
AWS CLIでの操作確認
AWS CLIでの暗号化に関する一通りの操作を確認してみましょう。
使用したaws cli version : aws-cli/2.27.9
# テーブルバケットに対する現在のデフォルト暗号化方式の確認
aws s3tables get-table-bucket-encryption --table-bucket-arn {作成したTableバケットのARN}
# 結果
{
    "encryptionConfiguration": {
        "sseAlgorithm": "aws:kms",
        "kmsKeyArn": "{作成時に指定したKMSのキーARN}"
    }
}
このようにテーブルバケットにデフォルトのKMS暗号化情報がセットされているとテーブルを作成するたびにデフォルトでこのKMSキーを使って暗号化してくれます。別のKMSキーにテーブルバケットのデフォルト暗号化を変更したい場合は以下のコマンドが有効です。
# テーブルバケットに対する現在のデフォルト暗号化キーの変更
aws s3tables put-table-bucket-encryption \
--table-bucket-arn "{作成したTableバケットのARN}" \
--encryption-configuration '{
    "sseAlgorithm": "aws:kms",
    "kmsKeyArn": "{デフォルトに指定したいKMSのキーARN}"
  }'
また、テーブルバケットに対する暗号化設定を削除したい場合は以下のコマンドで削除できます。
# テーブルバケットに対するデフォルト暗号化設定を解除
aws s3tables delete-table-bucket-encryption --table-bucket-arn {作成したTableバケットのARN}
削除すると先ほどのデフォルト暗号化を確認するコマンドは以下のようにエラーになります。
※テーブルバケットに対するデフォルトの暗号化設定を削除しただけで存在しているテーブルの暗号化が解除されているわけではありません。
# 再度テーブルバケットに対する現在のデフォルト暗号化方式の確認
aws s3tables get-table-bucket-encryption --table-bucket-arn {作成したTableバケットのARN}
# 結果
An error occurred (NotFoundException) when calling the GetTableBucketEncryption operation: The specified encryption configuration does not exist.
今回のアップデートで可能になった「SSE-KMS」暗号化の強力な特徴はテーブルごとにKMSキーを変更できることです。
まず先ほど作成したテーブル「daily_sales」について暗号化設定を確認してみましょう。テーブルに対して暗号化設定を確認する場合は名前空間とテーブル名を指定してあげる必要があります。
# テーブル自体の暗号化設定を確認
aws s3tables get-table-encryption --table-bucket-arn {作成したTableバケットのARN} --namespace demo_namespace --name daily_sales
# 結果
{
    "encryptionConfiguration": {
        "sseAlgorithm": "aws:kms",
        "kmsKeyArn": "{作成したdemo-sse-kms-table-bucket-keyのARN}"
    }
}
続いて、同じ名前空間「demo_namespace」にテーブル「orders」を追加します。この時に先ほどとは別のKMSキーを使って作成時に以下のように指定します。
# S3テーブル作成 KMS暗号化指定
aws s3tables create-table \
--table-bucket-arn {作成したTableバケットのARN} \
--namespace "demo_namespace" \
--name "orders" \
--format "ICEBERG" --encryption-configuration '{
    "sseAlgorithm": "aws:kms",
    "kmsKeyArn": "{別のKMSキーのARN}"
  }' \
  --metadata '{
    "iceberg": {
      "schema": {
        "fields": [
          {
            "name": "order_id",
            "type": "string",
            "required": true
          },
          {
            "name": "order_date",
            "type": "timestamp",
            "required": true
          },
          {
            "name": "total_amount",
            "type": "decimal(10,2)",
            "required": true
          }
        ]
      }
    }
  }'
「orders」テーブルの暗号化設定を確認してみると「daily_sales」とは別のKMSキーのARNが表示されており、無事暗号化キーをわけることができました。
# テーブル自体の暗号化設定を確認
aws s3tables get-table-encryption --table-bucket-arn {作成したTableバケットのARN} --namespace demo_namespace --name orders
# 結果
{
    "encryptionConfiguration": {
        "sseAlgorithm": "aws:kms",
        "kmsKeyArn": "{テーブル作成時に指定した別のKMSキーのARN}"
    }
}
またテーブルに対して暗号化キーを途中で変更することはできません。変更したい場合はテーブルをDROPして再度作成し直す必要があります。
CloudTrailでイベント履歴を確認
S3Tablesの「SSE-KMS」暗号化について以下のイベントがCloudTrailで記録されます。操作検知や監査に使用できるので確認してみましょう。
- 
s3tables:PutTableBucketEncryption 
- 
s3tables:GetTableBucketEncryption 
- 
s3tables:DeleteTableBucketEncryption 
- 
s3tables:GetTableEncryption 
- 
s3tables:CreateTable 
- 
s3tables:CreateTableBucket 
今回はコンソール上でイベントソース「s3tables.amazonaws.com」でフィルタリングして確認してみました。きちんとイベントが記録されています。

最後に
今回は、S3 Tables における SSE-KMS(カスタマー管理キー)を使った暗号化設定について、具体的な設定手順から、Athenaとの統合、各種権限まわり、そしてテーブル単位でのKMSキーの使い分けを実際の操作を通して検証しました。
特に以下のポイントは実務上非常に重要です
- 
S3 Tables では SSE-KMS を使う場合、カスタマー管理キーの使用権限が明示的に設定されていないとテーブル作成に失敗する 
- 
暗号化対象は「テーブルバケット」単位だけでなく、「テーブル単位」でもKMSキーを分けて設定可能 
- 
CloudTrail によるイベント履歴に監査証跡を記録可能 
現在はまだS3 Tablesに対してマネジメントコンソールだけでは対応できていない部分も多いのでAWS CLIを駆使して操作することが重要だと感じました。今回は以上です。












