Skip to content

Commit d55ad0e

Browse files
authored
chore: a couple more places where ResponseURL is logged (#20977)
Follow-up to #20899, missed a couple of spots. Marking this a `chore` instead of a `fix` since the previous commit will already show up in the CHANGELOG and both this and #20899 will go into the same release. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 277340d commit d55ad0e

File tree

42 files changed

+64
-1437
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+64
-1437
lines changed

packages/@aws-cdk/core/lib/custom-resource-provider/nodejs-entrypoint.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export type HandlerResponse = undefined | {
2222
};
2323

2424
export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent, context: AWSLambda.Context) {
25-
external.log(JSON.stringify(event, undefined, 2));
25+
const sanitizedEvent = { ...event, ResponseURL: '...' };
26+
external.log(JSON.stringify(sanitizedEvent, undefined, 2));
2627

2728
// ignore DELETE event when the physical resource ID is the marker that
2829
// indicates that this DELETE is a subsequent DELETE to a failed CREATE
@@ -39,7 +40,7 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
3940
// cloudformation (otherwise cfn waits).
4041
// eslint-disable-next-line @typescript-eslint/no-require-imports
4142
const userHandler: Handler = require(external.userHandlerIndex).handler;
42-
const result = await userHandler(event, context);
43+
const result = await userHandler(sanitizedEvent, context);
4344

4445
// validate user response and create the combined event
4546
const responseEvent = renderResponse(event, result);

packages/@aws-cdk/custom-resources/README.md

+10
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,16 @@ def is_complete(event, context):
103103
return { 'IsComplete': is_ready }
104104
```
105105

106+
> **Security Note**: the Custom Resource Provider Framework will write the value of `ResponseURL`,
107+
> which is a pre-signed S3 URL used to report the success or failure of the Custom Resource execution
108+
> back to CloudFormation, in a readable form to the AWS Step Functions execution history.
109+
>
110+
> Anybody who can list and read AWS StepFunction executions in your account will be able to write
111+
> a fake response to this URL and make your CloudFormation deployments fail.
112+
>
113+
> Do not use this library if your threat model requires that you cannot trust actors who are able
114+
> to list StepFunction executions in your account.
115+
106116
### Handling Lifecycle Events: onEvent
107117

108118
The user-defined `onEvent` AWS Lambda function is invoked whenever a resource

packages/@aws-cdk/custom-resources/lib/provider-framework/runtime/framework.ts

+10-7
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ export = {
2424
* @param cfnRequest The cloudformation custom resource event.
2525
*/
2626
async function onEvent(cfnRequest: AWSLambda.CloudFormationCustomResourceEvent) {
27-
log('onEventHandler', { ...cfnRequest, ResponseURL: '...' });
27+
const sanitizedRequest = { ...cfnRequest, ResponseURL: '...' } as const;
28+
log('onEventHandler', sanitizedRequest);
2829

2930
cfnRequest.ResourceProperties = cfnRequest.ResourceProperties || { };
3031

31-
const onEventResult = await invokeUserFunction(consts.USER_ON_EVENT_FUNCTION_ARN_ENV, cfnRequest) as OnEventResponse;
32+
const onEventResult = await invokeUserFunction(consts.USER_ON_EVENT_FUNCTION_ARN_ENV, sanitizedRequest) as OnEventResponse;
3233
log('onEvent returned:', onEventResult);
3334

3435
// merge the request and the result from onEvent to form the complete resource event
@@ -57,9 +58,10 @@ async function onEvent(cfnRequest: AWSLambda.CloudFormationCustomResourceEvent)
5758

5859
// invoked a few times until `complete` is true or until it times out.
5960
async function isComplete(event: AWSCDKAsyncCustomResource.IsCompleteRequest) {
60-
log('isComplete', event);
61+
const sanitizedRequest = { ...event, ResponseURL: '...' } as const;
62+
log('isComplete', sanitizedRequest);
6163

62-
const isCompleteResult = await invokeUserFunction(consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV, event) as IsCompleteResponse;
64+
const isCompleteResult = await invokeUserFunction(consts.USER_IS_COMPLETE_FUNCTION_ARN_ENV, sanitizedRequest) as IsCompleteResponse;
6365
log('user isComplete returned:', isCompleteResult);
6466

6567
// if we are not complete, return false, and don't send a response back.
@@ -68,6 +70,7 @@ async function isComplete(event: AWSCDKAsyncCustomResource.IsCompleteRequest) {
6870
throw new Error('"Data" is not allowed if "IsComplete" is "False"');
6971
}
7072

73+
// This must be the full event, it will be deserialized in `onTimeout` to send the response to CloudFormation
7174
throw new cfnResponse.Retry(JSON.stringify(event));
7275
}
7376

@@ -93,9 +96,9 @@ async function onTimeout(timeoutEvent: any) {
9396
});
9497
}
9598

96-
async function invokeUserFunction(functionArnEnv: string, payload: any) {
99+
async function invokeUserFunction<A extends { ResponseURL: '...' }>(functionArnEnv: string, sanitizedPayload: A) {
97100
const functionArn = getEnv(functionArnEnv);
98-
log(`executing user function ${functionArn} with payload`, payload);
101+
log(`executing user function ${functionArn} with payload`, sanitizedPayload);
99102

100103
// transient errors such as timeouts, throttling errors (429), and other
101104
// errors that aren't caused by a bad request (500 series) are retried
@@ -104,7 +107,7 @@ async function invokeUserFunction(functionArnEnv: string, payload: any) {
104107
FunctionName: functionArn,
105108

106109
// Strip 'ResponseURL' -- the downstream CR doesn't need it and can only log it by accident
107-
Payload: JSON.stringify({ ...payload, ResponseURL: undefined }),
110+
Payload: JSON.stringify({ ...sanitizedPayload, ResponseURL: undefined }),
108111
});
109112

110113
log('user function response:', resp, typeof(resp));

packages/@aws-cdk/pipelines/test/pipeline-security.integ.snapshot/PipelineSecurityStack.assets.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
{
22
"version": "20.0.0",
33
"files": {
4-
"17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb": {
4+
"60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26": {
55
"source": {
6-
"path": "asset.17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb",
6+
"path": "asset.60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26",
77
"packaging": "zip"
88
},
99
"destinations": {
1010
"current_account-current_region": {
1111
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12-
"objectKey": "17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb.zip",
12+
"objectKey": "60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26.zip",
1313
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
1414
}
1515
}
@@ -27,15 +27,15 @@
2727
}
2828
}
2929
},
30-
"7f17b1fbdb3783f2f992a94602a37c674f58741617a65f348b43ba1a7637a115": {
30+
"ff8909e2b3e01298b53c87d97e8e745b4f0b2e4b6d29d5680c44e5da87a207a4": {
3131
"source": {
3232
"path": "PipelineSecurityStack.template.json",
3333
"packaging": "file"
3434
},
3535
"destinations": {
3636
"current_account-current_region": {
3737
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
38-
"objectKey": "7f17b1fbdb3783f2f992a94602a37c674f58741617a65f348b43ba1a7637a115.json",
38+
"objectKey": "ff8909e2b3e01298b53c87d97e8e745b4f0b2e4b6d29d5680c44e5da87a207a4.json",
3939
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
4040
}
4141
}

packages/@aws-cdk/pipelines/test/pipeline-security.integ.snapshot/PipelineSecurityStack.template.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
"S3Bucket": {
113113
"Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}"
114114
},
115-
"S3Key": "17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb.zip"
115+
"S3Key": "60767da3831353fede3cfe92efef10580a600592dec8ccbb06c051e95b9c1b26.zip"
116116
},
117117
"Timeout": 900,
118118
"MemorySize": 128,

packages/@aws-cdk/pipelines/test/pipeline-security.integ.snapshot/asset.17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/__entrypoint__.js

-117
This file was deleted.

packages/@aws-cdk/pipelines/test/pipeline-security.integ.snapshot/asset.17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/index.d.ts

-1
This file was deleted.

packages/@aws-cdk/pipelines/test/pipeline-security.integ.snapshot/asset.17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/index.js

-78
This file was deleted.

packages/@aws-cdk/pipelines/test/pipeline-security.integ.snapshot/asset.17cb4b37288c269a54418db6e9c7c3763b2d1a82bdc374be4653bd366345eccb/index.ts

-82
This file was deleted.

0 commit comments

Comments
 (0)