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

Commit

Permalink
fix: fixes #26
Browse files Browse the repository at this point in the history
  • Loading branch information
arantespp committed Mar 1, 2021
1 parent 1c8b6b8 commit c04ec9d
Show file tree
Hide file tree
Showing 2 changed files with 253 additions and 27 deletions.
218 changes: 192 additions & 26 deletions packages/cli/src/deploy/staticApp/staticApp.template.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,206 @@ import {
getStaticAppTemplate,
generateCspString,
getLambdaEdgeOriginRequestZipFile,
getLambdaEdgeOriginResponseZipFile,
CLOUDFRONT_DISTRIBUTION_LOGICAL_ID,
LAMBDA_EDGE_IAM_ROLE_LOGICAL_ID,
LAMBDA_EDGE_VERSION_ORIGIN_REQUEST_LOGICAL_ID,
LAMBDA_EDGE_VERSION_ORIGIN_RESPONSE_LOGICAL_ID,
} from './staticApp.template';

const defaultCspString =
"default-src 'self'; connect-src 'self' https:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com/; font-src 'self' https://fonts.gstatic.com/; object-src 'none'";

const securityHeaders = {
'content-security-policy': [
{
key: 'Content-Security-Policy',
value:
"default-src 'self'; connect-src 'self' https:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com/; font-src 'self' https://fonts.gstatic.com/; object-src 'none'",
},
],
'referrer-policy': [{ key: 'Referrer-Policy', value: 'same-origin' }],
'strict-transport-security': [
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubdomains; preload',
},
],
'x-content-type-options': [
{ key: 'X-Content-Type-Options', value: 'nosniff' },
],
'x-frame-options': [{ key: 'X-Frame-Options', value: 'DENY' }],
'x-xss-protection': [{ key: 'X-XSS-Protection', value: '1; mode=block' }],
};

const cachingHeaders = {
'cache-control': [{ key: 'Cache-Control', value: 'max-age=30' }],
};

describe('Issue #26 https://github.com/ttoss/carlin/issues/26', () => {
/**
* https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html#lambda-event-structure-response-origin
*/
const event = {
Records: [
{
cf: {
config: {
distributionDomainName: 'd111111abcdef8.cloudfront.net',
distributionId: 'EDFDVBD6EXAMPLE',
eventType: 'origin-response',
requestId:
'4TyzHTaYWb1GX1qTfsHhEqV6HUDd_BzoBZnwfnvQc_1oF26ClkoUSEQ==',
},
request: {
clientIp: '203.0.113.178',
headers: {
'x-forwarded-for': [
{
key: 'X-Forwarded-For',
value: '203.0.113.178',
},
],
'user-agent': [
{
key: 'User-Agent',
value: 'Amazon CloudFront',
},
],
via: [
{
key: 'Via',
value:
'2.0 8f22423015641505b8c857a37450d6c0.cloudfront.net (CloudFront)',
},
],
host: [
{
key: 'Host',
value: 'example.org',
},
],
'cache-control': [
{
key: 'Cache-Control',
value: 'no-cache, cf-no-cache',
},
],
},
method: 'GET',
origin: {
custom: {
customHeaders: {},
domainName: 'example.org',
keepaliveTimeout: 5,
path: '',
port: 443,
protocol: 'https',
readTimeout: 30,
sslProtocols: ['TLSv1', 'TLSv1.1', 'TLSv1.2'],
},
},
querystring: '',
uri: '/',
},
response: {
headers: {
'access-control-allow-credentials': [
{
key: 'Access-Control-Allow-Credentials',
value: 'true',
},
],
'access-control-allow-origin': [
{
key: 'Access-Control-Allow-Origin',
value: '*',
},
],
date: [
{
key: 'Date',
value: 'Mon, 13 Jan 2020 20:12:38 GMT',
},
],
'referrer-policy': [
{
key: 'Referrer-Policy',
value: 'no-referrer-when-downgrade',
},
],
server: [
{
key: 'Server',
value: 'ExampleCustomOriginServer',
},
],
'x-content-type-options': [
{
key: 'X-Content-Type-Options',
value: 'nosniff',
},
],
'x-frame-options': [
{
key: 'X-Frame-Options',
value: 'DENY',
},
],
'x-xss-protection': [
{
key: 'X-XSS-Protection',
value: '1; mode=block',
},
],
'content-type': [
{
key: 'Content-Type',
value: 'text/html; charset=utf-8',
},
],
'content-length': [
{
key: 'Content-Length',
value: '9593',
},
],
},
status: '200',
statusDescription: 'OK',
},
},
},
],
};

const handler = () => eval(getLambdaEdgeOriginResponseZipFile())(event);

test('headers should be added properly', async () => {
const response = await handler();
expect(response.headers).toEqual(expect.objectContaining(securityHeaders));
expect(response.headers).toEqual(expect.objectContaining(cachingHeaders));
});

test('getLambdaEdgeOriginResponseZipFile should have been added to CloudFormation template', () => {
expect(
getStaticAppTemplate({ region, cloudfront: true }).Resources[
CLOUDFRONT_DISTRIBUTION_LOGICAL_ID
].Properties.DistributionConfig.DefaultCacheBehavior
.LambdaFunctionAssociations,
).toEqual(
expect.arrayContaining([
{
EventType: 'origin-response',
LambdaFunctionARN: {
'Fn::GetAtt': `${LAMBDA_EDGE_VERSION_ORIGIN_RESPONSE_LOGICAL_ID}.FunctionArn`,
},
},
]),
);
});
});

