Skip to content

Commit aefc6b5

Browse files
authored
Merge branch 'aws-samples:main' into sidd130-feature-sqs-lambda-s3
2 parents 3c664d5 + c63b518 commit aefc6b5

File tree

213 files changed

+2086
-282
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

213 files changed

+2086
-282
lines changed

alb-lambda-cdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
"typescript": "~3.9.7"
2222
},
2323
"dependencies": {
24-
"aws-cdk-lib": "2.177.0",
24+
"aws-cdk-lib": "^2.185.0",
2525
"constructs": "^10.0.0",
2626
"source-map-support": "^0.5.21"
2727
}

amplify-codecommit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"jest": "^29.5.0"
1515
},
1616
"dependencies": {
17-
"aws-cdk-lib": "^2.85.0",
17+
"aws-cdk-lib": "^2.185.0",
1818
"constructs": "^10.2.63"
1919
}
2020
}

api-gateway-cors-whitelist-cdk/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
},
2727
"dependencies": {
2828
"@aws-cdk/aws-lambda-go-alpha": "^2.66.1-alpha.0",
29-
"aws-cdk-lib": "2.177.0",
29+
"aws-cdk-lib": "^2.185.0",
3030
"constructs": "^10.0.0",
3131
"source-map-support": "^0.5.21"
3232
}

