KMSで暗号化されたS3のデータをLambdaで処理する方法を試してみた

KMSで暗号化されたS3のデータをLambdaで処理する方法を試してみた

2025.09.04

はじめに

お疲れ様です、あきとです。

今回は、AWS のサービスの一つである Lambda を使って、暗号化されたデータを処理する方法について紹介します。

S3 にデータを保存するときに暗号化できることはよく知られていますが、実際にその暗号化データを AWS 内でどのように処理できるのか疑問を持ち、調べて実際に Lambda で S3 内でデータを暗号化して保存できるか、保存したデータを復号化できるか試してみました。

事前知識

  • AWS の基本的なサービス(S3、Lambda、IAM、KMS)の理解
  • 簡単な Python の知識

やってみた

手順1: KMS キーの作成と設定

1-1. KMS キーの作成

カスタマー管理型のキーをデフォルトで作成してください。
後ほど、キーポリシーを編集します。

1-2. KMS操作用 IAM ポリシーの作成

Lambda でKMS権限付与のために IAM ポリシーを以下のように作成します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "S3Read",
      "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::<BUCKET_NAME>/*"
    },
    {
      "Sid": "S3WriteWithKmsOnly",
      "Effect": "Allow",
      "Action": "s3:PutObject",
      "Resource": "arn:aws:s3:::<BUCKET_NAME>/*"
    },
    {
      "Sid": "KmsForSseKmsFromS3Only",
      "Effect": "Allow",
      "Action": [
        "kms:Decrypt",
        "kms:GenerateDataKey*"
      ],
      "Resource": "arn:aws:kms:ap-northeast-1:<ACCOUNT_ID>:key/<KMS_KEY_ID>",
      "Condition": {
        "StringEquals": {
          "kms:ViaService": "s3.ap-northeast-1.amazonaws.com"
        },
        "ForAnyValue:StringLike": {
          "kms:EncryptionContext:aws:s3:arn": "arn:aws:s3:::<BUCKET_NAME>/*"
        }
      }
    }
  ]
}

各権限の説明:

  • s3:GetObject:S3 からオブジェクトを読み取れるようにする
  • s3:PutObject:S3 にオブジェクトを書き込めるようにする
  • kms:Decrypt:S3 に保存された暗号化オブジェクトを復号できるようにする
  • kms:GenerateDataKey*:S3 に新しいオブジェクトを書き込むときに必要なデータキーを生成する
  • Condition(kms:ViaService):S3 経由の特定バケット配下のオブジェクトの操作だけを許可

1-3. Lambda 用 IAM ロールの作成

Lambda で使用する IAM ロールを作成するために、ユースケースを Lambda にします。許可ポリシーに CloudWatch Logs への書き込み用の AWSLambdaBasicExecutionRole と先ほど作成したポリシーを追加し、作成します。

1-4. KMS キーの設定

作成した KMS キーの Default キーポリシーを以下のように変更します。

{
	"Version": "2012-10-17",
	"Id": "key-consolepolicy-3",
	"Statement": [
		{
			"Sid": "Enable IAM User Permissions",
			"Effect": "Allow",
			"Principal": {
				"AWS": "arn:aws:iam::<ACCOUNT_ID>:root"
			},
			"Action": "kms:*",
			"Resource": "*"
		},
		{
			"Sid": "AllowLambdaRoleUseOfKey",
			"Effect": "Allow",
			"Principal": {
				"AWS": "arn:aws:iam::<ACCOUNT_ID>:role/<LAMBDA_ROLE_NAME>"
			},
			"Action": [
				"kms:Decrypt",
				"kms:GenerateDataKey*"
			],
			"Resource": "*",
			"Condition": {
				"StringEquals": {
					"kms:ViaService": "s3.ap-northeast-1.amazonaws.com"
				}
			}
		}
	]
}

キーポリシーの説明:

  • Principal:このポリシーを使える IAM ロール(ここでは Lambda 実行ロール)を指定
  • Condition(kms:ViaService):S3 経由の操作だけを許可する制限(他のサービスからの利用を防ぐ)

手順2: Lambda 関数の実装とテスト

2-1. 基本的な Lambda の実装

KMS で暗号化された S3 を処理する Lambda を Python 3.13 で作成します:

import json
import boto3
import os

# --- S3 クライアント作成 ---
s3 = boto3.client("s3")

# 環境変数から S3 バケット名と KMS キーARNを取得
BUCKET = os.environ["BUCKET"]
KMS_KEY_ARN = os.environ["KMS_KEY_ARN"]

def lambda_handler(event, context):
    # --- 保存するテスト用データ(固定値) ---
    payload = {"message": "Hello from Lambda with SSE-KMS"}
    # JSON形式に変換し、バイト列にエンコード
    body = json.dumps(payload).encode("utf-8")

    # --- PutObject: S3に暗号化して保存 ---
    s3.put_object(
        Bucket=BUCKET,                      # 対象のバケット
        Key="sample.json",                  # 保存するオブジェクトのキー(ファイル名に相当)
        Body=body,                          # 保存するデータ本体
        ContentType="application/json",     # コンテンツタイプ(JSONを明示)
        ServerSideEncryption="aws:kms",     # サーバーサイド暗号化方式(KMS)を明示
        SSEKMSKeyId=KMS_KEY_ARN,            # 使用するKMSキーARNを指定
        BucketKeyEnabled=True               # 任意: S3 Bucket Keysを有効化(KMSリクエスト削減)
    )

    # --- GetObject: 保存した暗号化オブジェクトを取得 ---
    response = s3.get_object(
        Bucket=BUCKET, 
        Key="sample.json"
    )

    # 取得したデータをデコードして JSON として読み込み
    content = response['Body'].read().decode('utf-8')
    data = json.loads(content)

    # --- Lambdaの戻り値 ---
    return {
        'statusCode': 200,
        'body': json.dumps({
            'message': 'Successfully processed KMS encrypted S3 object',
            'data': data
        })
    }

2-2. 環境変数の設定

Lambda の環境変数に以下を設定:

  • BUCKET: 対象の S3 バケット名
  • KMS_KEY_ARN: 使用する KMS キーの ARN

lambda-setting

2-3. Lambda 関数のテスト

ハンドラを lambda_function.lambda_handler に設定し、
Lambda をテスト実行します。

手順3: S3 コンソールでの確認

3-1. 暗号化状態の確認

作成されたオブジェクトの暗号化設定を確認します。
S3 に対象の KMS で暗号化された sample.json のオブジェクトが、作成されます。

s3-encryption-settings

オブジェクトのプロパティから、SSE-KMS で適切に暗号化されていることが確認できます。

3-2. 動作確認結果

実行が成功すると、以下のようなレスポンスが返されます:

{
  "statusCode": 200,
  "body": "{\"message\": \"Successfully processed KMS encrypted S3 object\", \"data\": {\"message\": \"Hello from Lambda with SSE-KMS\"}}"
}

まとめ

今回は KMS で暗号化された S3 のデータを Lambda で処理する方法を実際に試しました。

IAM ポリシーと KMS キーポリシーを正しく設定することで、S3 に保存する際には自動的に暗号化され、取得時には復号化されることが確認できました(ただし、保存時に SSE-KMS を指定する必要があります)。今回の方法では、暗号化・復号化は KMS と S3 が自動的に処理するため、アプリケーションコードが復号処理を担っているわけではない点には注意が必要です。

本記事がどなたかの参考になれば幸いです。

参考資料

アノテーション株式会社について

アノテーション株式会社は、クラスメソッド社のグループ企業として「オペレーション・エクセレンス」を担える企業を目指してチャレンジを続けています。「らしく働く、らしく生きる」のスローガンを掲げ、様々な背景をもつ多様なメンバーが自由度の高い働き方を通してお客様へサービスを提供し続けてきました。現在当社では一緒に会社を盛り上げていただけるメンバーを募集中です。少しでもご興味あれば、アノテーション株式会社WEBサイトをご覧ください。

この記事をシェアする

facebookのロゴhatenaのロゴtwitterのロゴ

© Classmethod, Inc. All rights reserved.