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

feat(cloudfront): reportOnly flag on ResponseHeadersContentSecurityPolicy #29031

Closed
wants to merge 73 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
f47fe50
fix-29006 reportOnly flag on ResponseHeadersContentSecurityPolicy
dillonstreator Feb 8, 2024
c9fee16
update readme to show reportOnly field in comprehensive ResponseHeade…
dillonstreator Feb 9, 2024
1c790fd
reorder fields
dillonstreator Feb 9, 2024
14c8284
lint fix
dillonstreator Feb 9, 2024
84d7c91
add @default to jsdoc for optional reportOnly field
dillonstreator Feb 21, 2024
3a55e7e
Merge branch 'main' into fix-29006
paulhcsun Mar 7, 2024
0ea3894
Merge branch 'main' into fix-29006
dillonstreator Mar 8, 2024
552354d
Merge branch 'main' into fix-29006
dillonstreator Mar 8, 2024
e75b4e2
Merge branch 'main' into fix-29006
dillonstreator Mar 8, 2024
fa4b6c4
Merge branch 'main' into fix-29006
dillonstreator Mar 14, 2024
8d9e0d6
Merge branch 'main' into fix-29006
dillonstreator Mar 18, 2024
47f8fac
Merge branch 'main' into fix-29006
dillonstreator Mar 20, 2024
51cb257
Merge branch 'main' into fix-29006
dillonstreator Mar 21, 2024
0aa1f57
Merge branch 'main' into fix-29006
dillonstreator Mar 21, 2024
7118566
Merge branch 'main' into fix-29006
dillonstreator Mar 22, 2024
5ec8407
Merge branch 'main' into fix-29006
dillonstreator Mar 22, 2024
e210249
Merge branch 'main' into fix-29006
dillonstreator Mar 22, 2024
7e124bc
Merge branch 'main' into fix-29006
dillonstreator Mar 23, 2024
4931911
Merge branch 'main' into fix-29006
dillonstreator Mar 25, 2024
15f17e3
Merge branch 'main' into fix-29006
dillonstreator Mar 26, 2024
7611b2e
Merge branch 'main' into fix-29006
dillonstreator Mar 26, 2024
d94ee1f
Merge branch 'main' into fix-29006
dillonstreator Mar 27, 2024
afc4396
Merge branch 'main' into fix-29006
dillonstreator Mar 27, 2024
0509e04
Merge branch 'main' into fix-29006
dillonstreator Mar 27, 2024
30b4705
Merge branch 'main' into fix-29006
dillonstreator Mar 28, 2024
98cfd74
Merge branch 'main' into fix-29006
dillonstreator Mar 29, 2024
e19a082
Merge branch 'main' into fix-29006
dillonstreator Mar 29, 2024
348136a
Merge branch 'main' into fix-29006
dillonstreator Mar 30, 2024
166dabe
Merge branch 'main' into fix-29006
dillonstreator Apr 1, 2024
3ef1f43
Merge branch 'main' into fix-29006
dillonstreator Apr 2, 2024
c6573a2
Merge branch 'main' into fix-29006
dillonstreator Apr 3, 2024
d28adcd
Merge branch 'main' into fix-29006
dillonstreator Apr 3, 2024
8438a60
Merge branch 'main' into fix-29006
dillonstreator Apr 4, 2024
d56cc40
Merge branch 'main' into fix-29006
dillonstreator Apr 4, 2024
f58e951
Merge branch 'main' into fix-29006
dillonstreator Apr 4, 2024
2be701a
Merge branch 'main' into fix-29006
dillonstreator Apr 4, 2024
24b97c3
Merge branch 'main' into fix-29006
dillonstreator Apr 6, 2024
3103a30
Merge branch 'main' into fix-29006
dillonstreator Apr 9, 2024
14d53f9
Merge branch 'main' into fix-29006
dillonstreator Apr 9, 2024
b58598e
Merge branch 'main' into fix-29006
dillonstreator Apr 10, 2024
97c48bc
Merge branch 'main' into fix-29006
dillonstreator Apr 10, 2024
fd200a3
Merge branch 'main' into fix-29006
dillonstreator Apr 11, 2024
324152a
Merge branch 'main' into fix-29006
dillonstreator Apr 11, 2024
6727c67
Merge branch 'main' into fix-29006
dillonstreator Apr 12, 2024
e33fa2c
Merge branch 'main' into fix-29006
dillonstreator Apr 12, 2024
1d3f440
Merge branch 'main' into fix-29006
dillonstreator Apr 13, 2024
63517b5
Merge branch 'main' into fix-29006
dillonstreator Apr 14, 2024
e0494ba
Merge branch 'main' into fix-29006
dillonstreator Apr 15, 2024
50d9da7
Merge branch 'main' into fix-29006
dillonstreator Apr 15, 2024
8afc414
Merge branch 'main' into fix-29006
dillonstreator Apr 16, 2024
ecff3b9
securityHeadersBehavior.contentSecurityPolicy takes precedence with `…
dillonstreator Apr 17, 2024
d9287c6
Merge branch 'main' into fix-29006
dillonstreator Apr 17, 2024
3d68fd0
lint
dillonstreator Apr 17, 2024
e6980b2
Merge branch 'main' into fix-29006
dillonstreator Apr 17, 2024
3a2c2be
Merge branch 'main' into fix-29006
dillonstreator Apr 19, 2024
54d9b06
Merge branch 'main' into fix-29006
dillonstreator Apr 23, 2024
d0b9c16
Merge branch 'main' into fix-29006
dillonstreator Apr 24, 2024
baa9828
Merge branch 'main' into fix-29006
dillonstreator Apr 24, 2024
8a89345
Merge branch 'main' into fix-29006
dillonstreator Apr 25, 2024
3334206
Merge branch 'main' into fix-29006
dillonstreator Apr 26, 2024
dc8da84
Merge branch 'main' into fix-29006
dillonstreator Apr 26, 2024
b317afc
Merge branch 'main' into fix-29006
dillonstreator Apr 30, 2024
ce93883
Merge branch 'main' into fix-29006
dillonstreator Apr 30, 2024
1b509da
Merge branch 'main' into fix-29006
dillonstreator May 1, 2024
0c7a4d6
Merge branch 'main' into fix-29006
dillonstreator May 1, 2024
d7b62b5
Merge branch 'main' into fix-29006
dillonstreator May 2, 2024
8d2d529
Merge branch 'main' into fix-29006
dillonstreator May 2, 2024
937abd9
Merge branch 'main' into fix-29006
dillonstreator May 3, 2024
54398cb
Merge branch 'main' into fix-29006
dillonstreator May 4, 2024
1b4c42c
Merge branch 'main' into fix-29006
dillonstreator May 6, 2024
facb205
Merge branch 'main' into fix-29006
dillonstreator May 6, 2024
1719796
Merge branch 'main' into fix-29006
dillonstreator May 14, 2024
daa3037
Merge branch 'main' into fix-29006
dillonstreator May 14, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/aws-cdk-lib/aws-cloudfront/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ const myResponseHeadersPolicy = new cloudfront.ResponseHeadersPolicy(this, 'Resp
],
},
securityHeadersBehavior: {
contentSecurityPolicy: { contentSecurityPolicy: 'default-src https:;', override: true },
contentSecurityPolicy: { contentSecurityPolicy: 'default-src https:;', reportOnly: true, override: true },
contentTypeOptions: { override: true },
frameOptions: { frameOption: cloudfront.HeadersFrameOption.DENY, override: true },
referrerPolicy: { referrerPolicy: cloudfront.HeadersReferrerPolicy.NO_REFERRER, override: true },
Expand Down
40 changes: 37 additions & 3 deletions packages/aws-cdk-lib/aws-cloudfront/lib/response-headers-policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,40 @@ export class ResponseHeadersPolicy extends Resource implements IResponseHeadersP
maxLength: 128,
});

let securityHeadersBehavior = props.securityHeadersBehavior;
let customHeadersBehavior = props.customHeadersBehavior;

if (securityHeadersBehavior?.contentSecurityPolicy?.reportOnly) {
const reportOnlyCSPHeader = {
header: 'Content-Security-Policy-Report-Only',
value: securityHeadersBehavior.contentSecurityPolicy.contentSecurityPolicy,
override: true,
};
securityHeadersBehavior = {
...securityHeadersBehavior,
contentSecurityPolicy: undefined,
};

if (!customHeadersBehavior) {
customHeadersBehavior = {
customHeaders: [],
};
Comment on lines +131 to +134
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you making this an empty array only if reportOnly is set?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Content-Security-Policy-Report-Only header is only respected as a custom header configuration. The following line is pushing the report only csp header into this customHeaders array. If the customHeadersBehavior object is undefined (which it's allowed to be), we wont have anything to push into.
In the non-report-only configuration case, we don't need to worry about touching the customHeaders array.

}

const existingReportOnlyCSPHeader = customHeadersBehavior.customHeaders.findIndex(ch => ch.header === 'Content-Security-Policy-Report-Only');
if (existingReportOnlyCSPHeader !== -1) {
customHeadersBehavior.customHeaders.splice(existingReportOnlyCSPHeader, 1);
}
customHeadersBehavior.customHeaders.push(reportOnlyCSPHeader);
}

const resource = new CfnResponseHeadersPolicy(this, 'Resource', {
responseHeadersPolicyConfig: {
name: responseHeadersPolicyName,
comment: props.comment,
corsConfig: props.corsBehavior ? this._renderCorsConfig(props.corsBehavior) : undefined,
customHeadersConfig: props.customHeadersBehavior ? this._renderCustomHeadersConfig(props.customHeadersBehavior) : undefined,
securityHeadersConfig: props.securityHeadersBehavior ? this._renderSecurityHeadersConfig(props.securityHeadersBehavior) : undefined,
customHeadersConfig: customHeadersBehavior ? this._renderCustomHeadersConfig(customHeadersBehavior) : undefined,
securityHeadersConfig: securityHeadersBehavior ? this._renderSecurityHeadersConfig(securityHeadersBehavior) : undefined,
removeHeadersConfig: props.removeHeaders ? this._renderRemoveHeadersConfig(props.removeHeaders) : undefined,
serverTimingHeadersConfig: props.serverTimingSamplingRate ? this._renderServerTimingHeadersConfig(props.serverTimingSamplingRate) : undefined,
},
Expand Down Expand Up @@ -156,7 +183,7 @@ export class ResponseHeadersPolicy extends Resource implements IResponseHeadersP
strictTransportSecurity: behavior.strictTransportSecurity ? {
...behavior.strictTransportSecurity,
accessControlMaxAgeSec: behavior.strictTransportSecurity.accessControlMaxAge.toSeconds(),
}: undefined,
} : undefined,
xssProtection: behavior.xssProtection,
};
}
Expand Down Expand Up @@ -337,6 +364,13 @@ export interface ResponseHeadersContentSecurityPolicy {
* received from the origin with the one specified in this response headers policy.
*/
readonly override: boolean;

/**
* A Boolean that determines whether CloudFront includes the -Report-Only suffix in the Content-Security-Policy HTTP response header.
*
* @default - not report only
*/
readonly reportOnly?: boolean;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,57 @@ describe('ResponseHeadersPolicy', () => {
},
});
});

test('it respects CSP `reportOnly` flag by mapping to custom header', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only testing a single logic path. We need to test each of the paths added by this PR.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test hits both new paths introduced by this PR

  • reportOnly being set
  • customHeadersBehavior not existing

new ResponseHeadersPolicy(stack, 'ResponseHeadersPolicy', {
securityHeadersBehavior: {
contentSecurityPolicy: { contentSecurityPolicy: 'default-src https:;', reportOnly: true, override: true },
},
});

Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::ResponseHeadersPolicy', {
ResponseHeadersPolicyConfig: {
CustomHeadersConfig: {
Items: [
{
Header: 'Content-Security-Policy-Report-Only',
Value: 'default-src https:;',
Override: true,
},
],
},
},
});
});

test('securityHeadersBehavior.contentSecurityPolicy takes precedence with `reportOnly`', () => {
new ResponseHeadersPolicy(stack, 'ResponseHeadersPolicy', {
customHeadersBehavior: {
customHeaders: [
{
header: 'Content-Security-Policy-Report-Only',
value: 'default-src self;',
override: true,
},
],
},
securityHeadersBehavior: {
contentSecurityPolicy: { contentSecurityPolicy: 'default-src https:;', reportOnly: true, override: true },
},
});

Template.fromStack(stack).hasResourceProperties('AWS::CloudFront::ResponseHeadersPolicy', {
ResponseHeadersPolicyConfig: {
CustomHeadersConfig: {
Items: [
{
Header: 'Content-Security-Policy-Report-Only',
Value: 'default-src https:;',
Override: true,
},
],
},
},
});
});
});
Loading