Deploying our Guestbook application using API Gateway and Lambda required a significant number of manual steps. Manual deployment of code is repetitive and error-prone. "Infrastructure as Code" seeks to eliminate this by allowing one to programmatically deploy resources into your cloud project. Examples of this include platform-specific tools such as AWS Cloud Formation and GCP Cloud Deployment Manager as well as platform-agnostic tools such as HashiCorp's Terraform and Kubernetes.

In this lab we will repeat the deployment of the API version of our Guestbook, but deploy it to AWS using the AWS Cloud Development Kit (CDK).

We will now examine the CDK code for deploying the REST API backend. In the Cloud9 environment, change into the source directory for the backend

git clone https://github.com/wu4f/cs430-src
cd cs430-src/06_aws_restapi_lambda_cdk/restapi/

Examine app.py. First, we import the aws_cdk modules that we will need

CDK produces CloudFormation templates when we run app.py. We get an instance of App, register any stacks in our app, and emit our templates by calling the synth method

The stack represents a CloudFormation stack that CDK will use to deploy resources

Our stack will include an API Gateway, a sign lambda to POST guestbook entries, a get_entries lambda to GET guestbook entries, and a DynamoDB table.

We set up an API Gateway and two resources which will be the endpoints that API Gateway will proxy to our lambdas

Notice that we set up CORS headers. These headers will be applied to all endpoints, but remember that API Gateway is only proxying to our lambdas. We will also need to set up CORS on our lambdas.

To set up the sign lambda, we set up a lambda, an API Gateway integration, and a POST method

The get_entries lambda looks about the same, but with a GET method and a different handler.

Lastly, we create a DynamoDB table, grant read and write permissions to our lambdas, and add the table name as an environment variable to our lambdas

We will now deploy our API using CDK. In the Cloud9 environment we created earlier, update cdk to the newest version.

npm update -g cdk

Change into the base directory for this lab.

cd cs430-src/06_aws_restapi_lambda_cdk/

Set up a Python virtual environment and install the required packages.

python3 -m venv env
source env/bin/activate
pip install -r requirements.txt

We need to bootstrap CDK once with the AWS account and the region where we intend to run it. The bootstrapping process sets up a CloudFormation stack that allows CDK to provision resources on our behalf.

As done previously, obtain your AWS Account ID by using AWS's Security Token Service and parsing the response.

sudo apt install -y jq

aws sts get-caller-identity

export aws_account_id=$(aws sts get-caller-identity | jq '.Account | tonumber')

echo $aws_account_id

*Note this script will not work if your account id is prepended with a leading 0, instead:

export aws_account_id=<FMI>

Using this, bootstrap your CDK environment with it in the us-east-1 region from the 06_aws_restapi_lambda_cdk/restapi/ directory.

cd restapi/
cdk bootstrap aws://${aws_account_id}/us-east-1

Then, deploy the REST API

cdk deploy

Select y when you are asked if you want to deploy the changes. The CDK command line tool will show a summary of the resources as they are deployed.

When the deployment is complete, find the CloudFormation service and open it.

Back in the Cloud9 environment, CDK will report a RestApiStack.ApiGatewayEndpoint. Copy this endpoint and save it somewhere. We will use it to configure the client in an upcoming portion of the lab.

We will deploy the frontend as a separate CDK app. As before, our goal is to deploy the web app to an S3 bucket with static website hosting enabled, public access allowed, and a bucket policy that allows anyone to perform s3:GetObject on any object in the bucket. We will now examine the CDK code for the frontend deployment. Change into the source directory for the web app

cd cs430-src/06_aws_restapi_lambda_cdk/frontend/src/

We set up our frontend stack in frontend/app.py. We create the bucket with

Static website hosting is enabled by setting a website_index_document. Recall that S3 bucket names are globally unique. We probably will not get a bucket name like guestbook which surely must be taken. CloudFormation prepends the bucket name with the stack name and appends random characters to make sure we get a unique bucket name.

The bucket policy allows s3:GetObject to any principal on any object in the bucket. Any principal means that anonymous access is allowed, which means anyone can visit the website.

The source files for our web app are deployed by the aws-cdk.aws-s3-deployment package

Lastly, we create an output that shows us the static website hosting domain when the deploy finishes


Find the RestApiStack.ApiGatewayEndpoint from Deploy the API and fill it into the <FMI> in guestbook.js.

Change into the 06_aws_restapi_lambda_cdk/frontend/ directory

cd ..

Deploy the app

cdk deploy

Select y when you are asked if you want to deploy the changes. When the deploy is finished, CDK will report our static website hosting domain name.

Copy the URL and open the website in Chrome. Add an entry with the message "Hello Lambda and API Gateway!".

From the 06_aws_restapi_lambda_cdk/frontend/ directory

cdk destroy

From the 06_aws_restapi_lambda_cdk/restapi/ directory

cdk destroy

These two commands will destroy almost all of the resources that we have deployed. The DynamoDB table and S3 buckets are retained because we want to avoid accidentally deleting data.

Find the DynamoDB table and the S3 bucket and delete them. You will need to delete all of the objects from the S3 bucket before you are allowed to delete the bucket.

aws s3 rm --recursive s3://<FMI>/
aws s3 rb s3://<FMI>

If you no longer need it, go to Cloud9 and delete the environment used for this lab. This will automatically terminate the EC2 instance used to run the IDE.