Skip to content

Commit 545c5cd

Browse files
authored
Merge branch 'master' into feat/rds-paramaeter-group
2 parents a64ba83 + 846a222 commit 545c5cd

9 files changed

Lines changed: 479 additions & 25 deletions

File tree

packages/@aws-cdk/aws-rds/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,13 @@ import * as secrets from '@aws-cdk/aws-secretsmanager';
252252

253253
const vpc: ec2.IVpc = ...;
254254
const securityGroup: ec2.ISecurityGroup = ...;
255-
const secret: secrets.ISecret = ...;
255+
const secrets: secrets.ISecret[] = [...];
256256
const dbInstance: rds.IDatabaseInstance = ...;
257257

258258
const proxy = dbInstance.addProxy('proxy', {
259259
connectionBorrowTimeout: cdk.Duration.seconds(30),
260260
maxConnectionsPercent: 50,
261-
secret,
261+
secrets,
262262
vpc,
263263
});
264264
```

packages/@aws-cdk/aws-rds/lib/proxy.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -235,10 +235,9 @@ export interface DatabaseProxyOptions {
235235
/**
236236
* The secret that the proxy uses to authenticate to the RDS DB instance or Aurora DB cluster.
237237
* These secrets are stored within Amazon Secrets Manager.
238-
*
239-
* @default - no secret
238+
* One or more secrets are required.
240239
*/
241-
readonly secret: secretsmanager.ISecret;
240+
readonly secrets: secretsmanager.ISecret[];
242241

243242
/**
244243
* One or more VPC security groups to associate with the new proxy.
@@ -379,20 +378,26 @@ export class DatabaseProxy extends cdk.Resource
379378
assumedBy: new iam.ServicePrincipal('rds.amazonaws.com'),
380379
});
381380

382-
props.secret.grantRead(role);
381+
for (const secret of props.secrets) {
382+
secret.grantRead(role);
383+
}
383384

384385
this.connections = new ec2.Connections({ securityGroups: props.securityGroups });
385386

386387
const bindResult = props.proxyTarget.bind(this);
387388

389+
if (props.secrets.length < 1) {
390+
throw new Error('One or more secrets are required.');
391+
}
392+
388393
this.resource = new CfnDBProxy(this, 'Resource', {
389-
auth: [
390-
{
394+
auth: props.secrets.map(_ => {
395+
return {
391396
authScheme: 'SECRETS',
392397
iamAuth: props.iamAuth ? 'REQUIRED' : 'DISABLED',
393-
secretArn: props.secret.secretArn,
394-
},
395-
],
398+
secretArn: _.secretArn,
399+
};
400+
}),
396401
dbProxyName: this.physicalName,
397402
debugLogging: props.debugLogging,
398403
engineFamily: bindResult.engineFamily,

packages/@aws-cdk/aws-rds/test/integ.proxy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const dbInstance = new rds.DatabaseInstance(stack, 'dbInstance', {
1717
new rds.DatabaseProxy(stack, 'dbProxy', {
1818
borrowTimeout: cdk.Duration.seconds(30),
1919
maxConnectionsPercent: 50,
20-
secret: dbInstance.secret!,
20+
secrets: [dbInstance.secret!],
2121
proxyTarget: rds.ProxyTarget.fromInstance(dbInstance),
2222
vpc,
2323
});

packages/@aws-cdk/aws-rds/test/test.proxy.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export = {
1919
// WHEN
2020
new rds.DatabaseProxy(stack, 'Proxy', {
2121
proxyTarget: rds.ProxyTarget.fromInstance(instance),
22-
secret: instance.secret!,
22+
secrets: [instance.secret!],
2323
vpc,
2424
});
2525

@@ -94,7 +94,7 @@ export = {
9494
// WHEN
9595
new rds.DatabaseProxy(stack, 'Proxy', {
9696
proxyTarget: rds.ProxyTarget.fromCluster(cluster),
97-
secret: cluster.secret!,
97+
secrets: [cluster.secret!],
9898
vpc,
9999
});
100100

@@ -170,7 +170,7 @@ export = {
170170
test.doesNotThrow(() => {
171171
new rds.DatabaseProxy(stack, 'Proxy', {
172172
proxyTarget: rds.ProxyTarget.fromCluster(cluster),
173-
secret: cluster.secret!,
173+
secrets: [cluster.secret!],
174174
vpc,
175175
});
176176
}, /Cannot specify both dbInstanceIdentifiers and dbClusterIdentifiers/);
@@ -181,4 +181,29 @@ export = {
181181

182182
test.done();
183183
},
184+
185+
'One or more secrets are required.'(test: Test) {
186+
// GIVEN
187+
const stack = new cdk.Stack();
188+
const vpc = new ec2.Vpc(stack, 'VPC');
189+
const cluster = new rds.DatabaseCluster(stack, 'Database', {
190+
engine: rds.DatabaseClusterEngine.auroraPostgres({ version: '10.7' }),
191+
masterUser: { username: 'admin' },
192+
instanceProps: {
193+
instanceType: ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE2, ec2.InstanceSize.SMALL),
194+
vpc,
195+
},
196+
});
197+
198+
// WHEN
199+
test.throws(() => {
200+
new rds.DatabaseProxy(stack, 'Proxy', {
201+
proxyTarget: rds.ProxyTarget.fromCluster(cluster),
202+
secrets: [], // No secret
203+
vpc,
204+
});
205+
}, 'One or more secrets are required.');
206+
207+
test.done();
208+
},
184209
};

packages/@aws-cdk/aws-stepfunctions-tasks/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,19 @@ new tasks.LambdaInvoke(this, 'Invoke and set function response as task output',
623623
});
624624
```
625625

