Code Monkey home page Code Monkey logo

lambda-cloudfront-cookies's Introduction

lambda-cloudfront-cookies

AWS Lambda to protect your CloudFront content with username/passwords

How it works

The first step is to have CloudFront in front of your S3 bucket.

Browser ----> CloudFront ----> S3 bucket

We then add a Lambda function responsible for logging-in. When given valid credentials, this function creates signed session cookies. CloudFront will verify every request has valid cookies before forwarding them.

Browser                   CloudFront             Lambda              S3
  |                           |                    |                 |
  | ---------- get ---------> |                    |                 |
  |                           |                    |                 |
  |                      [no cookie]               |                 |
  |                           |                    |                 |
  |                           |                    |                 |
  |                           |                    |                 |
  | <------ error page ------ |                    |                 |
  |                                                |                 |
  | -------------------- login ------------------> |                 |
  | <------------------- cookies ----------------- |                 |
  |                                                                  |
  | ---------- get ---------> |                                      |
  |                           |                                      |
  |                      [has cookie]                                |
  |                           |                                      |
  |                           | -----------------------------------> |
  |                           | <------------ html page ------------ |
  | <------ html page ------- |

Pre-requisites

1. Encryption key

  • Create an encryption key in KMS, or choose one that you already have. Note that each KMS key costs $1/month.
  • Take note of the key ID.

2. CloudFront key pair

  • Logging in with your AWS root account, generate a CloudFront key pair
  • Take note of the key pair ID
  • Download the private key, and encrypt it with KMS using
aws kms encrypt --key-id $KMS_KEY_ID --plaintext "$(cat pk-000000.pem)" --query CiphertextBlob --output text
  • Write down the encrypted value, then secure the private key or delete it

3. Htpasswd

  • Create a local htpasswd file with your usernames and passwords. You can generate the hashes from the command-line:
$ htpasswd -nB username
New password: **********
Re-type new password: **********
username:$2a$08$eTTe9DM5N0w50CxL5OL0D.ToMtpAuip/4TCSWCSDJddoIW9gaQIym
  • Encrypt your htpasswd file using KMS again
aws kms encrypt --key-id $KMS_KEY_ID --plaintext "$(cat htpasswd)" --query CiphertextBlob --output text

Deployment

Create a configuration file called dist/config.json, based on config.example.json. Make sure you don't commit this file to source control (the dist folder is ignored).

It should contain the following info - minus the comments:

[
  // -------------------
  // PLAIN TEXT SETTINGS
  // -------------------

  // the website domain, as seen by the users
  "websiteDomain=website.com",
  // how long the CloudFront access is granted for, in seconds
  // note that the cookies are session cookies, and will get deleted when the browser is closed anyway
  "sessionDuration=86400",
  // if false, a successful login will return HTTP 200 (typically for Ajax calls)
  // if true, a successful login will return HTTP 302 to the Referer (typically for form submissions)
  "redirectOnSuccess=true",
  // KMS key ID created in step 1
  "kmsKeyId=00000000-0000-0000-0000-000000000000",
  // CloudFront key pair ID from step 2
  // This is not sensitive, and will be one of the cookie values
  "cloudFrontKeypairId=APK...",

  // ------------------
  // ENCRYPTED SETTINGS
  // ------------------

  // encrypted CloudFront private key from step 2
  "encryptedCloudFrontPrivateKey=AQECAH...",

  // encrypted contents of the <htpasswd> file from step 3
  "encryptedHtpasswd=AQECAH..."
]

You can then deploy the full stack using:

export AWS_PROFILE="your-profile"
export AWS_REGION="ap-southeast-2"

# name of an S3 bucket for storing the Lambda code
./deploy my-bucket

The output should end with the AWS API Gateway endpoint:

Endpoint URL: https://0000000000.execute-api.ap-southeast-2.amazonaws.com/Prod/login"

Take note of that URL, and test it out!

# with a HTTP Form payload
curl -X POST -d "username=hello&password=world" -H "Content-Type: x-www-form-encoded" -i "https://0000000000.execute-api.ap-southeast-2.amazonaws.com/Prod/login"

# with a JSON payload
curl -X POST -d "{\"username\":\"hello\", \"password\":\"world\"}" -H "Content-Type: application/json" -i "https://0000000000.execute-api.ap-southeast-2.amazonaws.com/Prod/login"

Final steps:

  • optionally setup CloudFront in front of this URL too, so you can use a custom domain like https://website.com/login
  • once everything is working, change your CloudFront distribution to require signed cookies and it will return HTTP 403 for users who aren't logged in
  • setup CloudFront to serve a nice login page for 403 errors, or use an existing page from your website to trigger the Lambda function

lambda-cloudfront-cookies's People

Contributors

raphaelsampaio avatar rprieto avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

lambda-cloudfront-cookies's Issues

Multiple distributions for multiple origin paths

Hey - I want to extend this that it works for multiple distributions setup for multiple origin paths in the same bucket. Can the same KMS and CloudFront key pair work for this? What would I specify in the websiteDomain attribute for config.json ?

example :

myBucket
->folder-a -> folder-a.mysite.com
->folder-b -> folder-b.mysite.com

I want to use different credentials to log into the 2 sites.
Will I need to create multiple lambda functions - 1 per site or can I just use a single one with some params?

Thanks

Server error

First off, huge thanks for putting this together. Looks exactly like what I want to set up. ๐Ÿ‘Œ

However, after following all the steps, I can't seem to get the lambda function to successfully "log in":

curl -X POST -d "{\"username\":\"MY_USERNAME\", \"password\":\"MY_PASSWORD\"}" -H "Content-Type: application/json" -i "https://0000000000.execute-api.us-west-1.amazonaws.com/Prod/login" 
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 12
Connection: keep-alive
Date: Fri, 16 Jun 2017 00:32:27 GMT
x-amzn-RequestId: 4555c638-522b-11e7-b0db-9b020bd73a15
X-Amzn-Trace-Id: sampled=0;root=1-59432719-509f99d0578ae66e8ee848ce
X-Cache: Error from cloudfront
Via: 1.1 81871f1c889cc44b6c25e3ef722a3801.cloudfront.net (CloudFront)
X-Amz-Cf-Id: lMLUkiAOkyh08ry0XXLpHTTPdHGISOzNkU4TDRTBLYELAw1MIId04g==

Server error

Would you have any advice as to how to debug this? My AWS-fu is pretty weak ๐Ÿ˜…

Thanks again.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.