API Gateway + Lambda + AWS CLI
-
Create an API Gateway and Lambda from the CLI.
-
Create an API Gateway from the CLI is much more complex than going through the web interface. But if you want to create a script and automate some tasks, you will have to deal with it.
Install and setup the code
Get the code from this github repository :
# download the code
$ git clone \
--depth 1 \
https://github.com/jeromedecoster/aws-apigateway-lambda-cli.git \
/tmp/aws
# cd
$ cd /tmp/aws
To setup the project, you must edit the settings file first :
$ cat settings.sample.sh
# Project
AWS_ID=
AWS_REGION=eu-west-3
# Lambda
LAMBDA_FUNCTION_NAME=aws-apigateway-lamdba-cli
LAMBDA_FUNCTION_ARN=
# ...
You can change some values, but the most important thing is to choose your region. The default value is :
- AWS_REGION :
eu-west-3
After that you can execute the 1-setup.sh script. This will create the settings.sh
file :
# execute the setup
$ ./1-setup.sh
Create the Lambda
To create a Lambda we need to :
- Create a role
- Attach the execution policy to it
- Package a zip from the source code
- Create the Lambda function
All the following steps, and other little tricks, are in the 2-create-lambda.sh script.
You can avoid all of the following copy and paste by running this script :
# execute all the steps below
$ ./2-create-lambda.sh
Create a role
We use the create-role command :
# get the values
$ source ./settings.sh
# create the lambda role
$ aws iam create-role \
--role-name $LAMBDA_ROLE_NAME \
--assume-role-policy-document fileb://lambda-role-policy.json \
--query 'Role.Arn' \
--output text
This is the trust policy :
# the policy
$ cat lambda-role-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Attach the execution policy to it
We use the attach-role-policy command :
# attach the `AWSLambdaBasicExecutionRole` policy to the lambda role
$ aws iam attach-role-policy \
--role-name $LAMBDA_ROLE_NAME \
--policy-arn $LAMBDA_POLICY_ARN
Package a zip from the source code
We use zip :
# zip the code of the lambda function
$ zip -9 lambda.zip index.js
The code is very simple :
# the code
$ cat index.js
exports.handler = async (event) => {
return {
statusCode: 200,
body: JSON.stringify('hello')
}
}
Create the Lambda function
We use the create-function command :
# get the lambda role Arn
LAMBDA_ROLE_ARN=$(aws iam get-role \
--role-name $LAMBDA_ROLE_NAME \
--query 'Role.Arn' \
--output text)
# create the Lambda
$ aws lambda create-function \
--region $AWS_REGION \
--function-name $LAMBDA_FUNCTION_NAME \
--runtime nodejs12.x \
--role $LAMBDA_ROLE_ARN \
--handler index.handler \
--zip-file fileb://lambda.zip
Create the API Gateway
To create an API Gateway and connect it whith the Lambda we need to :
All the following steps, and other little tricks, are in the 3-create-apigateway.sh script.
You can avoid all of the following copy and paste by running this script :
# execute all the steps below
$ ./3-create-apigateway.sh
Create the REST API Gateway
We use the create-rest-api command :
# create the API Gateway
$ aws apigateway create-rest-api \
--region $AWS_REGION \
--name $API_GATEWAY_NAME \
--endpoint-configuration types=REGIONAL \
--description 'A test API'
Now we need to define some variables :
# get the API Gateway id
API_GATEWAY_ID=$(aws apigateway get-rest-apis \
--region $AWS_REGION \
--query "items[?name=='$API_GATEWAY_NAME'].[id]" \
--output text)
# get the API Gateway arn
API_GATEWAY_ARN="arn:aws:execute-api:${AWS_REGION}:${AWS_ID}:${API_GATEWAY_ID}"
# get the root path id
API_GATEWAY_ROOT_RESOURCE_ID=$(aws apigateway get-resources \
--region $AWS_REGION \
--rest-api-id $API_GATEWAY_ID \
--query "items[?path=='/'].[id]" \
--output text)
Create the resource
We use the create-resource command :
# create the `API_GATEWAY_RESOURCE_NAME` resource path
$ aws apigateway create-resource \
--region $AWS_REGION \
--rest-api-id $API_GATEWAY_ID \
--parent-id $API_GATEWAY_ROOT_RESOURCE_ID \
--path-part $API_GATEWAY_RESOURCE_NAME
# get the `API_GATEWAY_RESOURCE_NAME` path id
$ API_GATEWAY_RESOURCE_ID=$(aws apigateway get-resources \
--region $AWS_REGION \
--rest-api-id $API_GATEWAY_ID \
--query "items[?path=='/$API_GATEWAY_RESOURCE_NAME'].[id]" \
--output text)
Create the POST method
We will associate the POST
method with our resource. And we’re going to attach the Lambda function to it.
We use the put-method command :
# create the POST method
$ aws apigateway put-method \
--region $AWS_REGION \
--rest-api-id $API_GATEWAY_ID \
--resource-id $API_GATEWAY_RESOURCE_ID \
--http-method POST \
--authorization-type NONE
# setup the POST method integration request
$ aws apigateway put-integration \
--region $AWS_REGION \
--rest-api-id $API_GATEWAY_ID \
--resource-id $API_GATEWAY_RESOURCE_ID \
--http-method POST \
--integration-http-method POST \
--type AWS_PROXY \
--uri "arn:aws:apigateway:$AWS_REGION:lambda:path/2015-03-31/functions/$LAMBDA_FUNCTION_ARN/invocations"
# add lambda permission
$ STATEMENT_ID=api-lambda-permission-$(cat /dev/urandom | tr -dc 'a-z' | fold -w 10 | head -n 1)
$ aws lambda add-permission \
--region $AWS_REGION \
--function-name $LAMBDA_FUNCTION_NAME \
--source-arn "$API_GATEWAY_ARN/*/POST/$API_GATEWAY_RESOURCE_NAME" \
--principal apigateway.amazonaws.com \
--statement-id $STATEMENT_ID \
--action lambda:InvokeFunction
To complete the process, we need to setup the method response.
We use the put-method-response command :
# setup the POST method responses (method + integration response)
$ aws apigateway put-method-response \
--region $AWS_REGION \
--rest-api-id $API_GATEWAY_ID \
--resource-id $API_GATEWAY_RESOURCE_ID \
--http-method POST \
--status-code 200 \
--response-models '{"application/json": "Empty"}'
$ aws apigateway put-integration-response \
--region $AWS_REGION \
--rest-api-id $API_GATEWAY_ID \
--resource-id $API_GATEWAY_RESOURCE_ID \
--http-method POST \
--status-code 200 --selection-pattern ''
Deploy the API
We can now deploy the API Gateaway and test it with curl.
We use the create-deployment command :
# publish the API, create the `dev` stage
$ aws apigateway create-deployment \
--region $AWS_REGION \
--rest-api-id $API_GATEWAY_ID \
--stage-name dev
# it works !
$ curl --request POST \
https://$API_GATEWAY_ID.execute-api.$AWS_REGION.amazonaws.com/dev/$API_GATEWAY_RESOURCE_NAME
"hello"
If we want to clear everything we have created, we have to use these commands :
# delete the API Gateway
$ aws apigateway delete-rest-api \
--region $AWS_REGION \
--rest-api-id $API_GATEWAY_ID
# delete the Lambda
$ aws lambda delete-function \
--region $AWS_REGION \
--function-name $LAMBDA_FUNCTION_NAME
# to delete the role, you must detach policy first
$ aws iam detach-role-policy \
--role-name $LAMBDA_ROLE_NAME \
--policy-arn $LAMBDA_POLICY_ARN
# delete the role
$ aws iam delete-role \
--role-name $LAMBDA_ROLE_NAME