{"id":19745184,"url":"https://github.com/castle/castle-aws-cloudfront-sample","last_synced_at":"2025-10-09T07:37:19.538Z","repository":{"id":49432501,"uuid":"343540661","full_name":"castle/castle-aws-cloudfront-sample","owner":"castle","description":"Castle at the Edge with AWS Lambda and CloudFront ","archived":false,"fork":false,"pushed_at":"2021-06-17T17:07:18.000Z","size":30,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-02-28T07:39:53.605Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/castle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-03-01T20:00:23.000Z","updated_at":"2021-09-21T11:12:56.000Z","dependencies_parsed_at":"2022-09-08T01:11:13.949Z","dependency_job_id":null,"html_url":"https://github.com/castle/castle-aws-cloudfront-sample","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/castle/castle-aws-cloudfront-sample","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/castle%2Fcastle-aws-cloudfront-sample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/castle%2Fcastle-aws-cloudfront-sample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/castle%2Fcastle-aws-cloudfront-sample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/castle%2Fcastle-aws-cloudfront-sample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/castle","download_url":"https://codeload.github.com/castle/castle-aws-cloudfront-sample/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/castle%2Fcastle-aws-cloudfront-sample/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000960,"owners_count":26082973,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-12T02:04:50.335Z","updated_at":"2025-10-09T07:37:19.521Z","avatar_url":"https://github.com/castle.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg align=\"center\" alt=\"Castle logo\" src='./assets/castle-logo.svg' width='150'/\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eCastle at the Edge with AWS Lambda and CloudFront\n\u003c/h1\u003e\n\u003c/div\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003cimage alt=\"Package version\" src=\"https://img.shields.io/github/package-json/v/castle/castle-aws-cloudfront-sample\"/\u003e\n  \u003cimage alt=\"License\" src=\"https://img.shields.io/github/license/castle/castle-aws-cloudfront-sample\"/\u003e\n\u003c/div\u003e\n\n## Overview\n\nAWS 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.\n\nThis 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).\n\n## How it works\n\nOnce you've installed this Lambda function, it will listen for POSTs to the\n`/users/sign_up`\n\nroute.\n\nThe POST should include a Castle `castle_request_token` in the body of the request. Click [here](https://castle.io/filter-api/) to learn more about how to include a Castle `request_token` in a POST.\n\nWhen 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.\n\n## Prerequisites\n\nYou'll need a Castle account and an AWS account to get started.\n\n### Castle\n\nIf you don't have a Castle account already, you can [set up a free trial](https://dashboard.castle.io/signup/new). You will need your Castle API Secret, which can be found in the Settings section of your Castle dashboard.\n\n## Installation\n\n### CloudFront\n\nLambda@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.\n\nA couple of notes as you set up your CloudFront distribution:\n\n* 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)\n* Ignore the Lambda section for now. We're going to attach the Lambda function \"manually\".\n\n### Prepare the repo\n\nBefore you set up your Lambda function, you need to prepare this repo, which involves three main steps:\n\n1. download the repo\n2. install dependencies\n3. add your Castle API Secret\n4. create a .zip archive\n\n#### Download the repo\n\n`git clone https://github.com/castle/castle-aws-cloudfront-sample`\n\n#### Install dependencies\n\n`cd castle-aws-cloudfront-sample`\n\n`npm install`\n\n#### Add your Castle API key\n\nUnlike standard Lambda functions, Lambda@Edge functions do *not* allow environment variables.\n\nSo to proceed you have to copy the file \n\n`config.example.json`\n\nto\n\n`config.json`\n\nand put your Castle API Secret and APP ID in the `config.json` file.\n\n\u003e 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).\n\n\u003e Note: the default CORS policy in this script is to allow all origins; you can adjust as necessary.\n\n#### Create a .zip archive\n\nThis command will create a `.zip` archive:\n\n`zip -x \".git\" -r function.zip .`\n\n### Create a new Lambda function\n\nLog in to your AWS Console-\u003eLambda\n\n* Create function\n\n* Select `Author from scratch`\n* Enter function name: castle-edge\n* Runtime: Node.js\n\n* Create function\n\nOn the function home screen:\n\nScroll down to the Function `Code source` section and select `.zip fil`e from the `Upload from`\n\nUpload the zip archive that you created.\n\nClick on newly created roe in the Configuration/Permissions tab and add\n\n`edgelambda.amazonaws.com` \n\nto 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](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-permissions.html).\n\n\u003e Note: reload the Lambda dashboard after you adjust the permissions for the Lambda function.\n\n#### Test your Lambda function\n\nYou can test your Lambda function with the `cloudfront_request.json` sample event included in the `requests` directory and by running `node test.js`\n\n#### Add a CloudFront trigger\n\n\u003e 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 the `us-east-1` region.\n\nClick Add Trigger (Configuration/Trigger)\n\nSelect the CloudFront \n\nClick Deploy to Lambda@Edge\n\nDistribution: select the Distribution that you previously created\n\nCloudFront Event: Viewer Request (not the default!)\n\nInclude body: Yes (not the default!)\n\nConfirm deploy to Lambda@Edge: Yes\n\nPress Deploy\n\nAfter 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.\n\n## Testing\n\nTo test the deployment, send a POST to:\n\n`{{cloudfront_url}}/users/sign_up`\n\nA sample CURL request is included in the `sampleRequests` folder.\n\nYour result will look something like this:\n\n{\n    \"prodStatus\": \"200\",\n    \"riskScore\": 0.4079629060878592,\n    \"riskThreshold\": 0.9,\n    \"castleAssessment\": {\n        \"action\": \"allow\",\n        \"user_id\": null,\n        \"user\": {},\n        \"risk\": 0.4079629060878592\n    }\n}\n\n## Adapting To Your Use Case\n\nTo 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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcastle%2Fcastle-aws-cloudfront-sample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcastle%2Fcastle-aws-cloudfront-sample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcastle%2Fcastle-aws-cloudfront-sample/lists"}