626+
If you want to combine the input and the Lambda function response you can use
627+
the `payloadResponseOnly` property and specify the `resultPath`. This will put the
628+
Lambda function ARN directly in the "Resource" string, but it conflicts with the
629+
integrationPattern, invocationType, clientContext, and qualifier properties.
630+
631+
```ts
632+
new tasks.LambdaInvoke(this, 'Invoke and combine function response with task input', {
633+
lambdaFunction: myLambda,
634+
payloadResponseOnly: true,
635+
resultPath: '$.myLambda',
636+
});
637+
```
638+
626639
You can have Step Functions pause a task, and wait for an external process to
627640
return a task token. Read more about the [callback pattern](https://docs.aws.amazon.com/step-functions/latest/dg/callback-task-sample-sqs.html#call-back-lambda-example)
628641

packages/@aws-cdk/aws-stepfunctions-tasks/lib/lambda/invoke.ts

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ export interface LambdaInvokeProps extends sfn.TaskStateBaseProps {
4646
* @default - Version or alias inherent to the `lambdaFunction` object.
4747
*/
4848
readonly qualifier?: string;
49+
50+
/**
51+
* Invoke the Lambda in a way that only returns the payload response without additional metadata.
52+
*
53+
* The `payloadResponseOnly` property cannot be used if `integrationPattern`, `invocationType`,
54+
* `clientContext`, or `qualifier` are specified.
55+
* It always uses the REQUEST_RESPONSE behavior.
56+
*
57+
* @default false
58+
*/
59+
readonly payloadResponseOnly?: boolean;
4960
}
5061

5162
/**
@@ -76,6 +87,13 @@ export class LambdaInvoke extends sfn.TaskStateBase {
7687
throw new Error('Task Token is required in `payload` for callback. Use JsonPath.taskToken to set the token.');
7788
}
7889

90+
if (props.payloadResponseOnly &&
91+
(props.integrationPattern || props.invocationType || props.clientContext || props.qualifier)) {
92+
throw new Error(
93+
"The 'payloadResponseOnly' property cannot be used if 'integrationPattern', 'invocationType', 'clientContext', or 'qualifier' are specified.",
94+
);
95+
}
96+
7997
this.taskMetrics = {
8098
metricPrefixSingular: 'LambdaFunction',
8199
metricPrefixPlural: 'LambdaFunctions',
@@ -100,16 +118,23 @@ export class LambdaInvoke extends sfn.TaskStateBase {
100118
* @internal
101119
*/
102120
protected _renderTask(): any {
103-
return {
104-
Resource: integrationResourceArn('lambda', 'invoke', this.integrationPattern),
105-
Parameters: sfn.FieldUtils.renderObject({
106-
FunctionName: this.props.lambdaFunction.functionArn,
107-
Payload: this.props.payload ? this.props.payload.value : sfn.TaskInput.fromDataAt('$').value,
108-
InvocationType: this.props.invocationType,
109-
ClientContext: this.props.clientContext,
110-
Qualifier: this.props.qualifier,
111-
}),
112-
};
121+
if (this.props.payloadResponseOnly) {
122+
return {
123+
Resource: this.props.lambdaFunction.functionArn,
124+
...this.props.payload && { Parameters: sfn.FieldUtils.renderObject(this.props.payload.value) },
125+
};
126+
} else {
127+
return {
128+
Resource: integrationResourceArn('lambda', 'invoke', this.integrationPattern),
129+
Parameters: sfn.FieldUtils.renderObject({
130+
FunctionName: this.props.lambdaFunction.functionArn,
131+
Payload: this.props.payload ? this.props.payload.value : sfn.TaskInput.fromDataAt('$').value,
132+
InvocationType: this.props.invocationType,
133+
ClientContext: this.props.clientContext,
134+
Qualifier: this.props.qualifier,
135+
}),
136+
};
137+
}
113138
}
114139
}
115140

0 commit comments

Comments
 (0)