In this project, we will create a note-taking app with a serverless backend using AWS. We will use serverless functions to process CRUD requests, a NoSQL database to store metadata, an object storage for media content, and the API Gateway, which will serve as an endpoint for the CRUD functions.
Caution
This mini project simulates an environment and its architecture might lack some best practices. It is advised against using it for production environments.
- AWS account
- AWS CLI in
us-east-1
with admin privileges
- AWS
- Lambda
- S3
- API Gateway
- CloudFormation
- CloudTrail
- KMS
- DynamoDB
- Python (Boto3)
/CloudFormation-templates
: CloudFormation templates for the infrastructure/lambda-code
: Source codes for CRUD and EmptyS3Bucket Lambda functions/zipped-codes
: Zip format of Lambda functions codes
Note
This project repository only contains backend configurations. It does not contain a frontend application, but the backend will fit with most CRUD operations apps.
We will create two stacks for this project: CloudTrail and backend.
I have already created a public S3 bucket that contains CloudFormation templates and Lambda codes that we will use in this project. You can readily use it with the following commands.
This stack will create three main things:
- KMS keys for encryption
- CloudTrail
- S3 bucket for CloudTrail logs
Since it's important to harden security, the API logs will be encrypted both at-rest and in-transit. For this purpose, we will generate encryption keys using KMS and CloudTrail will use those keys to encrypt the logs as well as the bucket.
Apply the stack via cli:
aws cloudformation create-stack \
--stack-name mycloudtrailstack \
--template-body https://code-for-note-functions-86.s3.amazonaws.com/cloudtrail-kms-s3.yaml
If you don't have AWS CLI configured, you can apply it via One-click deployment link.
For the backend in this project, we will use Lambda functions for CRUD operations, a DynamoDB table for storing metadata, and a S3 bucket for storing media such as contents or images. There will be a single API Gateway that will invoke backend functions based on different resource paths and methods.
This stack will create four main things:
- DynamoDB table
- S3 bucket
- Lambda functions
- API Gateway
aws cloudformation create-stack \
--stack-name myserverlessappstack \
--template-body https://code-for-note-functions-86.s3.amazonaws.com/serverless-backend.yaml \
--capabilities CAPABILITY_IAM
One-click deployment (This may need IAM role with admin privileges)
I have enabled CORS for my API Gateway. You can adjust/disable this configuration based on your usage. The CloudFormation template will output two invoke links: CRUD and EmptyBucket.
Let's test these APIs. You can use different tools such as curl. However, I will use Postman since it is more convenient.
Here's the sample of how POST API method for CULambdaFunction looks like.
The expected query parameters that I have written in my Lambda codes are as follows:
- CU function
- Name
- Content
- READ function
- CreatedAt
- Name
- DELETE function
- CreatedAt
- Name
You can adjust the Lamda code based on your application use case.
Now, the CULambdaFunction
stores the metadata(CreatedAt
and Name
)in the DynamoDB table and media(Content
) in the S3 bucket. It's important to note that CloudFormation won't be able to delete a non-empty S3 bucket.
I have written a python code that will be used by a Lambda function, and this will delete all the objects inside the S3 bucket that we created earlier with CloudFormation. You can invoke this Lambda function via API Gateway as well:
If you do not need the infrastructure anymore, you can clean up everything that we created earlier.
This will delete everything except the S3 bucket. This will differ based on the environment, and I think it's better to retain the bucket containing tracing information for any further use.
aws cloudformation delete-stack --stack-name mycloudtrailstack
aws cloudformation delete-stack --stack-name myserverlessappstack
- Frontend UI hosted on S3 or ECS Fargate (for serverless purposes)
- Authentication of users (JWT, Firebase, Cognito)
- Cognito is more expensive than other options.
Any contribution is welcomed with the aim of improving this mini project.