Deploy Lambda and Configure Event Mapping with AWS CDK#
Keywords: Amazon, AWS, Lambda, CDK, Event
Overview#
This document provides a comprehensive list of sample AWS CDK code in Python to deploy a Lambda function and configure event mapping for various AWS services.
# create virtualenv
virtualenv -p python3.10 .venv
# activate virtualenv
source .venv/bin/activate
# install dependencies
pip install -r requirements.txt
# deploy
python cdk_deploy.py
# delete
python cdk_delete.py
S3 put#
s3-put.json
1{
2 "Records": [
3 {
4 "eventVersion": "2.0",
5 "eventSource": "aws:s3",
6 "awsRegion": "us-east-1",
7 "eventTime": "1970-01-01T00:00:00.000Z",
8 "eventName": "ObjectCreated:Put",
9 "userIdentity": {
10 "principalId": "EXAMPLE"
11 },
12 "requestParameters": {
13 "sourceIPAddress": "127.0.0.1"
14 },
15 "responseElements": {
16 "x-amz-request-id": "EXAMPLE123456789",
17 "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
18 },
19 "s3": {
20 "s3SchemaVersion": "1.0",
21 "configurationId": "testConfigRule",
22 "bucket": {
23 "name": "example-bucket",
24 "ownerIdentity": {
25 "principalId": "EXAMPLE"
26 },
27 "arn": "arn:aws:s3:::example-bucket"
28 },
29 "object": {
30 "key": "test%2Fkey",
31 "size": 1024,
32 "eTag": "0123456789abcdef0123456789abcdef",
33 "sequencer": "0A1B2C3D4E5F678901"
34 }
35 }
36 }
37 ]
38}
S3 delete#
s3-delete.json
1{
2 "Records": [
3 {
4 "eventVersion": "2.0",
5 "eventSource": "aws:s3",
6 "awsRegion": "us-east-1",
7 "eventTime": "1970-01-01T00:00:00.000Z",
8 "eventName": "ObjectRemoved:Delete",
9 "userIdentity": {
10 "principalId": "EXAMPLE"
11 },
12 "requestParameters": {
13 "sourceIPAddress": "127.0.0.1"
14 },
15 "responseElements": {
16 "x-amz-request-id": "EXAMPLE123456789",
17 "x-amz-id-2": "EXAMPLE123/5678abcdefghijklambdaisawesome/mnopqrstuvwxyzABCDEFGH"
18 },
19 "s3": {
20 "s3SchemaVersion": "1.0",
21 "configurationId": "testConfigRule",
22 "bucket": {
23 "name": "example-bucket",
24 "ownerIdentity": {
25 "principalId": "EXAMPLE"
26 },
27 "arn": "arn:aws:s3:::example-bucket"
28 },
29 "object": {
30 "key": "test%2Fkey",
31 "sequencer": "0A1B2C3D4E5F678901"
32 }
33 }
34 }
35 ]
36}
SNS Notification#
sns-notification.json
1{
2 "Records": [
3 {
4 "EventSource": "aws:sns",
5 "EventVersion": "1.0",
6 "EventSubscriptionArn": "arn:aws:sns:us-east-1:{{{accountId}}}:ExampleTopic",
7 "Sns": {
8 "Type": "Notification",
9 "MessageId": "95df01b4-ee98-5cb9-9903-4c221d41eb5e",
10 "TopicArn": "arn:aws:sns:us-east-1:123456789012:ExampleTopic",
11 "Subject": "example subject",
12 "Message": "example message",
13 "Timestamp": "1970-01-01T00:00:00.000Z",
14 "SignatureVersion": "1",
15 "Signature": "EXAMPLE",
16 "SigningCertUrl": "EXAMPLE",
17 "UnsubscribeUrl": "EXAMPLE",
18 "MessageAttributes": {
19 "Test": {
20 "Type": "String",
21 "Value": "TestString"
22 },
23 "TestBinary": {
24 "Type": "Binary",
25 "Value": "TestBinary"
26 }
27 }
28 }
29 }
30 ]
31}
app.py
1# -*- coding: utf-8 -*-
2
3from pathlib import Path
4
5from boto_session_manager import BotoSesManager
6
7import aws_cdk as cdk
8import aws_cdk.aws_iam as iam
9import aws_cdk.aws_sns as sns
10import aws_cdk.aws_sns_subscriptions as sns_subscription
11import aws_cdk.aws_lambda as lambda_
12from constructs import Construct
13
14
15class Stack(cdk.Stack):
16 def __init__(
17 self,
18 scope: Construct,
19 id: str,
20 project_name: str,
21 **kwargs,
22 ) -> None:
23 project_name_slug = project_name.replace("_", "-")
24 super().__init__(scope, id=id, stack_name=project_name_slug, **kwargs)
25
26 self.iam_role_for_lbd = iam.Role(
27 self,
28 "IamRoleForLambda",
29 assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
30 role_name=f"{project_name}-{cdk.Aws.REGION}-lambda-role",
31 managed_policies=[
32 iam.ManagedPolicy.from_aws_managed_policy_name("PowerUserAccess")
33 ],
34 )
35
36 # SNS is declared in the same stack
37 self.sns_topic_name = f"{project_name}-topic"
38 self.sns_topic = sns.Topic(
39 self,
40 "SNSTopic",
41 topic_name=self.sns_topic_name,
42 )
43
44 self.lbd_func_1 = lambda_.Function(
45 self,
46 "LambdaFunction1",
47 function_name=f"{project_name}-1",
48 code=lambda_.Code.from_asset(f"{dir_lambda_app}"),
49 handler=f"lambda_function.lambda_handler",
50 runtime=lambda_.Runtime.PYTHON_3_10,
51 memory_size=128,
52 timeout=cdk.Duration.seconds(3),
53 role=self.iam_role_for_lbd,
54 )
55
56 self.sns_topic.add_subscription(
57 sns_subscription.LambdaSubscription(self.lbd_func_1)
58 )
59
60 # SNS is declared in another stack
61 self.lbd_func_2 = lambda_.Function(
62 self,
63 "LambdaFunction2",
64 function_name=f"{project_name}-2",
65 code=lambda_.Code.from_asset(f"{dir_lambda_app}"),
66 handler=f"lambda_function.lambda_handler",
67 runtime=lambda_.Runtime.PYTHON_3_10,
68 memory_size=128,
69 timeout=cdk.Duration.seconds(3),
70 role=self.iam_role_for_lbd,
71 )
72
73 sns_topic = sns.Topic.from_topic_arn(
74 self,
75 "SNSTopicInterface",
76 topic_arn=f"arn:aws:sns:{cdk.Aws.REGION}:{cdk.Aws.ACCOUNT_ID}:{self.sns_topic_name}",
77 )
78 sns_topic.add_subscription(sns_subscription.LambdaSubscription(self.lbd_func_2))
79
80
81# ------------------------------------------------------------------------------
82# Config
83aws_profile = "bmt_app_dev_us_east_1"
84project_name = "lbd_cdk_event_demo-sns"
85# ------------------------------------------------------------------------------
86
87dir_workspace = Path(__file__).absolute().parent
88dir_lambda_app = dir_workspace.joinpath("lambda_app")
89bsm = BotoSesManager(profile_name=aws_profile)
90
91app = cdk.App()
92stack = Stack(app, "MyApp", project_name=project_name)
93
94if __name__ == "__main__":
95 app.synth()
SQS#
sqs.json
1{
2 "Records": [
3 {
4 "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
5 "receiptHandle": "MessageReceiptHandle",
6 "body": "Hello from SQS!",
7 "attributes": {
8 "ApproximateReceiveCount": "1",
9 "SentTimestamp": "1523232000000",
10 "SenderId": "123456789012",
11 "ApproximateFirstReceiveTimestamp": "1523232000001"
12 },
13 "messageAttributes": {},
14 "md5OfBody": "{{{md5_of_body}}}",
15 "eventSource": "aws:sqs",
16 "eventSourceARN": "arn:aws:sqs:us-east-1:123456789012:MyQueue",
17 "awsRegion": "us-east-1"
18 }
19 ]
20}
app.py
1# -*- coding: utf-8 -*-
2
3from pathlib import Path
4
5from boto_session_manager import BotoSesManager
6
7import aws_cdk as cdk
8import aws_cdk.aws_iam as iam
9import aws_cdk.aws_sqs as sqs
10import aws_cdk.aws_lambda as lambda_
11import aws_cdk.aws_lambda_event_sources as event_source
12from constructs import Construct
13
14
15class Stack(cdk.Stack):
16 def __init__(
17 self,
18 scope: Construct,
19 id: str,
20 project_name: str,
21 **kwargs,
22 ) -> None:
23 project_name_slug = project_name.replace("_", "-")
24 super().__init__(scope, id=id, stack_name=project_name_slug, **kwargs)
25
26 self.iam_role_for_lbd = iam.Role(
27 self,
28 "IamRoleForLambda",
29 assumed_by=iam.ServicePrincipal("lambda.amazonaws.com"),
30 role_name=f"{project_name}-{cdk.Aws.REGION}-lambda-role",
31 managed_policies=[
32 iam.ManagedPolicy.from_aws_managed_policy_name("PowerUserAccess")
33 ],
34 )
35
36 # SQS is declared in the same stack
37 self.sqs_queue_name = f"{project_name}-queue"
38 self.sqs_queue = sqs.Queue(
39 self,
40 "SQSQueue",
41 queue_name=self.sqs_queue_name,
42 )
43
44 self.lbd_func_1 = lambda_.Function(
45 self,
46 "LambdaFunction1",
47 function_name=f"{project_name}-1",
48 code=lambda_.Code.from_asset(f"{dir_lambda_app}"),
49 handler=f"lambda_function.lambda_handler",
50 runtime=lambda_.Runtime.PYTHON_3_10,
51 memory_size=128,
52 timeout=cdk.Duration.seconds(3),
53 role=self.iam_role_for_lbd,
54 )
55
56 self.sqs_event_source_1 = event_source.SqsEventSource(
57 queue=self.sqs_queue,
58 batch_size=10,
59 enabled=True,
60 )
61 self.lbd_func_1.add_event_source(self.sqs_event_source_1)
62
63 # SQS is declared in another stack
64 self.lbd_func_2 = lambda_.Function(
65 self,
66 "LambdaFunction2",
67 function_name=f"{project_name}-2",
68 code=lambda_.Code.from_asset(f"{dir_lambda_app}"),
69 handler=f"lambda_function.lambda_handler",
70 runtime=lambda_.Runtime.PYTHON_3_10,
71 memory_size=128,
72 timeout=cdk.Duration.seconds(3),
73 role=self.iam_role_for_lbd,
74 )
75
76 sqs_queue = sqs.Queue.from_queue_arn(
77 self,
78 "SQSQueueInterface",
79 queue_arn=f"arn:aws:sqs:{cdk.Aws.REGION}:{cdk.Aws.ACCOUNT_ID}:{self.sqs_queue_name}",
80 )
81 self.sqs_event_source_2 = event_source.SqsEventSource(
82 queue=sqs_queue,
83 batch_size=10,
84 enabled=True,
85 )
86 self.lbd_func_2.add_event_source(self.sqs_event_source_2)
87
88
89# ------------------------------------------------------------------------------
90# Config
91aws_profile = "bmt_app_dev_us_east_1"
92project_name = "lbd_cdk_event_demo-sqs"
93# ------------------------------------------------------------------------------
94
95dir_workspace = Path(__file__).absolute().parent
96dir_lambda_app = dir_workspace.joinpath("lambda_app")
97bsm = BotoSesManager(profile_name=aws_profile)
98
99app = cdk.App()
100stack = Stack(app, "MyApp", project_name=project_name)
101
102if __name__ == "__main__":
103 app.synth()
DynamoDB Update#
dynamodb-update.json
1{
2 "Records": [
3 {
4 "eventID": "c4ca4238a0b923820dcc509a6f75849b",
5 "eventName": "INSERT",
6 "eventVersion": "1.1",
7 "eventSource": "aws:dynamodb",
8 "awsRegion": "us-east-1",
9 "dynamodb": {
10 "Keys": {
11 "Id": {
12 "N": "101"
13 }
14 },
15 "NewImage": {
16 "Message": {
17 "S": "New item!"
18 },
19 "Id": {
20 "N": "101"
21 }
22 },
23 "ApproximateCreationDateTime": 1428537600,
24 "SequenceNumber": "4421584500000000017450439091",
25 "SizeBytes": 26,
26 "StreamViewType": "NEW_AND_OLD_IMAGES"
27 },
28 "eventSourceARN": "arn:aws:dynamodb:us-east-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899"
29 },
30 {
31 "eventID": "c81e728d9d4c2f636f067f89cc14862c",
32 "eventName": "MODIFY",
33 "eventVersion": "1.1",
34 "eventSource": "aws:dynamodb",
35 "awsRegion": "us-east-1",
36 "dynamodb": {
37 "Keys": {
38 "Id": {
39 "N": "101"
40 }
41 },
42 "NewImage": {
43 "Message": {
44 "S": "This item has changed"
45 },
46 "Id": {
47 "N": "101"
48 }
49 },
50 "OldImage": {
51 "Message": {
52 "S": "New item!"
53 },
54 "Id": {
55 "N": "101"
56 }
57 },
58 "ApproximateCreationDateTime": 1428537600,
59 "SequenceNumber": "4421584500000000017450439092",
60 "SizeBytes": 59,
61 "StreamViewType": "NEW_AND_OLD_IMAGES"
62 },
63 "eventSourceARN": "arn:aws:dynamodb:us-east-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899"
64 },
65 {
66 "eventID": "eccbc87e4b5ce2fe28308fd9f2a7baf3",
67 "eventName": "REMOVE",
68 "eventVersion": "1.1",
69 "eventSource": "aws:dynamodb",
70 "awsRegion": "us-east-1",
71 "dynamodb": {
72 "Keys": {
73 "Id": {
74 "N": "101"
75 }
76 },
77 "OldImage": {
78 "Message": {
79 "S": "This item has changed"
80 },
81 "Id": {
82 "N": "101"
83 }
84 },
85 "ApproximateCreationDateTime": 1428537600,
86 "SequenceNumber": "4421584500000000017450439093",
87 "SizeBytes": 38,
88 "StreamViewType": "NEW_AND_OLD_IMAGES"
89 },
90 "eventSourceARN": "arn:aws:dynamodb:us-east-1:123456789012:table/ExampleTableWithStream/stream/2015-06-27T00:48:05.899"
91 }
92 ]
93}
Kinesis Get Records#
kinesis-get-records.json
1{
2 "Records": [
3 {
4 "kinesis": {
5 "partitionKey": "partitionKey-03",
6 "kinesisSchemaVersion": "1.0",
7 "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0IDEyMy4=",
8 "sequenceNumber": "49545115243490985018280067714973144582180062593244200961",
9 "approximateArrivalTimestamp": 1428537600
10 },
11 "eventSource": "aws:kinesis",
12 "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961",
13 "invokeIdentityArn": "arn:aws:iam::EXAMPLE",
14 "eventVersion": "1.0",
15 "eventName": "aws:kinesis:record",
16 "eventSourceARN": "arn:aws:kinesis:EXAMPLE",
17 "awsRegion": "us-east-1"
18 }
19 ]
20}