Skip to content

Commit cf1411c

Browse files
committed
CDK implementation of Lambda to SNS pattern
1 parent 5a92562 commit cf1411c

File tree

5 files changed

+226
-0
lines changed

5 files changed

+226
-0
lines changed

lambda-sns-cdk/README.md

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
2+
# Lambda to Amazon SNS (CDK)
3+
4+
This pattern deploys an SNS Topic and a Lambda Function that will send a custom message to the topic once triggered.
5+
The CDK application contains the minimum IAM resources required to run the application.
6+
7+
Learn more about this pattern at: https://serverlessland.com/patterns/lambda-sns-cdk
8+
9+
Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the AWS Pricing page for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
10+
11+
## Requirements
12+
13+
* [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and log in. The IAM user that you use must have sufficient permissions to make necessary AWS service calls and manage AWS resources.
14+
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
15+
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
16+
* [AWS Cloud Development Kit](https://docs.aws.amazon.com/cdk/latest/guide/getting_started.html) (AWS CDK >= 1.124.0) Installed
17+
18+
## Language
19+
Python
20+
21+
## Framework
22+
CDK
23+
24+
## Services From/To
25+
AWS Lambda to Amazon SNS
26+
27+
## Deployment Instructions
28+
29+
1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
30+
```bash
31+
git clone https://github.com/aws-samples/serverless-patterns
32+
```
33+
2. Change directory to the pattern directory:
34+
```bash
35+
cd lambda-sns-cdk/src
36+
```
37+
3. Create a virtual environment for python:
38+
```bash
39+
python3 -m venv .venv
40+
```
41+
4. Activate the virtual environment:
42+
```bash
43+
source .venv/bin/activate
44+
```
45+
46+
If you are in Windows platform, you would activate the virtualenv like this:
47+
48+
```
49+
% .venv\Scripts\activate.bat
50+
```
51+
52+
5. Install python modules:
53+
```bash
54+
python3 -m pip install -r requirements.txt
55+
```
56+
57+
If the previous command doesn't work, try this one bellow:
58+
```bash
59+
pip3 install -r requirements.txt
60+
```
61+
6. From the command line, use CDK to synthesize the CloudFormation template and check for errors:
62+
```bash
63+
cdk synth
64+
```
65+
7. From the command line, use CDK to deploy the stack:
66+
```bash
67+
cdk deploy
68+
```
69+
8. Note the outputs from the CDK deployment process. These contain the resource names and/or ARNs which are used for testing.
70+
71+
72+
73+
## How it works
74+
75+
The CDK stack deploys the resources and the IAM permissions required to run the application.
76+
77+
The SNS topic specified in the stack app.py will be the target of the Lambda Function. The function reads the event to determine which SNS topic will receive the message body.
78+
79+
80+
## Testing
81+
82+
Tests can be done using aws-cli or directly on the console. Follow the steps below to test from the command line.
83+
84+
85+
1. Invoke the lambda function with a sample message
86+
87+
````
88+
aws lambda invoke --function-name <FUNCTION_NAME> --cli-binary-format raw-in-base64-out --payload '{ "topic_arn": "<TOPIC_ARN>", "message": "Hello, SNS topic!" }' response.json"
89+
````
90+
91+
2. A successful publish to the topic will cause the Lambda to return a 200 status code. Go to CloudWatch and verify the related Log Group. You should see an Info level log with a success message and the Message ID of the successfully published payload.
92+
93+
94+
95+
## Cleanup
96+
97+
1. Delete the stack
98+
```bash
99+
aws cloudformation delete-stack --stack-name STACK_NAME
100+
```
101+
1. Confirm the stack has been deleted
102+
```bash
103+
aws cloudformation list-stacks --query "StackSummaries[?contains(StackName,'STACK_NAME')].StackStatus"
104+
```
105+
106+
107+
108+
## Tutorial
109+
See [this useful workshop](https://cdkworkshop.com/30-python.html) on working with the AWS CDK for Python projects.
110+
111+
## Useful commands
112+
113+
* `cdk ls` list all stacks in the app
114+
* `cdk synth` emits the synthesized CloudFormation template
115+
* `cdk deploy` deploy this stack to your default AWS account/region
116+
* `cdk diff` compare deployed stack with current state
117+
* `cdk docs` open CDK documentation
118+
119+
120+
Enjoy!

lambda-sns-cdk/src/app.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env python3
2+
from aws_cdk import (
3+
aws_lambda as _lambda,
4+
aws_logs as logs,
5+
aws_sns as sns,
6+
core as cdk
7+
)
8+
9+
from constructs import Construct
10+
11+
class LambdaSnsCdkStack(cdk.Stack):
12+
13+
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
14+
super().__init__(scope, construct_id, **kwargs)
15+
16+
# Create SNS Topic
17+
# SNS topic
18+
topic = sns.Topic(self, 'sns-to-lambda-topic',
19+
display_name='My SNS topic')
20+
21+
# Create Lambda function
22+
lambdaFn = _lambda.Function(self, "SNSPublisher",
23+
runtime=_lambda.Runtime.PYTHON_3_9,
24+
code=_lambda.Code.from_asset("lambda"),
25+
handler="handler.main",
26+
timeout=cdk.Duration.seconds(10))
27+
28+
# Set Lambda Logs Retention and Removal Policy
29+
logs.LogGroup(
30+
self,
31+
'logs',
32+
log_group_name=f"/aws/lambda/{lambdaFn.function_name}",
33+
removal_policy=cdk.RemovalPolicy.DESTROY,
34+
retention=logs.RetentionDays.ONE_DAY
35+
)
36+
37+
# Grant publish to lambda function
38+
topic.grant_publish(lambdaFn)
39+
40+
cdk.CfnOutput(self, 'snsTopicArn',
41+
value=topic.topic_arn,
42+
description='The arn of the SNS topic')
43+
cdk.CfnOutput(self, 'functionName',
44+
value=lambdaFn.function_name,
45+
description='The name of the handler function')
46+
47+
48+
app = cdk.App()
49+
LambdaSnsCdkStack(app, "LambdaSnsCdkStack")
50+
app.synth()

lambda-sns-cdk/src/cdk.json

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"app": "python3 app.py",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"requirements.txt",
11+
"python/__pycache__"
12+
]
13+
},
14+
"context": {
15+
"@aws-cdk/aws-apigateway:usagePlanKeyOrderInsensitiveId": true,
16+
"@aws-cdk/core:stackRelativeExports": true,
17+
"@aws-cdk/aws-rds:lowercaseDbIdentifier": true,
18+
"@aws-cdk/aws-lambda:recognizeVersionProps": true,
19+
"@aws-cdk/aws-cloudfront:defaultSecurityPolicyTLSv1.2_2021": true
20+
}
21+
}

lambda-sns-cdk/src/lambda/handler.py

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import logging
2+
import json
3+
import boto3
4+
5+
from botocore.exceptions import ClientError
6+
7+
def main(event, context):
8+
logger = logging.getLogger(__name__)
9+
logger.setLevel(logging.INFO)
10+
logger.info("request: " + json.dumps(event))
11+
12+
sns_client = boto3.client("sns")
13+
topic_arn = event['topic_arn']
14+
15+
16+
try:
17+
sent_message = sns_client.publish(
18+
TopicArn=topic_arn,
19+
Message=json.dumps(event['message'])
20+
)
21+
22+
if sent_message is not None:
23+
logger.info(f"Success - Message ID: {sent_message['MessageId']}")
24+
return {
25+
"statusCode": 200,
26+
"body": json.dumps(event['message'])
27+
}
28+
29+
except ClientError as e:
30+
logger.error(e)
31+
return None

lambda-sns-cdk/src/requirements.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
aws-cdk.core
2+
aws-cdk.aws-lambda
3+
aws-cdk.aws-logs
4+
aws-cdk.aws-sns

0 commit comments

Comments
 (0)