Data key caching example: AWS CloudFormation template - AWS Encryption SDK

Data key caching example: AWS CloudFormation template

This AWS CloudFormation template sets up all the necessary AWS resources to reproduce the data key caching example.

JSON
{ "Parameters": { "SourceCodeBucket": { "Type": "String", "Description": "S3 bucket containing Lambda source code zip files" }, "PythonLambdaS3Key": { "Type": "String", "Description": "S3 key containing Python Lambda source code zip file" }, "PythonLambdaObjectVersionId": { "Type": "String", "Description": "S3 version id for S3 key containing Python Lambda source code zip file" }, "JavaLambdaS3Key": { "Type": "String", "Description": "S3 key containing Python Lambda source code zip file" }, "JavaLambdaObjectVersionId": { "Type": "String", "Description": "S3 version id for S3 key containing Python Lambda source code zip file" }, "KeyAliasSuffix": { "Type": "String", "Description": "Suffix to use for KMS key Alias (ie: alias/<KeyAliasSuffix>)" }, "StreamName": { "Type": "String", "Description": "Name to use for Kinesis Stream" } }, "Resources": { "InputStream": { "Type": "AWS::Kinesis::Stream", "Properties": { "Name": { "Ref": "StreamName" }, "ShardCount": 2 } }, "PythonLambdaOutputTable": { "Type": "AWS::DynamoDB::Table", "Properties": { "AttributeDefinitions": [ { "AttributeName": "id", "AttributeType": "S" } ], "KeySchema": [ { "AttributeName": "id", "KeyType": "HASH" } ], "ProvisionedThroughput": { "ReadCapacityUnits": 1, "WriteCapacityUnits": 1 } } }, "PythonLambdaRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }, "ManagedPolicyArns": [ "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" ], "Policies": [ { "PolicyName": "PythonLambdaAccess", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:DescribeTable", "dynamodb:BatchWriteItem" ], "Resource": { "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PythonLambdaOutputTable}" } }, { "Effect": "Allow", "Action": [ "dynamodb:PutItem" ], "Resource": { "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PythonLambdaOutputTable}*" } }, { "Effect": "Allow", "Action": [ "kinesis:GetRecords", "kinesis:GetShardIterator", "kinesis:DescribeStream", "kinesis:ListStreams" ], "Resource": { "Fn::Sub": "arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}" } } ] } } ] } }, "PythonLambdaFunction": { "Type": "AWS::Lambda::Function", "Properties": { "Description": "Python consumer", "Runtime": "python2.7", "MemorySize": 512, "Timeout": 90, "Role": { "Fn::GetAtt": [ "PythonLambdaRole", "Arn" ] }, "Handler": "aws_crypto_examples.kinesis_datakey_caching.consumer.lambda_handler", "Code": { "S3Bucket": { "Ref": "SourceCodeBucket" }, "S3Key": { "Ref": "PythonLambdaS3Key" }, "S3ObjectVersion": { "Ref": "PythonLambdaObjectVersionId" } }, "Environment": { "Variables": { "TABLE_NAME": { "Ref": "PythonLambdaOutputTable" } } } } }, "PythonLambdaSourceMapping": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { "BatchSize": 1, "Enabled": true, "EventSourceArn": { "Fn::Sub": "arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}" }, "FunctionName": { "Ref": "PythonLambdaFunction" }, "StartingPosition": "TRIM_HORIZON" } }, "JavaLambdaOutputTable": { "Type": "AWS::DynamoDB::Table", "Properties": { "AttributeDefinitions": [ { "AttributeName": "id", "AttributeType": "S" } ], "KeySchema": [ { "AttributeName": "id", "KeyType": "HASH" } ], "ProvisionedThroughput": { "ReadCapacityUnits": 1, "WriteCapacityUnits": 1 } } }, "JavaLambdaRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }, "ManagedPolicyArns": [ "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" ], "Policies": [ { "PolicyName": "JavaLambdaAccess", "PolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "dynamodb:DescribeTable", "dynamodb:BatchWriteItem" ], "Resource": { "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${JavaLambdaOutputTable}" } }, { "Effect": "Allow", "Action": [ "dynamodb:PutItem" ], "Resource": { "Fn::Sub": "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${JavaLambdaOutputTable}*" } }, { "Effect": "Allow", "Action": [ "kinesis:GetRecords", "kinesis:GetShardIterator", "kinesis:DescribeStream", "kinesis:ListStreams" ], "Resource": { "Fn::Sub": "arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}" } } ] } } ] } }, "JavaLambdaFunction": { "Type": "AWS::Lambda::Function", "Properties": { "Description": "Java consumer", "Runtime": "java8", "MemorySize": 512, "Timeout": 90, "Role": { "Fn::GetAtt": [ "JavaLambdaRole", "Arn" ] }, "Handler": "com.amazonaws.crypto.examples.kinesisdatakeycaching.LambdaDecryptAndWrite::handleRequest", "Code": { "S3Bucket": { "Ref": "SourceCodeBucket" }, "S3Key": { "Ref": "JavaLambdaS3Key" }, "S3ObjectVersion": { "Ref": "JavaLambdaObjectVersionId" } }, "Environment": { "Variables": { "TABLE_NAME": { "Ref": "JavaLambdaOutputTable" }, "CMK_ARN": { "Fn::GetAtt": [ "RegionKinesisCMK", "Arn" ] } } } } }, "JavaLambdaSourceMapping": { "Type": "AWS::Lambda::EventSourceMapping", "Properties": { "BatchSize": 1, "Enabled": true, "EventSourceArn": { "Fn::Sub": "arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream}" }, "FunctionName": { "Ref": "JavaLambdaFunction" }, "StartingPosition": "TRIM_HORIZON" } }, "RegionKinesisCMK": { "Type": "AWS::KMS::Key", "Properties": { "Description": "Used to encrypt data passing through Kinesis Stream in this region", "Enabled": true, "KeyPolicy": { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": { "Fn::Sub": "arn:aws:iam::${AWS::AccountId}:root" } }, "Action": [ "kms:Encrypt", "kms:GenerateDataKey", "kms:CreateAlias", "kms:DeleteAlias", "kms:DescribeKey", "kms:DisableKey", "kms:EnableKey", "kms:PutKeyPolicy", "kms:ScheduleKeyDeletion", "kms:UpdateAlias", "kms:UpdateKeyDescription" ], "Resource": "*" }, { "Effect": "Allow", "Principal": { "AWS": [ { "Fn::GetAtt": [ "PythonLambdaRole", "Arn" ] }, { "Fn::GetAtt": [ "JavaLambdaRole", "Arn" ] } ] }, "Action": "kms:Decrypt", "Resource": "*" } ] } } }, "RegionKinesisCMKAlias": { "Type": "AWS::KMS::Alias", "Properties": { "AliasName": { "Fn::Sub": "alias/${KeyAliasSuffix}" }, "TargetKeyId": { "Ref": "RegionKinesisCMK" } } } } }
YAML
Parameters: SourceCodeBucket: Type: String Description: S3 bucket containing Lambda source code zip files PythonLambdaS3Key: Type: String Description: S3 key containing Python Lambda source code zip file PythonLambdaObjectVersionId: Type: String Description: S3 version id for S3 key containing Python Lambda source code zip file JavaLambdaS3Key: Type: String Description: S3 key containing Python Lambda source code zip file JavaLambdaObjectVersionId: Type: String Description: S3 version id for S3 key containing Python Lambda source code zip file KeyAliasSuffix: Type: String Description: 'Suffix to use for KMS CMK Alias (ie: alias/<KeyAliasSuffix>)' StreamName: Type: String Description: Name to use for Kinesis Stream Resources: InputStream: Type: AWS::Kinesis::Stream Properties: Name: !Ref StreamName ShardCount: 2 PythonLambdaOutputTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 PythonLambdaRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: PythonLambdaAccess PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - dynamodb:DescribeTable - dynamodb:BatchWriteItem Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PythonLambdaOutputTable} - Effect: Allow Action: - dynamodb:PutItem Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${PythonLambdaOutputTable}* - Effect: Allow Action: - kinesis:GetRecords - kinesis:GetShardIterator - kinesis:DescribeStream - kinesis:ListStreams Resource: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream} PythonLambdaFunction: Type: AWS::Lambda::Function Properties: Description: Python consumer Runtime: python2.7 MemorySize: 512 Timeout: 90 Role: !GetAtt PythonLambdaRole.Arn Handler: aws_crypto_examples.kinesis_datakey_caching.consumer.lambda_handler Code: S3Bucket: !Ref SourceCodeBucket S3Key: !Ref PythonLambdaS3Key S3ObjectVersion: !Ref PythonLambdaObjectVersionId Environment: Variables: TABLE_NAME: !Ref PythonLambdaOutputTable PythonLambdaSourceMapping: Type: AWS::Lambda::EventSourceMapping Properties: BatchSize: 1 Enabled: true EventSourceArn: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream} FunctionName: !Ref PythonLambdaFunction StartingPosition: TRIM_HORIZON JavaLambdaOutputTable: Type: AWS::DynamoDB::Table Properties: AttributeDefinitions: - AttributeName: id AttributeType: S KeySchema: - AttributeName: id KeyType: HASH ProvisionedThroughput: ReadCapacityUnits: 1 WriteCapacityUnits: 1 JavaLambdaRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: JavaLambdaAccess PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - dynamodb:DescribeTable - dynamodb:BatchWriteItem Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${JavaLambdaOutputTable} - Effect: Allow Action: - dynamodb:PutItem Resource: !Sub arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${JavaLambdaOutputTable}* - Effect: Allow Action: - kinesis:GetRecords - kinesis:GetShardIterator - kinesis:DescribeStream - kinesis:ListStreams Resource: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream} JavaLambdaFunction: Type: AWS::Lambda::Function Properties: Description: Java consumer Runtime: java8 MemorySize: 512 Timeout: 90 Role: !GetAtt JavaLambdaRole.Arn Handler: com.amazonaws.crypto.examples.kinesisdatakeycaching.LambdaDecryptAndWrite::handleRequest Code: S3Bucket: !Ref SourceCodeBucket S3Key: !Ref JavaLambdaS3Key S3ObjectVersion: !Ref JavaLambdaObjectVersionId Environment: Variables: TABLE_NAME: !Ref JavaLambdaOutputTable CMK_ARN: !GetAtt RegionKinesisCMK.Arn JavaLambdaSourceMapping: Type: AWS::Lambda::EventSourceMapping Properties: BatchSize: 1 Enabled: true EventSourceArn: !Sub arn:aws:kinesis:${AWS::Region}:${AWS::AccountId}:stream/${InputStream} FunctionName: !Ref JavaLambdaFunction StartingPosition: TRIM_HORIZON RegionKinesisCMK: Type: AWS::KMS::Key Properties: Description: Used to encrypt data passing through Kinesis Stream in this region Enabled: true KeyPolicy: Version: 2012-10-17 Statement: - Effect: Allow Principal: AWS: !Sub arn:aws:iam::${AWS::AccountId}:root Action: # Data plane actions - kms:Encrypt - kms:GenerateDataKey # Control plane actions - kms:CreateAlias - kms:DeleteAlias - kms:DescribeKey - kms:DisableKey - kms:EnableKey - kms:PutKeyPolicy - kms:ScheduleKeyDeletion - kms:UpdateAlias - kms:UpdateKeyDescription Resource: '*' - Effect: Allow Principal: AWS: - !GetAtt PythonLambdaRole.Arn - !GetAtt JavaLambdaRole.Arn Action: kms:Decrypt Resource: '*' RegionKinesisCMKAlias: Type: AWS::KMS::Alias Properties: AliasName: !Sub alias/${KeyAliasSuffix} TargetKeyId: !Ref RegionKinesisCMK