Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Suggestion: Integrate lambda@edge to allow adding HTTP Security Headers #36

Open
NikitaKoren opened this issue Feb 23, 2021 · 1 comment

Comments

@NikitaKoren
Copy link

Overview
It would be great if fullstack-serverless exposed an option, potentially called headers that would allow to set any custom headers for the static content using lambda@edge or some other solution.

I found it difficult to set any security headers since s3 bucket and cloudfront support very limited amount of headers. Specifically, almost none of the commonly used headers for security hardening like Strict Transport Security, Content-Security-Policy, X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Referrer-Policy (infosec.mozilla).

Possible Solution with lambda@edge

Screen Shot 2021-02-22 at 9 58 34 PM

Here is how the process works:

  1. Viewer requests website www.example.com.
  2. If the object is cached already, CloudFront returns the object from the cache to the viewer, otherwise it moves on to step 3.
  3. CloudFront requests the object from the origin, in this case an S3 bucket.
  4. S3 returns the object, which in turn causes CloudFront to trigger the origin response event.
  5. Our Add Security Headers Lambda function triggers, and the resulting output is cached and served by CloudFront.

Edge function source

'use strict';
exports.handler = (event, context, callback) => {
    
    //Get contents of response
    const response = event.Records[0].cf.response;
    const headers = response.headers;

    //Set new headers 
    headers['strict-transport-security'] = [{key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubdomains; preload'}]; 
    headers['content-security-policy'] = [{key: 'Content-Security-Policy', value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"}]; 
    headers['x-content-type-options'] = [{key: 'X-Content-Type-Options', value: 'nosniff'}]; 
    headers['x-frame-options'] = [{key: 'X-Frame-Options', value: 'DENY'}]; 
    headers['x-xss-protection'] = [{key: 'X-XSS-Protection', value: '1; mode=block'}]; 
    headers['referrer-policy'] = [{key: 'Referrer-Policy', value: 'same-origin'}]; 
    
    //Return modified response
    callback(null, response);
};

Reference


As of right now, one of the workarounds is to setup lambda@edge manually and map it to the cloudfront distribution created by the fullstack-serverless plugin. In addition, you will need to configure Basic Lambda Execution Policy allowing logs to be written to CloudWatch and Trust Relationship allowing Lambda and Lambda@Edge to assume the role. (configuring-x-frame-options-response-header-on-aws-cloudfront-and-s3).

@andrewphahn
Copy link

Awesome writeup @NikitaKoren! This will help others a ton when they need to do something similar.

I have looked at adding this before and haven't yet found the time. The work needed is:

  • Figure out what the additions to the CloudFormation need to look like
  • Add a way to make the changes to the CFT
    • This could look like origins or cacheBehaviors where custom CF snippets are injected into the final resource
  • Package and deploy the lanbda@edge function code
    • Or just provide the ARN of an already deployed lanbda@edge function

A PR for this would be most welcome!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants