Skip to content

Commit

Permalink
implement tgtm suggestions to apigw custom domain sample (#246)
Browse files Browse the repository at this point in the history
* implement tgtm suggestions to apigw custom domain sample

* upgrade serverless localstack plugin version

* implement suggestions

* make suggested changes

* skip auth token check

* make all changes
  • Loading branch information
HarshCasper authored Jun 10, 2024
1 parent d308c5f commit a20710d
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 109 deletions.
87 changes: 52 additions & 35 deletions apigw-custom-domain/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,74 @@ export AWS_ACCESS_KEY_ID ?= test
export AWS_SECRET_ACCESS_KEY ?= test
export AWS_DEFAULT_REGION ?= us-east-1


usage: ## Show this help
@fgrep -h "##" $(MAKEFILE_LIST) | fgrep -v fgrep | sed -e 's/\\$$//' | sed -e 's/##//'

check: ## Check if all required prerequisites are installed
@command -v docker > /dev/null 2>&1 || { echo "Docker is not installed. Please install Docker and try again."; exit 1; }
@command -v node > /dev/null 2>&1 || { echo "Node.js is not installed. Please install Node.js and try again."; exit 1; }
@command -v aws > /dev/null 2>&1 || { echo "AWS CLI is not installed. Please install AWS CLI and try again."; exit 1; }
@command -v python > /dev/null 2>&1 || { echo "Python is not installed. Please install Python and try again."; exit 1; }
@command -v openssl > /dev/null 2>&1 || { echo "OpenSSL is not installed. Please install OpenSSL and try again."; exit 1; }
@command -v localstack > /dev/null 2>&1 || { echo "LocalStack is not installed. Please install LocalStack and try again."; exit 1; }
@echo "All required prerequisites are available."

install: ## Install dependencies
@npm install
@which serverless || npm install -g serverless
@which localstack || pip install localstack
@which awslocal || pip install awscli-local
@if [ ! -d "node_modules" ]; then \
echo "node_modules not found. Running npm install..."; \
npm install; \
else \
echo "node_modules already installed."; \
fi
@echo "All required dependencies are available."

cert: ## Create test SSL certificate
mkdir -p sslcert
cd sslcert; \
which openssl || exit; \
openssl req -new -newkey RSA:2048 -nodes -keyout ssl.key -out ssl.csr -subj '/CN=test.example.com'; \
openssl genrsa -out rootCA.key 2048; \
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.pem -subj /CN=TestCA; \
@echo "Creating SSL certificates directory..."
@mkdir -p sslcert
@echo "Generating SSL certificate..."
@cd sslcert; \
which openssl || { echo "OpenSSL is not installed. Please install OpenSSL and try again."; exit 1; }; \
openssl req -new -newkey RSA:2048 -nodes -keyout ssl.key -out ssl.csr -subj '/CN=test.example.com' && \
openssl genrsa -out rootCA.key 2048 && \
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 3650 -out rootCA.pem -subj /CN=TestCA && \
openssl x509 -req -in ssl.csr -CAcreateserial -out server.crt -sha256 -CAkey rootCA.key -CA rootCA.pem
@echo "SSL certificate generated successfully."

deploy: ## Deploy Serverless app to local environment with SSL setup for Route53
@echo "Generating and importing test SSL certificate to ACM for Route53 domain test.example.com"
@make cert
@echo "Importing local test certificate into ACM API ..."
@awslocal acm import-certificate --certificate fileb://sslcert/server.crt --private-key fileb://sslcert/ssl.key
@echo "Creating Route53 hosted zone for test domain 'test.example.com' ..."
@awslocal route53 create-hosted-zone --name test.example.com --caller-reference r1
@echo "Deploying Serverless app to local environment"
@SLS_DEBUG=1 npm run deploy
@echo "Serverless app successfully deployed."

run: ## Run the app locally and show test invocations
./run.sh

run: ## Deploy the app locally and run an API GW test invocation
echo "Generating and importing test SSL certificate to ACM for Route53 domain test.example.com"; \
make cert; \
echo "Importing local test certificate into ACM API ..."; \
awslocal acm import-certificate --certificate fileb://sslcert/server.crt --private-key fileb://sslcert/ssl.key && \
echo "Creating Route53 hosted zone for test domain 'test.example.com' ..."; \
awslocal route53 create-hosted-zone --name test.example.com --caller-reference r1 && \
echo "Deploying Serverless app to local environment"; \
SLS_DEBUG=1 npm run deploy && \
echo "Serverless app successfully deployed. Now trying to invoke the API Gateway endpoints with custom domains." && \
echo && echo "Invoking endpoint 1: http://test.example.com:4566/hello" && \
response1=`curl -H 'Host: test.example.com' http://localhost:4566/hello` && \
../assert "$$response1" = "hello world" && \
echo && echo && echo "Invoking endpoint 2: http://test.example.com:4566/goodbye" && \
response2=`curl -H 'Host: test.example.com' http://localhost:4566/goodbye` && \
../assert "$$response2" = "goodbye"

start:
localstack start -d

stop:
test: ## Run tests
make deploy run target=ci

start: ## Start LocalStack
ACTIVATE_PRO=1 localstack start -d

stop: ## Stop LocalStack
@echo
localstack stop
ready:

ready: ## Wait until LocalStack is ready
@echo Waiting on the LocalStack container...
@localstack wait -t 30 && echo Localstack is ready to use! || (echo Gave up waiting on LocalStack, exiting. && exit 1)

logs:
logs: ## Retrieve LocalStack logs
@localstack logs > logs.txt

test-ci:
make start install ready run; return_code=`echo $$?`;\
test-ci: ## Run CI tests
make check start install ready test; return_code=`echo $$?`;\
make logs; make stop; exit $$return_code;

.PHONY: usage install run cert ready stop logs test-ci
.PHONY: usage check install run cert start stop ready logs test-ci
87 changes: 40 additions & 47 deletions apigw-custom-domain/README.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,61 @@
# LocalStack Demo: API Gateway with Custom Domains
# API Gateway with Custom Domains

Simple demo application illustrating API Gateway (v2) endpoints using custom domain names (via Route53, ACM), deployed locally in LocalStack using the Serverless framework.
| Key | Value |
| ------------ | --------------------------------- |
| Environment | LocalStack |
| Services | API Gateway, Lambda, Route53, ACM |
| Integrations | Serverless Framework |
| Categories | Serverless; REST API |

## Introduction

A demo application showcasing API Gateway (v2) endpoints with custom domain names configured through Route53 and ACM, deployed locally using LocalStack and the Serverless framework. For more details, refer to the [documentation](https://docs.localstack.cloud/user-guide/aws/apigateway/#custom-domain-names-with-api-gateway).

Under the hood, the Serverless framework uses the [`serverless-localstack`](https://github.com/localstack/serverless-localstack) plugin to deploy the application to LocalStack. The plugin is configured in the `serverless.yml` file to use the LocalStack endpoint and the custom domain name.

## Prerequisites

* LocalStack
* Docker
* Node.js / `npm`
* `make`
* [Node.js 18.x](https://nodejs.org/en/download/package-manager) with `npm`
* [Serverless Framework](https://www.serverless.com/framework/docs/getting-started) 3.x
* `openssl`

## Installing
## Check prerequisites

To install the dependencies:
```bash
make check
```

## Installation

```bash
make install
```

## Running
## Start LocalStack

Make sure that LocalStack is started:
```
LOCALSTACK_AUTH_TOKEN=... DEBUG=1 localstack start
```bash
make start
```

Deploy the app locally and run a test invocation via:
```
make run
```
## Deploy the Application

The script first generates an SSL certificate for local testing (in case the `openssl` command is not available, it will use an existing, predefined certificate), and then adds it to Amazon Certificate Manager (ACM), and finally creates a Route53 hosted zone for the domain name `test.example.com`:
```
Generating a 2048 bit RSA private key
...
subject=/CN=test.example.com
...
Importing local test certificate into ACM API ...
{
"CertificateArn": "arn:aws:acm:us-east-1:000000000000:certificate/9cbc69d6-abf9-412e-9e2b-36f99fcbf251"
}
Creating Route53 hosted zone for test domain 'test.example.com' ...
{
"HostedZone": {
"Id": "/hostedzone/SU1TPRNX6CL3OE0",
"Name": "test.example.com.",
...
```bash
make deploy
```

Next, you should see some output with the deployment logs of the Serverless application, and some details in the output section towards the bottom:
```
...
Serverless Domain Manager: Info: Created API mapping '(none)' for test.example.com
Serverless Domain Manager: Summary: Distribution Domain Name
Serverless Domain Manager: Domain Name: test.example.com
Serverless Domain Manager: Target Domain: test.example.com
Serverless Domain Manager: Hosted Zone Id: Z2FDTNDATAQYW2
```
The script:

Finally, the script runs two invocations of the new API GW API deployed under the custom domain name `test.example.com`:
```
Invoking endpoint 1: http://test.example.com:4566/hello
...
- Generates an SSL certificate for local testing using `openssl`.
- Uses a predefined certificate if `openssl` is unavailable.
- Adds the certificate to Amazon Certificate Manager (ACM).
- Creates a Route53 hosted zone for `test.example.com`.
- Displays deployment logs of the Serverless application in the output section.
- Showcases API Gateway endpoints and custom domain configuration.

## Run the application

Invoking endpoint 2: http://test.example.com:4566/goodbye
...
```bash
make run
```

## License
Expand Down
42 changes: 23 additions & 19 deletions apigw-custom-domain/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apigw-custom-domain/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"serverless": "^3.0.0",
"serverless-deployment-bucket": "^1.6.0",
"serverless-domain-manager": "^6.4.4",
"serverless-localstack": "^1.0.6"
"serverless-localstack": "^1.2.0"
},
"scripts": {
"deploy": "sls deploy --stage local"
Expand Down
30 changes: 30 additions & 0 deletions apigw-custom-domain/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/bash
set -euo pipefail

invoke_endpoints() {
echo "Invoking endpoint 1: http://test.example.com:4566/hello"
response1=$(curl -H 'Host: test.example.com' http://localhost:4566/hello)
if [ "$response1" != "hello world" ]; then
echo "Error: Response from endpoint 1 does not match expected output."
exit 1
fi

echo "Invoking endpoint 2: http://test.example.com:4566/goodbye"
response2=$(curl -H 'Host: test.example.com' http://localhost:4566/goodbye)
if [ "$response2" != "goodbye" ]; then
echo "Error: Response from endpoint 2 does not match expected output."
exit 1
fi
}

target="${target:-default}"

if [[ "$target" == "ci" ]]; then
invoke_endpoints
else
echo "Now trying to invoke the API Gateway endpoints with custom domains."
echo "Sample command to invoke endpoint 1:"
echo "curl -H 'Host: test.example.com' http://localhost:4566/hello"
echo "Sample command to invoke endpoint 2:"
echo "curl -H 'Host: test.example.com' http://localhost:4566/goodbye"
fi
4 changes: 2 additions & 2 deletions apigw-custom-domain/serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ service: sls-apigw-domain

provider:
name: aws
runtime: nodejs16.x
runtime: nodejs18.x
stage: local
region: ${env:AWS_DEFAULT_REGION, 'us-east-1'}
region: ${env:AWS_DEFAULT_REGION}

custom:
customDomain:
Expand Down

This file was deleted.

0 comments on commit a20710d

Please sign in to comment.