apigw-data-validation-tf/README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Amazon API Gateway data validation models
2+
3+
This pattern creates an Amazon API Gateway that handles simple data validation at the endpoint without invoking the Lambda function when the data validation fails.
4+
5+
Learn more about this pattern at Serverless Land Patterns: [https://serverlessland.com/patterns/apigw-custom-resource-policy](https://serverlessland.com/patterns/apigw-custom-resource-policy)
6+
7+
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.
8+
9+
## Requirements
10+
11+
* [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.
12+
* [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html) installed and configured
13+
* [Git Installed](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
14+
* [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli?in=terraform/aws-get-started) installed
15+
16+
## Deployment Instructions
17+
18+
1. Create a new directory, navigate to that directory in a terminal and clone the repository:
19+
```
20+
git clone https://github.com/aws-samples/serverless-patterns
21+
```
22+
1. Change directory to this pattern's directory
23+
```
24+
cd serverless-patterns/apigw-data-validation-tf
25+
```
26+
1. From the command line, initialize Terraform to downloads and install the providers defined in the configuration:
27+
```
28+
terraform init
29+
```
30+
1. From the command line, apply the configuration in the main.tf file:
31+
```
32+
terraform apply
33+
```
34+
1. Note the outputs from the deployment process. These contain the resource names and/or ARNs which are used for testing.
35+
36+
## API Endpoint
37+
38+
After running `terraform apply`, you will see outputs including the API endpoint URL. You'll need this URL for testing. The output will look similar to:
39+
```
40+
api_endpoint = "https://xxxxx.execute-api.us-east-1.amazonaws.com/Prod"
41+
```
42+
43+
Note: When testing, append `/123?order=ORD12345` to this base URL. For example, if your API endpoint is `https://xxxxx.execute-api.us-east-1.amazonaws.com/Prod`, your full testing URL would be:
44+
```
45+
`https://xxxxx.execute-api.us-east-1.amazonaws.com/Prod/123?order=ORD12345`
46+
```
47+
48+
## How it works
49+
50+
The data model is declared in the API Gateway resource. The Lambda function then requires the request body to be validated against this model.
51+
52+
## Testing
53+
54+
After the application is deployed try the following scenarios.
55+
56+
### Create a new vehicle entering valid data:
57+
```
58+
curl --location --request POST 'https://t9nde3gpp2.execute-api.us-east-1.amazonaws.com/Prod/123?order=ORD12345' \
59+
--header 'Content-Type: application/json' \
60+
--header 'custom-agent: MyMobileApp/1.0' \
61+
--data-raw '{
62+
"make":"MINI",
63+
"model":"Countryman",
64+
"year": 2010
65+
}'
66+
```
67+
Expected response: `{"message": "Data validation succeded", "data": {"make": "MINI", "model": "Countryman", "year": 2010}}`
68+
### Now enter a year less than 2010
69+
```
70+
curl --location --request POST 'https://t9nde3gpp2.execute-api.us-east-1.amazonaws.com/Prod/123?order=ORD12345' \
71+
--header 'Content-Type: application/json' \
72+
--header 'custom-agent: MyMobileApp/1.0' \
73+
--data-raw '{
74+
"make":"MINI",
75+
"model":"Countryman",
76+
"year": 2002
77+
}'
78+
```
79+
Expected response: `{"message": "Invalid request body"}`
80+
81+
Try some other combinations and see what you get!
82+
83+
## Cleanup
84+
85+
1. Change directory to the pattern directory:
86+
```
87+
cd apigw-data-validation-tf
88+
```
89+
1. Delete all created resources by Terraform
90+
```bash
91+
terraform destroy
92+
```
93+
1. Confirm all created resources has been deleted
94+
```bash
95+
terraform show
96+
```
97+
98+
----
99+
Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
100+
101+
SPDX-License-Identifier: MIT-0
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"title": "Amazon API Gateway data validation",
3+
"description": "Creates an Amazon API Gateway with request validation, rejecting invalid requests before AWS Lambda invocation using model schema validation.",
4+
"language": "YAML",
5+
"level": "300",
6+
"framework": "Terraform",
7+
"introBox": {
8+
"headline": "How it works",
9+
"text": [
10+
"The data model is declared in the API Gateway resource. The Lambda function then requires the request body to be validated against this model."
11+
]
12+
},
13+
"gitHub": {
14+
"template": {
15+
"repoURL": "https://github.com/aws-samples/serverless-patterns/tree/main/apigw-data-validation-tf",
16+
"templateURL": "serverless-patterns/apigw-data-validation-tf",
17+
"projectFolder": "apigw-data-validation-tf",
18+
"templateFile": "main.tf"
19+
}
20+
},
21+
"resources": {
22+
"bullets": [
23+
{
24+
"text": "Amazon API Gateway model example",
25+
"link": "https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-api.html#sam-api-models"
26+
},
27+
{
28+
"text": "JSON Schema",
29+
"link": "https://datatracker.ietf.org/doc/html/draft-zyp-json-schema-04#section-4.1"
30+
}
31+
]
32+
},
33+
"deploy": {
34+
"text": [
35+
"terraform init",
36+
"terraform apply"
37+
]
38+
},
39+
"testing": {
40+
"text": [
41+
"See the Github repo for detailed testing instructions."
42+
]
43+
},
44+
"cleanup": {
45+
"text": [
46+
"<code>terraform destroy</code>",
47+
"terraform show"
48+
]
49+
},
50+
"authors": [
51+
{
52+
"name": "Makendran G",
53+
"image": "https://drive.google.com/file/d/1mUObnbmn52UWL-Zn39EpgpneiBNv3LCN/view?usp=sharing",
54+
"bio": "Cloud Support Engineer @ AWS",
55+
"linkedin": "makendran",
56+
"twitter": "@MakendranG"
57+
}
58+
]
59+
}

apigw-data-validation-tf/main.tf

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
# Provider configuration
2+
provider "aws" {
3+
region = "us-east-1" # Change this to your desired region
4+
}
5+
6+
terraform {
7+
required_providers {
8+
aws = {
9+
source = "hashicorp/aws"
10+
version = "~> 4.0"
11+
}
12+
archive = {
13+
source = "hashicorp/archive"
14+
version = "~> 2.0"
15+
}
16+
null = {
17+
source = "hashicorp/null"
18+
version = "~> 3.0"
19+
}
20+
}
21+
}
22+
23+
# Archive the Lambda function code
24+
data "archive_file" "lambda_zip" {
25+
type = "zip"
26+
source_dir = "${path.module}/src"
27+
output_path = "${path.module}/lambda.zip"
28+
}
29+
30+
# API Gateway REST API
31+
resource "aws_api_gateway_rest_api" "main_api" {
32+
name = "validation-api"
33+
description = "API Gateway with data validation"
34+
35+
body = jsonencode({
36+
openapi = "3.0.1"
37+
info = {
38+
title = "validation-api"
39+
version = "1.0"
40+
}
41+
components = {
42+
schemas = {
43+
Vehicle = {
44+
type = "object"
45+
required = ["make", "model", "year"]
46+
properties = {
47+
make = {
48+
type = "string"
49+
}
50+
model = {
51+
type = "string"
52+
}
53+
year = {
54+
type = "integer"
55+
minimum = 2010
56+
}
57+
color = {
58+
type = "string"
59+
enum = ["green", "red", "blue"]
60+
}
61+
}
62+
}
63+
}
64+
}
65+
})
66+
}
67+
68+
# Lambda Function
69+
resource "aws_lambda_function" "process_function" {
70+
filename = data.archive_file.lambda_zip.output_path
71+
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
72+
function_name = "process-function"
73+
role = aws_iam_role.lambda_role.arn
74+
handler = "app.lambda_handler"
75+
runtime = "python3.13"
76+
architectures = ["arm64"]
77+
timeout = 3
78+
79+
depends_on = [
80+
data.archive_file.lambda_zip
81+
]
82+
}
83+
84+
# IAM Role for Lambda
85+
resource "aws_iam_role" "lambda_role" {
86+
name = "process_function_role"
87+
88+
assume_role_policy = jsonencode({
89+
Version = "2012-10-17"
90+
Statement = [
91+
{
92+
Action = "sts:AssumeRole"
93+
Effect = "Allow"
94+
Principal = {
95+
Service = "lambda.amazonaws.com"
96+
}
97+
}
98+
]
99+
})
100+
}
101+
102+
# Basic Lambda execution policy
103+
resource "aws_iam_role_policy_attachment" "lambda_basic" {
104+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
105+
role = aws_iam_role.lambda_role.name
106+
}
107+
108+
# API Gateway Resource
109+
resource "aws_api_gateway_resource" "api_resource" {
110+
rest_api_id = aws_api_gateway_rest_api.main_api.id
111+
parent_id = aws_api_gateway_rest_api.main_api.root_resource_id
112+
path_part = "{id}"
113+
}
114+
115+
# API Gateway Method
116+
resource "aws_api_gateway_method" "api_method" {
117+
rest_api_id = aws_api_gateway_rest_api.main_api.id
118+
resource_id = aws_api_gateway_resource.api_resource.id
119+
http_method = "POST"
120+
authorization = "NONE"
121+
122+
request_parameters = {
123+
"method.request.querystring.order" = true
124+
"method.request.header.custom-agent" = true
125+
}
126+
127+
request_validator_id = aws_api_gateway_request_validator.validator.id
128+
request_models = {
129+
"application/json" = aws_api_gateway_model.vehicle_model.name
130+
}
131+
}
132+
133+
# Request Validator
134+
resource "aws_api_gateway_request_validator" "validator" {
135+
name = "validator"
136+
rest_api_id = aws_api_gateway_rest_api.main_api.id
137+
validate_request_body = true
138+
validate_request_parameters = true
139+
}
140+
141+
# Vehicle Model
142+
resource "aws_api_gateway_model" "vehicle_model" {
143+
rest_api_id = aws_api_gateway_rest_api.main_api.id
144+
name = "Vehicle"
145+
description = "Vehicle model for validation"
146+
content_type = "application/json"
147+
148+
schema = jsonencode({
149+
type = "object"
150+
required = ["make", "model", "year"]
151+
properties = {
152+
make = {
153+
type = "string"
154+
}
155+
model = {
156+
type = "string"
157+
}
158+
year = {
159+
type = "integer"
160+
minimum = 2010
161+
}
162+
color = {
163+
type = "string"
164+
enum = ["green", "red", "blue"]
165+
}
166+
}
167+
})
168+
}
169+
170+
# Lambda Integration
171+
resource "aws_api_gateway_integration" "lambda_integration" {
172+
rest_api_id = aws_api_gateway_rest_api.main_api.id
173+
resource_id = aws_api_gateway_resource.api_resource.id
174+
http_method = aws_api_gateway_method.api_method.http_method
175+
type = "AWS_PROXY"
176+
integration_http_method = "POST"
177+
uri = aws_lambda_function.process_function.invoke_arn
178+
}
179+
180+
# Lambda Permission
181+
resource "aws_lambda_permission" "api_gateway" {
182+
statement_id = "AllowAPIGatewayInvoke"
183+
action = "lambda:InvokeFunction"
184+
function_name = aws_lambda_function.process_function.function_name
185+
principal = "apigateway.amazonaws.com"
186+
source_arn = "${aws_api_gateway_rest_api.main_api.execution_arn}/*/*/*"
187+
}
188+
189+
# API Gateway Deployment
190+
resource "aws_api_gateway_deployment" "api_deployment" {
191+
rest_api_id = aws_api_gateway_rest_api.main_api.id
192+
depends_on = [aws_api_gateway_integration.lambda_integration]
193+
}
194+
195+
# API Gateway Stage
196+
resource "aws_api_gateway_stage" "prod" {
197+
deployment_id = aws_api_gateway_deployment.api_deployment.id
198+
rest_api_id = aws_api_gateway_rest_api.main_api.id
199+
stage_name = "Prod"
200+
}
201+
202+
# Output
203+
output "api_endpoint" {
204+
description = "API Gateway endpoint URL for Prod stage"
205+
value = "${aws_api_gateway_stage.prod.invoke_url}"
206+
}

0 commit comments

Comments
 (0)