describe('testing getLambdaEdgeOriginRequestZipFile', () => {
const gtmId = faker.random.word();
const bucketName = faker.random.word();
Expand Down Expand Up @@ -151,32 +343,6 @@ describe('testing getLambdaEdgeOriginRequestZipFile', () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { 'cache-control': _, ...requestHeaders } = record.cf.request.headers;

const securityHeaders = {
'content-security-policy': [
{
key: 'Content-Security-Policy',
value:
"default-src 'self'; connect-src 'self' https:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com/; font-src 'self' https://fonts.gstatic.com/; object-src 'none'",
},
],
'referrer-policy': [{ key: 'Referrer-Policy', value: 'same-origin' }],
'strict-transport-security': [
{
key: 'Strict-Transport-Security',
value: 'max-age=63072000; includeSubdomains; preload',
},
],
'x-content-type-options': [
{ key: 'X-Content-Type-Options', value: 'nosniff' },
],
'x-frame-options': [{ key: 'X-Frame-Options', value: 'DENY' }],
'x-xss-protection': [{ key: 'X-XSS-Protection', value: '1; mode=block' }],
};

const cachingHeaders = {
'cache-control': [{ key: 'Cache-Control', value: 'max-age=30' }],
};

const handler = (event: any = defaultEvent) =>
eval(
getLambdaEdgeOriginRequestZipFile({ region }).replace(
Expand Down
62 changes: 61 additions & 1 deletion packages/cli/src/deploy/staticApp/staticApp.template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ const crypto = require('crypto');
const s3 = new S3({ region: "${region}" });
exports.handler = async (event, context) => {
const request = { ...event.Records[0].cf.request };
const request = event.Records[0].cf.request;
const headers = request.headers;
Expand Down Expand Up @@ -440,6 +440,36 @@ exports.handler = async (event, context) => {
);
};

const LAMBDA_EDGE_ORIGIN_RESPONSE_LOGICAL_ID = 'LambdaEdgeOriginResponse';

export const LAMBDA_EDGE_VERSION_ORIGIN_RESPONSE_LOGICAL_ID =
'LambdaEdgeVersionOriginResponse';

/**
* This method is only triggered if origin request doesn't return a body.
*/
export const getLambdaEdgeOriginResponseZipFile = ({
csp = {},
}: { csp?: CSP } = {}) => {
return formatCode(`
'use strict';
exports.handler = async (event, context) => {
const request = event.Records[0].cf.request;
const response = event.Records[0].cf.response;
const headers = response.headers;
${assignSecurityHeaders({
csp: updateCspObject({ csp, currentCsp: getDefaultCsp() }),
})}
${assignCachingHeaders({})}
return response;
};
`);
};

const getBaseTemplate = ({
cloudfront,
spa,
Expand Down Expand Up @@ -652,6 +682,30 @@ const getCloudFrontEdgeLambdas = ({
},
},
},
[LAMBDA_EDGE_ORIGIN_RESPONSE_LOGICAL_ID]: {
Type: 'AWS::Lambda::Function',
Properties: {
Code: { ZipFile: getLambdaEdgeOriginResponseZipFile({ csp }) },
Description: 'Lambda@Edge function serving as origin response.',
Handler: 'index.handler',
MemorySize: 128,
Role: { 'Fn::GetAtt': `${LAMBDA_EDGE_IAM_ROLE_LOGICAL_ID}.Arn` },
Runtime: 'nodejs12.x',
Timeout: 5,
},
},
[LAMBDA_EDGE_VERSION_ORIGIN_RESPONSE_LOGICAL_ID]: {
Type: 'Custom::LatestLambdaVersion',
Properties: {
FunctionName: {
Ref: LAMBDA_EDGE_ORIGIN_RESPONSE_LOGICAL_ID,
},
Nonce: `${Date.now()}`,
ServiceToken: {
'Fn::GetAtt': `${PUBLISH_LAMBDA_VERSION_LOGICAL_ID}.Arn`,
},
},
},
};

return lambdaEdgeResources;
Expand Down Expand Up @@ -751,6 +805,12 @@ const getCloudFrontTemplate = ({
},
]
: []),
{
EventType: 'origin-response',
LambdaFunctionARN: {
'Fn::GetAtt': `${LAMBDA_EDGE_VERSION_ORIGIN_RESPONSE_LOGICAL_ID}.FunctionArn`,
},
},
],
TargetOriginId: { Ref: STATIC_APP_BUCKET_LOGICAL_ID },
ViewerProtocolPolicy: 'redirect-to-https',
Expand Down

0 comments on commit c04ec9d

Please sign in to comment.