AWS CloudFront allows you to distribute your content globally so that your users can access your content from a source as close to home as possible. AWS Lambda@Edge allows you to add the power of Lambda functions to requests coming in to your CloudFront distribution.
This repo will allow you to attach Castle to a Lambda@Edge function, so that you can block bot traffic at the edge, before malicious requests reach your /users/sign_up
endpoint (or whatever other endpoint you want to protect).
Once you've installed this Lambda function, it will listen for POSTs to the
/users/sign_up
route.
The POST should include a Castle castle_request_token
in the body of the request. Click here to learn more about how to include a Castle request_token
in a POST.
When the Lambda function receives the POST, it will in turn make a POST to Castle, and receive a verdict (policy[action]
) and risk score in return if the verdict is "deny", then the function will respond with a 403.
You'll need a Castle account and an AWS account to get started.
If you don't have a Castle account already, you can set up a free trial. You will need your Castle API Secret, which can be found in the Settings section of your Castle dashboard.
Lambda@Edge requires a CloudFront distribution to function. So, even though this particular solution will not be serving static files from an S3 bucket via CloudFront, you still need to set up a CloudFront distribution to attach the Lambda@Edge function to.
A couple of notes as you set up your CloudFront distribution:
- You must explicitly allow POST requests. (By default, POST requests are not allowed. You need to allow
GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
HTTP Methods) - Ignore the Lambda section for now. We're going to attach the Lambda function "manually".
Before you set up your Lambda function, you need to prepare this repo, which involves three main steps:
- download the repo
- install dependencies
- add your Castle API Secret
- create a .zip archive
git clone https://github.com/castle/castle-aws-cloudfront-sample
cd castle-aws-cloudfront-sample
npm install
Unlike standard Lambda functions, Lambda@Edge functions do not allow environment variables.
So to proceed you have to copy the file
config.example.json
to
config.json
and put your Castle API Secret and APP ID in the config.json
file.
Note: this pattern of putting the API Secret in a separate file simply allows the API key to be easily excluded from source control. The API Secret will be visible to any AWS user/role who has access to the source of the Lambda function (just like environment variables).
Note: the default CORS policy in this script is to allow all origins; you can adjust as necessary.
This command will create a .zip
archive:
zip -x ".git" -r function.zip .
Log in to your AWS Console->Lambda
-
Create function
-
Select
Author from scratch
-
Enter function name: castle-edge
-
Runtime: Node.js
-
Create function
On the function home screen:
Scroll down to the Function Code source
section and select .zip fil
e from the Upload from
Upload the zip archive that you created.
Click on newly created roe in the Configuration/Permissions tab and add
edgelambda.amazonaws.com
to the Trust Relationship for the role that was created automatically when you created the Lambda function. More details on Lambda@Edge IAM are available here.
Note: reload the Lambda dashboard after you adjust the permissions for the Lambda function.
You can test your Lambda function with the cloudfront_request.json
sample event included in the requests
directory and by running node test.js
As of March 2021, Lambda@Edge functions are available only the
us-east-1
region. If you don't see Cloudfront in the list of triggers, make sure you're in theus-east-1
region.
Click Add Trigger (Configuration/Trigger)
Select the CloudFront
Click Deploy to Lambda@Edge
Distribution: select the Distribution that you previously created
CloudFront Event: Viewer Request (not the default!)
Include body: Yes (not the default!)
Confirm deploy to Lambda@Edge: Yes
Press Deploy
After you deploy, it will take a few minutes (sometimes longer) for the Lambda function to deploy across your CloudFront distribution. You can open your CloudFront dashboard to monitor the progress of the deployment in the "status" column of your distribution.
To test the deployment, send a POST to:
{{cloudfront_url}}/users/sign_up
A sample CURL request is included in the sampleRequests
folder.
Your result will look something like this:
{ "prodStatus": "200", "riskScore": 0.4079629060878592, "riskThreshold": 0.9, "castleAssessment": { "action": "allow", "user_id": null, "user": {}, "risk": 0.4079629060878592 } }
To add new routes, methods and customize the sample to be protected by Castle. You may want to add the route for your login endpoint, as well as the route for your password reset endpoint.