Skip to content
This repository was archived by the owner on Jun 28, 2022. It is now read-only.

Commit

Permalink
fix: issues 10 and 11 (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
arantespp authored Jan 29, 2021
1 parent 9558d0f commit 62cda51
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 26 deletions.
64 changes: 47 additions & 17 deletions packages/cli/src/deploy/staticApp/staticApp.template.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {
getStaticAppTemplate,
generateCsp,
generateCspString,
getLambdaEdgeOriginResponseZipFile,
CLOUDFRONT_DISTRIBUTION_LOGICAL_ID,
} from './staticApp.template';
Expand All @@ -9,46 +9,76 @@ import {
* Mock to snapshots don't fail.
*/
Date.now = jest.fn(() => 1487076708000);

const PACKAGE_VERSION = '10.40.23';

jest.mock('../../utils', () => ({
getPackageVersion: jest.fn().mockReturnValue('10.40.23'),
}));

describe("fix issue 'Add Google Marketing Platform to CSP' #3 https://github.com/ttoss/carlin/issues/3", () => {
const defaultCsp =
"default-src 'self'; connect-src 'self' https:; img-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com/; font-src 'self' https://fonts.gstatic.com/; object-src 'none'";
const defaultCspString =
"default-src 'self'; connect-src 'self' https:; img-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com/; font-src 'self' https://fonts.gstatic.com/; object-src 'none'";

describe("fix issue 'Filter CSP directives' #11 https://github.com/ttoss/carlin/issues/11", () => {
test('generate default CSP', () => {
expect(generateCsp()).toEqual(defaultCsp);
const generated = generateCspString({
csp: {
directiveSrc: 'some text',
'directive-src': 'some text',
},
});
expect(generated).not.toContain('directiveSrc');
expect(generated).toContain('directive-src');
});
});

test('add new directive', () => {
expect(generateCsp({ csp: { newDirective: "'some text'" } })).toContain(
"newDirective 'some text'",
describe("fix issue 'Add default CSP to Lambda@Edge origin response' #10 https://github.com/ttoss/carlin/issues/10", () => {
test('should add csp to Lambda@Edge Origin response', () => {
expect(getLambdaEdgeOriginResponseZipFile({ csp: {} })).toContain(
`value: "${defaultCspString}"`,
);
});

test('should add csp to Lambda@Edge Origin response when a directive is passed', () => {
const code = getLambdaEdgeOriginResponseZipFile({
csp: { 'new-directive-src': "'some text'" },
});

defaultCspString.split('; ').forEach((csp) => expect(code).toContain(csp));

expect(code).toContain("new-directive-src 'some text'");
});
});

describe("fix issue 'Add Google Marketing Platform to CSP' #3 https://github.com/ttoss/carlin/issues/3", () => {
test('generate default CSP', () => {
expect(generateCspString()).toEqual(defaultCspString);
});

test('add new directive', () => {
expect(
generateCspString({ csp: { 'new-directive-src': "'some text'" } }),
).toContain("new-directive-src 'some text'");
});

test('append directive', () => {
const expected = /default-src .*'some text'/;
expect(generateCsp({ csp: { 'default-src': "'some text'" } })).toMatch(
expected,
);
expect(generateCsp({ csp: { 'default-src': ["'some text'"] } })).toMatch(
expected,
);
expect(
generateCspString({ csp: { 'default-src': "'some text'" } }),
).toMatch(expected);
expect(
generateCspString({ csp: { 'default-src': ["'some text'"] } }),
).toMatch(expected);
});

test('replace directive', () => {
expect(
generateCsp({ csp: { 'default-src': ["'some text'", 'replace'] } }),
generateCspString({ csp: { 'default-src': ["'some text'", 'replace'] } }),
).toContain("default-src 'some text'");
});

test('should add csp to Lambda@Edge Origin response', () => {
expect(getLambdaEdgeOriginResponseZipFile()).toContain(
`value: "${defaultCsp}"`,
`value: "${defaultCspString}"`,
);
});
});
Expand Down
36 changes: 27 additions & 9 deletions packages/cli/src/deploy/staticApp/staticApp.template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,22 @@ const updateCspObject = ({ csp, currentCsp }: { csp: CSP; currentCsp: CSP }) =>
{ ...currentCsp },
);

export const generateCsp = ({ csp = getDefaultCsp() }: { csp?: CSP } = {}) => {
return Object.entries(csp)
.map(([key, value]) => `${key} ${value}`)
.join('; ');
/**
* Generate CSP string from object.
*/
export const generateCspString = ({
csp = getDefaultCsp(),
}: { csp?: CSP } = {}) => {
return (
Object.entries(csp)
/**
* Yargs transform kebab-case to camelCase. Then return only keys that
* end with '-src' {@link https://github.com/ttoss/carlin/issues/11}
*/
.filter(([key]) => key.endsWith('-src'))
.map(([key, value]) => `${key} ${value}`)
.join('; ')
);
};

const assignHeaders = ({ csp }: { csp?: CSP }) => {
Expand All @@ -145,7 +157,7 @@ const assignHeaders = ({ csp }: { csp?: CSP }) => {
headers['content-security-policy'] = [
{
key: 'Content-Security-Policy',
value: "${generateCsp({ csp })}"
value: "${generateCspString({ csp })}"
},
];
headers['x-content-type-options'] = [
Expand Down Expand Up @@ -188,6 +200,9 @@ const LAMBDA_EDGE_VERSION_ORIGIN_REQUEST_LOGICAL_ID =
* implementation was made considering this questions and responses.
* - {@link https://stackoverflow.com/questions/62893845/how-can-i-modify-a-pages-html-with-aws-cloudfront-running-a-lambdaedge-functio}
* - {@link https://stackoverflow.com/questions/51230768/aws-lambdaedge-how-to-read-html-file-from-s3-and-put-content-in-response-body}
*
* When this Lambda@Edge is created, origin response is not created because
* this function make a GET request to S3 and return the body.
*/
const getLambdaEdgeOriginRequestZipFile = ({
gtmId,
Expand Down Expand Up @@ -332,13 +347,14 @@ const LAMBDA_EDGE_VERSION_ORIGIN_RESPONSE_LOGICAL_ID =
'LambdaEdgeVersionOriginResponse';

/**
* - Cache the files whose URL matches the regex expression @see {@link originCacheExpression}.
* This method is only triggered if origin request is not created, because
* origin request return a "body".
*
* - Add some headers to improve security
* Add some headers to improve security
* {@link https://aws.amazon.com/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/}.
*/
export const getLambdaEdgeOriginResponseZipFile = ({
csp,
csp = {},
}: { csp?: CSP } = {}) => {
return `
'use strict';
Expand All @@ -347,7 +363,9 @@ exports.handler = (event, context, callback) => {
const response = event.Records[0].cf.response;
const headers = response.headers;
${assignHeaders({ csp })}
${assignHeaders({
csp: updateCspObject({ csp, currentCsp: getDefaultCsp() }),
})}
callback(null, response);
};
Expand Down

0 comments on commit 62cda51

Please sign in to comment.