share facebook facebook twitter menu hatena pocket slack

2015.12.14 MON

DynamoDBの暗号化データをKMSで復号化してメールで送る(DynamoDB Triggers)

鈴木 宏康

WRITTEN BY 鈴木 宏康

下記で、KMSで暗号化したデータをDynamoDBに登録
(SQS → Lambda → DynamoDB)したので、

今回は、下記のDynamoDB TriggersでDynamoDBにデータが登録されたタイミングで
再度LambdaでKMSを用いてデータを復号化し、その内容をメール(SES)してみました。

図で書くと、こんな感じです。

Untitled%2810%29

DynamoDBのテーブルは次の通りです。

2015-10-14_04-27-09

ですので、DynamoDB Streamsで渡されるLambdaのイベントの中身は、
こんな感じになります。

{'Records': [{
    'eventID': '...',
    'eventVersion': '1.0',
    'dynamodb': {
        'Keys': { 'uuid': {'S': 'urn:uuid:...'}},
        'NewImage': {
            'key3': {'S': '…'},
            'key3': {'S': '...'},
            'key1': {'S': '...'},
            'uuid': {'S': '...'}
        },
        'StreamViewType': 'NEW_AND_OLD_IMAGES',
        'SequenceNumber': ’...',
        'SizeBytes': 830
    },
    'awsRegion': 'ap-northeast-1',
    'eventName': 'INSERT',
    'eventSourceARN': '...',
    'eventSource': 'aws:dynamodb'
}]}

Lambdaのコードは、こんな感じです。

import logging
import boto3
import base64
import json

logger = logging.getLogger()
logger.setLevel(logging.INFO)

source = 'suzuki@suz-lab.com'
toAddress = 'suzuki@suz-lab.com'
subject = 'SUZ-LAB TEST'

def lambda_handler(event, context):

    try:
        logger.info(event)
        responses = []

        text = []
        kms = boto3.client('kms')
        for record in event['Records']:
            if record['eventName'] == 'INSERT':
                text.append(kms.decrypt(
                    CiphertextBlob = base64.b64decode(
                        record['dynamodb']['NewImage']['key1']['S']
                    )
                )['Plaintext'])
                text.append(kms.decrypt(
                    CiphertextBlob = base64.b64decode(
                        record['dynamodb']['NewImage']['key2']['S']
                    )
                )['Plaintext'])
                text.append(kms.decrypt(
                    CiphertextBlob = base64.b64decode(
                        record['dynamodb']['NewImage']['key3']['S']
                    )
                )['Plaintext'])

        responses.append(boto3.client(
                'ses',
                region_name = 'us-east-1'
            ).send_email(
                Source = source,
                Destination = {'ToAddresses': [toAddress]},
                Message = {
                    'Subject': {'Data': subject},
                    'Body': {'Text': {'Data': json.dumps(text)}}
                }
            )
        )

        logger.info(responses)
        return responses

    except Exception as e:
        logger.error(e)
        raise e

実際に上記のLambdaがDynamoDB Streamsと連動するように、
イベントの設定をします。

2015-10-12_16-47-18_01

2015-10-12_16-50-05

2015-10-12_16-49-06

2015-10-12_16-50-49

ちなみに、設定項目のBatch sizeとStarting positionは下記の通りです。

  • Batch size: Lambdaがストリームから受け取るレコード数の最大値(1 -10000)
  • Starting position: Lambdaが読み始めるストリームの場所
    — TRIM_HORIZON: 最も古くに保存されたレコードからスタート
    — LATEST: 到着した新しいレコードからスタート

当然、Lambdaに関連付けられているIAMロール(lambda_basic_execution)に
SESを操作するポリシーをアタッチする必要もあります。

2015-10-14_03-12-29_01

2015-10-14_03-13-36

2015-10-14_03-14-35

この状態で、DynamoDBに(暗号化した)データを登録すると、
次のように、復号化されたデータがメールで送信されてきました。

2015-10-14_03-49-58

ここまでが、会員登録して、必要な情報を暗号化してDBに登録して、
確認メールを送信する流れって感じでしょうか?

元記事はこちら

DynamoDBの暗号化データをKMSで復号化してメールで送る(DynamoDB Triggers)

鈴木 宏康

鈴木 宏康

愛知県生まれ。東京工業大学大学院修士課程修了。在学時より、ベンチャー企業でインターネットに関する業務に携わり、現在はクラウド(主にAmazon Web Services)上での開発・運用を軸とした事業の、業務の中心として活躍。