Skip to content

Commit 8fc26bb

Browse files
authored
Merge pull request #20 from SatoshiMoriyama/add-apigateway-lambda-tutorial
Add tutorial 087: API Gateway Lambda Integration
2 parents 47e5d16 + a36ab20 commit 8fc26bb

4 files changed

Lines changed: 558 additions & 1 deletion

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# API Gateway Lambda Integration Tutorial
2+
3+
This tutorial demonstrates how to create a REST API with Lambda proxy integration using the AWS CLI.
4+
5+
## Files
6+
7+
- `apigateway-lambda-integration.md` - Step-by-step tutorial
8+
- `apigateway-lambda-integration.sh` - Automated execution script
9+
10+
## Usage
11+
12+
### Manual execution following the tutorial
13+
```bash
14+
# Read the tutorial and execute commands manually
15+
cat apigateway-lambda-integration.md
16+
```
17+
18+
### Automated execution with script
19+
```bash
20+
# Execute all steps automatically
21+
chmod +x apigateway-lambda-integration.sh
22+
./apigateway-lambda-integration.sh
23+
```
24+
25+
## Prerequisites
26+
27+
- AWS CLI configured
28+
- Appropriate IAM permissions
29+
30+
## Security Warning
31+
32+
This tutorial is for learning purposes only and is not production-ready.
33+
34+
### High Risk Issues
35+
36+
- **Public API**: Creates an unauthenticated API accessible to anyone on the internet
37+
- **Overly permissive permissions**: Lambda can be invoked by any API Gateway method/resource
38+
39+
### Medium Risk Issues
40+
41+
- **No input validation**: User inputs are processed without sanitization
42+
- **Information disclosure**: Lambda logs full request data to CloudWatch
43+
- **No rate limiting**: API has no protection against abuse
44+
45+
Before production use, you must:
46+
- Add authentication (AWS_IAM, API keys, or Cognito)
47+
- Implement input validation and sanitization
48+
- Remove debug logging of sensitive data
49+
- Configure rate limiting and throttling
50+
51+
## Resources Created
52+
53+
- Lambda function
54+
- API Gateway REST API
55+
- IAM role
56+
57+
All resources are automatically cleaned up after script execution.
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
# Create a REST API with Lambda proxy integration using the AWS CLI
2+
3+
This tutorial guides you through creating a REST API with Lambda proxy integration using the AWS Command Line Interface (AWS CLI). You'll learn how to create a Lambda function, set up an API Gateway REST API, configure Lambda proxy integration, and test your API endpoints.
4+
5+
Note: This tutorial is for learning purposes only and is not production-ready. For more info, see [README.md](./README.md).
6+
7+
## Prerequisites
8+
9+
Before you begin this tutorial, make sure you have the following:
10+
11+
1. The AWS CLI installed and configured with appropriate credentials
12+
2. Basic familiarity with command line interfaces and REST API concepts
13+
3. Sufficient permissions to create and manage Lambda functions, API Gateway resources, and IAM roles
14+
4. `jq` command-line JSON processor installed (for parsing AWS CLI responses)
15+
- **Alternative**: If `jq` is not available, you can manually extract IDs from the AWS CLI output
16+
17+
**Note**: If you don't have `jq` installed, you can install it using:
18+
- **macOS**: `brew install jq`
19+
- **Ubuntu/Debian**: `sudo apt-get install jq`
20+
- **CentOS/RHEL**: `sudo yum install jq`
21+
22+
## Create an IAM role for Lambda execution
23+
24+
Lambda functions require an execution role that grants them permission to access AWS services and write logs to CloudWatch.
25+
26+
**Create a trust policy document**
27+
28+
```bash
29+
cat > trust-policy.json << 'EOF'
30+
{
31+
"Version": "2012-10-17",
32+
"Statement": [
33+
{
34+
"Effect": "Allow",
35+
"Principal": {
36+
"Service": "lambda.amazonaws.com"
37+
},
38+
"Action": "sts:AssumeRole"
39+
}
40+
]
41+
}
42+
EOF
43+
```
44+
45+
**Create the IAM role**
46+
47+
```bash
48+
aws iam create-role \
49+
--role-name GetStartedLambdaBasicExecutionRole \
50+
--assume-role-policy-document file://trust-policy.json
51+
```
52+
53+
**Attach the basic execution policy**
54+
55+
```bash
56+
aws iam attach-role-policy \
57+
--role-name GetStartedLambdaBasicExecutionRole \
58+
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
59+
```
60+
61+
## Create and deploy a Lambda function
62+
63+
Create a Lambda function that responds to API Gateway requests with a personalized greeting.
64+
65+
**Create the Lambda function code**
66+
67+
```bash
68+
cat > lambda_function.py << 'EOF'
69+
import json
70+
71+
def lambda_handler(event, context):
72+
print(event)
73+
74+
greeter = 'World'
75+
76+
try:
77+
if (event['queryStringParameters']) and (event['queryStringParameters']['greeter']) and (
78+
event['queryStringParameters']['greeter'] is not None):
79+
greeter = event['queryStringParameters']['greeter']
80+
except KeyError:
81+
print('No greeter')
82+
83+
try:
84+
if (event['multiValueHeaders']) and (event['multiValueHeaders']['greeter']) and (
85+
event['multiValueHeaders']['greeter'] is not None):
86+
greeter = " and ".join(event['multiValueHeaders']['greeter'])
87+
except KeyError:
88+
print('No greeter')
89+
90+
try:
91+
if (event['headers']) and (event['headers']['greeter']) and (
92+
event['headers']['greeter'] is not None):
93+
greeter = event['headers']['greeter']
94+
except KeyError:
95+
print('No greeter')
96+
97+
if (event['body']) and (event['body'] is not None):
98+
body = json.loads(event['body'])
99+
try:
100+
if (body['greeter']) and (body['greeter'] is not None):
101+
greeter = body['greeter']
102+
except KeyError:
103+
print('No greeter')
104+
105+
res = {
106+
"statusCode": 200,
107+
"headers": {
108+
"Content-Type": "*/*"
109+
},
110+
"body": "Hello, " + greeter + "!"
111+
}
112+
113+
return res
114+
EOF
115+
```
116+
117+
**Create a deployment package**
118+
119+
```bash
120+
zip function.zip lambda_function.py
121+
```
122+
123+
**Create the Lambda function**
124+
125+
```bash
126+
aws lambda create-function \
127+
--function-name GetStartedLambdaProxyIntegration \
128+
--runtime python3.12 \
129+
--role arn:aws:iam::$(aws sts get-caller-identity --query Account --output text):role/GetStartedLambdaBasicExecutionRole \
130+
--handler lambda_function.lambda_handler \
131+
--zip-file fileb://function.zip
132+
```
133+
134+
## Create a REST API
135+
136+
Create a REST API in API Gateway and set up the necessary resources and methods.
137+
138+
**Create the REST API**
139+
140+
```bash
141+
# Create API and capture response
142+
API_RESPONSE=$(aws apigateway create-rest-api \
143+
--name LambdaProxyAPI \
144+
--endpoint-configuration types=REGIONAL)
145+
146+
# Extract API ID and root resource ID from response
147+
API_ID=$(echo $API_RESPONSE | jq -r '.id')
148+
ROOT_RESOURCE_ID=$(echo $API_RESPONSE | jq -r '.rootResourceId')
149+
150+
echo "API ID: $API_ID"
151+
echo "Root Resource ID: $ROOT_RESOURCE_ID"
152+
```
153+
154+
**Create a resource**
155+
156+
```bash
157+
# Create resource and capture response
158+
RESOURCE_RESPONSE=$(aws apigateway create-resource \
159+
--rest-api-id $API_ID \
160+
--parent-id $ROOT_RESOURCE_ID \
161+
--path-part helloworld)
162+
163+
# Extract resource ID from response
164+
RESOURCE_ID=$(echo $RESOURCE_RESPONSE | jq -r '.id')
165+
166+
echo "Resource ID: $RESOURCE_ID"
167+
```
168+
169+
## Configure Lambda proxy integration
170+
171+
Create an ANY method on your resource and configure it to use Lambda proxy integration.
172+
173+
**Create an ANY method**
174+
175+
```bash
176+
aws apigateway put-method \
177+
--rest-api-id $API_ID \
178+
--resource-id $RESOURCE_ID \
179+
--http-method ANY \
180+
--authorization-type NONE
181+
```
182+
183+
**Set up Lambda proxy integration**
184+
185+
```bash
186+
# Get account ID and region
187+
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
188+
REGION=$(aws configure get region)
189+
190+
# If region is not set in config, use default
191+
if [ -z "$REGION" ]; then
192+
REGION="us-east-1"
193+
fi
194+
195+
echo "Account ID: $ACCOUNT_ID"
196+
echo "Region: $REGION"
197+
198+
aws apigateway put-integration \
199+
--rest-api-id $API_ID \
200+
--resource-id $RESOURCE_ID \
201+
--http-method ANY \
202+
--type AWS_PROXY \
203+
--integration-http-method POST \
204+
--uri "arn:aws:apigateway:${REGION}:lambda:path/2015-03-31/functions/arn:aws:lambda:${REGION}:${ACCOUNT_ID}:function:GetStartedLambdaProxyIntegration/invocations"
205+
```
206+
207+
**Grant API Gateway permission to invoke Lambda**
208+
209+
```bash
210+
aws lambda add-permission \
211+
--function-name GetStartedLambdaProxyIntegration \
212+
--statement-id apigateway-invoke \
213+
--action lambda:InvokeFunction \
214+
--principal apigateway.amazonaws.com \
215+
--source-arn "arn:aws:execute-api:$REGION:$ACCOUNT_ID:$API_ID/*/*"
216+
```
217+
218+
## Deploy and test the API
219+
220+
Deploy your API to make it accessible and test it using different methods.
221+
222+
**Deploy the API**
223+
224+
```bash
225+
aws apigateway create-deployment \
226+
--rest-api-id $API_ID \
227+
--stage-name test
228+
```
229+
230+
**Test the API**
231+
232+
Get the invoke URL and test with different methods:
233+
234+
```bash
235+
# Construct the invoke URL
236+
INVOKE_URL="https://$API_ID.execute-api.$REGION.amazonaws.com/test/helloworld"
237+
echo "Invoke URL: $INVOKE_URL"
238+
239+
# Test with query parameter
240+
echo "Testing with query parameter..."
241+
curl -X GET "$INVOKE_URL?greeter=John"
242+
243+
# Test with header
244+
echo "Testing with header..."
245+
curl -X GET "$INVOKE_URL" \
246+
-H 'content-type: application/json' \
247+
-H 'greeter: John'
248+
249+
# Test with body
250+
echo "Testing with body..."
251+
curl -X POST "$INVOKE_URL" \
252+
-H 'content-type: application/json' \
253+
-d '{ "greeter": "John" }'
254+
```
255+
256+
All tests should return: `Hello, John!`
257+
258+
## Clean up resources
259+
260+
To avoid ongoing charges, delete the resources you created:
261+
262+
```bash
263+
# Delete API
264+
aws apigateway delete-rest-api --rest-api-id $API_ID
265+
266+
# Delete Lambda function
267+
aws lambda delete-function --function-name GetStartedLambdaProxyIntegration
268+
269+
# Delete IAM role
270+
aws iam detach-role-policy \
271+
--role-name GetStartedLambdaBasicExecutionRole \
272+
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
273+
274+
aws iam delete-role --role-name GetStartedLambdaBasicExecutionRole
275+
276+
# Clean up local files
277+
rm lambda_function.py function.zip trust-policy.json
278+
```
279+
280+
## Next steps
281+
282+
Now that you've successfully created a REST API with Lambda proxy integration, you can explore additional features:
283+
284+
- Add authentication and authorization to your APIs
285+
- Implement request validation and transformation
286+
- Monitor your APIs with CloudWatch
287+
- Use Lambda layers to share code between functions

0 commit comments

Comments
 (0)