Create a serverless CRUD application using AWS Lambda to handle create, read, update, and delete operations. Utilize AWS Serverless Application Model (SAM) for deployment, Amazon Cognito for authentication, and Amazon API Gateway to expose the Lambda functions as RESTful endpoints.
To set up AWS SAM, Amazon Cognito, and Amazon API Gateway for your serverless CRUD application, follow these steps:
brew tap aws/tap
brew install aws-sam-cli
Create a new AWS SAM project:
sam init
Follow the prompts to select a template and runtime.
Edit the template.yaml
file to define your Lambda functions, API Gateway, and Cognito User Pool.
Generated file example:
AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Resources:
UserPool:
Type: AWS::Cognito::UserPool
Properties:
UserPoolName: MyUserPool
UserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: MyUserPoolClient
UserPoolId: !Ref UserPool
ApiGateway:
Type: AWS::Serverless::Api
Properties:
Name: MyApi
Auth:
DefaultAuthorizer: CognitoAuthorizer
Authorizers:
CognitoAuthorizer:
UserPoolArn: !GetAtt UserPool.Arn
CreateFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/create.handler
Runtime: nodejs14.x
Events:
Api:
Type: Api
Properties:
Path: /create
Method: post
RestApiId: !Ref ApiGateway
ReadFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/read.handler
Runtime: nodejs14.x
Events:
Api:
Type: Api
Properties:
Path: /read
Method: get
RestApiId: !Ref ApiGateway
UpdateFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/update.handler
Runtime: nodejs14.x
Events:
Api:
Type: Api
Properties:
Path: /update
Method: put
RestApiId: !Ref ApiGateway
DeleteFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/delete.handler
Runtime: nodejs14.x
Events:
Api:
Type: Api
Properties:
Path: /delete
Method: delete
RestApiId: !Ref ApiGateway
Create the Lambda function handlers in the src
directory. For example, create.js
:
exports.handler = async (event) => {
// Your create logic here
return {
statusCode: 200,
body: JSON.stringify({ message: 'Item created' }),
};
};
sam validate
Build and deploy your application using the AWS SAM CLI:
sam build
sam deploy --guided
# sam deploy --guided --profile academy (for specific aws profile)
(For this repository examples, run)
npm install --omit=dev
After, it can run only sam deploy
Follow the prompts to configure your deployment settings.
After deployment, you can test your endpoints using tools like Postman or curl. Ensure you have the necessary authentication tokens from Amazon Cognito.
- Go to the AWS Lambda Console.
- Select the Lambda function you want to execute.
- Click on "Test" at the top of the page.
- Configure a test event (you can use a sample event or create a custom one).
- Click "Test" again to execute the function.
You can use the invoke
command from the AWS CLI to execute the Lambda function. Here is an example:
aws lambda invoke --function-name DeleteItemLambdaFunction --payload '{"id": "123"}' response.json
--function-name
: Name of the Lambda function.--payload
: JSON with the input data for the function.response.json
: File where the execution response will be saved.
Here is an example of how to invoke a Lambda function using the AWS SDK for Python (Boto3):
import boto3
import json
# Create a Lambda client
client = boto3.client('lambda')
# Input Data for Lambda Function
payload = {
"id": "123"
}
# Invoke the Lambda function
response = client.invoke(
FunctionName='DeleteItemLambdaFunction',
InvocationType='RequestResponse',
Payload=json.dumps(payload)
)
# Read the response
response_payload = json.loads(response['Payload'].read())
print(response_payload)
Here is an example of how to invoke a Lambda function using the AWS SDK for Node.js:
const AWS = require('aws-sdk');
const lambda = new AWS.Lambda();
// Input Data for Lambda Function
const payload = {
id: "123"
};
// Params to invoke Lambda function
const params = {
FunctionName: 'DeleteItemLambdaFunction',
Payload: JSON.stringify(payload)
};
// Invoke the Lambda function
lambda.invoke(params, (err, data) => {
if (err) {
console.error(err);
} else {
console.log(JSON.parse(data.Payload));
}
});
Install dependencies that will be created a zip from:
npm install --only=prod
-
Create table
npm run create:table
-
Get all
npm run get:all
-
Get id
npm run get:id -- "<id>"
-
Create
npm run create -- "<name>"
-
Update
npm run update -- "<id>" "<name>"
-
Delete
npm run delete -- "<id>"
Since the endpoints are added into AWS API Gateway, we can access them directly as a REST API.
- Enable Docker;
- Run:
sam local start-api --profile <profile>
If everything is cool, you should see something like:
Containers Initialization is done.
Mounting GetAllItemsLambdaFunction at http://127.0.0.1:3000/ [GET]
Mounting DeleteItemLambdaFunction at http://127.0.0.1:3000/{id} [DELETE]
Mounting GetByIdLambdaFunction at http://127.0.0.1:3000/{id} [GET]
Mounting CreateItemLambdaFunction at http://127.0.0.1:3000/ [POST]
Mounting CreateTableLambdaFunction at http://127.0.0.1:3000/create-users-table [GET]
Mounting UpdateItemLambdaFunction at http://127.0.0.1:3000/{id} [PUT]
So we can hit those APIs with curl or with browser.
CreateTableLambdaFunction has no authentication. Is this okay? [y/N]:
MyCognitoAuthorizer:
Type: AWS::ApiGateway::Authorizer
Properties:
Name: CognitoAuthorizer
Type: COGNITO_USER_POOLS
IdentitySource: method.request.header.Authorization
RestApiId: !Ref ServerlessRestApi
ProviderARNs:
- !Sub arn:aws:cognito-idp:${AWS::Region}:${AWS::AccountId}:userpool/${CognitoUserPoolId}
Some error happened. Remove stack
aws cloudformation delete-stack --stack-name serveless-crud-app --profile academy
Verify if stack were removed:
aws cloudformation wait stack-delete-complete --stack-name serveless-crud-app --profile academy
_Execution failed due to configuration error: Invalid permissions on Lambda function
aws lambda add-permission --function-name serveless-crud-app-GetByIdLambdaFunction-zrwjZeOIWA6Z --statement-id random-id-01 --action lambda:InvokeFunction --principal apigateway.amazonaws.com --source-arn arn:aws:iam::520138362070:role/LabRole --profile academy
or
aws lambda add-permission --function-name serveless-crud-app-GetAllItemsLambdaFunction-OE22TZ2B5hqs --statement-id random-id-03 --action lambda:InvokeFunction --principal apigateway.amazonaws.com --source-arn arn:aws:execute-api:us-east-1:520138362070:1lw8ew6ksj --profile academy
To avoid errors with duplication:
STACK_NAME="serveless-crud-app-$(uuidgen)"
sam deploy --template-file template.yaml --stack-name $STACK_NAME --capabilities CAPABILITY_IAM --profile academy
I can't see my code at console editor - limit of the zip it should be 3 MB:
https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html#limits-list
It's possible to work with Layers: https://docs.aws.amazon.com/lambda/latest/dg/creating-deleting-layers.html