Skip to content

Commit 8f79304

Browse files
authored
Merge pull request #2389 from mayafrieman/mayafrieman-feature-apigw-dynamodb-python-cdk
New serverless pattern - apigw dynamodb python cdk
2 parents 7836880 + a073f03 commit 8f79304

23 files changed

+1085
-0
lines changed
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
2+
# API Gateway direct integration to DynamoDB
3+
4+
This pattern shows how to create an API Gateway with direct integration to DynamoDB.
5+
The pattern showcase transformation of request/response using VTL and CDK and implement examples for using Cognito, Lambda authorizer and API keys.
6+
7+
Learn more about this pattern at Serverless Land Patterns: [Serverless Land Patterns](https://serverlessland.com/patterns/apigw-dynamodb-python-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](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in this example.
10+
11+
![alt text](image.png)
12+
13+
## Requirements
14+
15+
* [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.
16+
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
17+
* [AWS Cloud Development Kit](https://docs.aws.amazon.com/cdk/latest/guide/cli.html) (AWS CDK) installed
18+
19+
## Deployment Instructions
20+
21+
1. Create a new directory, navigate to that directory in a terminal and clone the GitHub repository:
22+
```
23+
git clone https://github.com/aws-samples/serverless-patterns/
24+
```
25+
2. Change directory
26+
```
27+
cd serverless-patterns/apigw-dynamodb-python-cdk
28+
```
29+
3. To manually create a virtualenv on MacOS and Linux:
30+
```
31+
python3 -m venv .venv
32+
```
33+
4. After the init process completes and the virtualenv is created, you can use the following to activate virtualenv.
34+
```
35+
source .venv/bin/activate
36+
```
37+
6. After activating your virtual environment for the first time, install the app's standard dependencies:
38+
```
39+
python -m pip install -r requirements.txt
40+
```
41+
7. Install jwt package for Lambda:
42+
```
43+
cd src; pip install pyjwt --target .
44+
```
45+
8. Zip the Lambda function and dependencies
46+
```
47+
zip -r lambda.zip . ; cd
48+
```
49+
9. To generate a cloudformation templates (optional)
50+
```
51+
cdk synth
52+
```
53+
10. To deploy AWS resources as a CDK project
54+
```
55+
cdk deploy
56+
```
57+
58+
## How it works
59+
At the end of the deployment the CDK output will list stack outputs, and an API Gateway URL. In the customer's AWS account, a REST API along with an authorizer, Cognito user pool, and a DynamoDB table will be created.
60+
Put resource - uses Lambda authorizer to authenticate the client and send allow/deny to API Gateway.
61+
Get resource - uses API key to control the rate limit. Need to provide valid key for the request with x-api-key header.
62+
Delete resource - uses Cognito to authenticate the client. Cognito token need to be provided with Authorization header.
63+
64+
## Testing
65+
1. Run pytest
66+
```
67+
pytest tests/test_apigw_dynamodb_python_stack.py
68+
```
69+
## Cleanup
70+
71+
1. Delete the stack
72+
```bash
73+
cdk destroy
74+
```
75+
1. Confirm the stack has been deleted
76+
```bash
77+
cdk list
78+
```
79+
----
80+
Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
81+
82+
SPDX-License-Identifier: MIT-0
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
{
2+
"title": "API Gateway direct integration to DynamoDB",
3+
"description": "Direct integration with API Gateway to DynamoDB with transformation using VTL and CDK and examples for Cognito, Lambda authorizer and API keys.",
4+
"language": "Python",
5+
"level": "300",
6+
"framework": "CDK",
7+
"introBox": {
8+
"headline": "How it works",
9+
"text": [
10+
"This pattern shows how to create an API Gateway with direct integration to DynamoDB.",
11+
"The pettern showcase transformation of request/response using VTL and CDK and implement examples for using Cognito, Lambda authorizer and API keys."
12+
]
13+
},
14+
"gitHub": {
15+
"template": {
16+
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-dynamodb-python-cdk",
17+
"templateURL": "serverless-patterns/apigw-dynamodb-python-cdk",
18+
"projectFolder": "apigw-dynamodb-python-cdk",
19+
"templateFile": "apigw_dynamodb_python_cdk_stack.py"
20+
}
21+
},
22+
"resources": {
23+
"bullets": [
24+
{
25+
"text": "API Gateway Integrations",
26+
"link": "https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-integration-settings.html"
27+
}
28+
]
29+
},
30+
"deploy": {
31+
"text": [
32+
"cdk deploy"
33+
]
34+
},
35+
"testing": {
36+
"text": [
37+
"See the GitHub repo for detailed testing instructions."
38+
]
39+
},
40+
"cleanup": {
41+
"text": [
42+
"Delete the stack: <code>cdk delete</code>."
43+
]
44+
},
45+
"authors": [
46+
{
47+
"name": "Maya Morav Freiman",
48+
"image": "https://avatars.githubusercontent.com/u/11615439?v=4",
49+
"bio": "Technical Account Manager at AWS",
50+
"linkedin": "mayaaws"
51+
}
52+
],
53+
"patternArch": {
54+
"icon1": {
55+
"x": 20,
56+
"y": 50,
57+
"service": "apigw",
58+
"label": "API Gateway REST API"
59+
},
60+
"icon2": {
61+
"x": 80,
62+
"y": 50,
63+
"service": "dynamodb",
64+
"label": "Amazon DynamoDB"
65+
},
66+
"line1": {
67+
"from": "icon1",
68+
"to": "icon2"
69+
}
70+
}
71+
}

apigw-dynamodb-python-cdk/apigw_dynamodb_python_cdk/__init__.py

Whitespace-only changes.
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from constructs import Construct
2+
import aws_cdk.aws_apigateway as apigateway
3+
4+
5+
class UsagePlanConstruct(Construct):
6+
def __init__(self, scope: Construct, id: str, apigateway_construct, plan_name, plan_config ,**kwargs) -> None:
7+
super().__init__(scope, id, **kwargs)
8+
9+
# Map the period of the usage plan from the config to apigateway.Period.XXX
10+
period_enum = self.get_period_enum(plan_config['quota']['period'])
11+
12+
# Create usage plan dynamically using the context data
13+
usage_plan = apigateway_construct.api.add_usage_plan(plan_name,
14+
name=plan_name,
15+
throttle=apigateway.ThrottleSettings(
16+
rate_limit=plan_config['throttle']['rate_limit'],
17+
burst_limit=plan_config['throttle']['burst_limit']
18+
),
19+
quota=apigateway.QuotaSettings(
20+
limit=plan_config['quota']['limit'],
21+
period=period_enum
22+
)
23+
)
24+
25+
# Create API key
26+
api_key = apigateway.ApiKey(self, f"ApiKey-{plan_name}",
27+
api_key_name=f"ApiKey-{plan_name}")
28+
self.api_key_id = api_key.key_id
29+
usage_plan.add_api_key(api_key)
30+
31+
# If method is configured in the context assign the API key to the relevant API method
32+
if plan_config['method']:
33+
def get_method(method_name):
34+
method_mapping = { # Change the method to fit your API
35+
"GET": apigateway_construct.get_method,
36+
"POST": apigateway_construct.put_method,
37+
"DELETE": apigateway_construct.delete_method
38+
}
39+
return method_mapping.get(method_name.upper())
40+
usage_plan.add_api_stage(
41+
stage=apigateway_construct.api.deployment_stage,
42+
throttle=[apigateway.ThrottlingPerMethod(
43+
method=get_method(plan_config['method']),
44+
throttle=apigateway.ThrottleSettings(
45+
rate_limit=100,
46+
burst_limit=1
47+
))]
48+
)
49+
50+
51+
52+
53+
@staticmethod
54+
def get_period_enum(period: str) -> apigateway.Period:
55+
period_mapping = {
56+
"DAY": apigateway.Period.DAY,
57+
"WEEK": apigateway.Period.WEEK,
58+
"MONTH": apigateway.Period.MONTH
59+
}
60+
return period_mapping.get(period.upper())
61+
62+

0 commit comments

Comments
 (0)