From 14561aca0ad9c0d5eef29729dbc97fc3ccd4d171 Mon Sep 17 00:00:00 2001 From: Nicholas Omer Chiasson Date: Thu, 31 Oct 2024 20:37:24 +0000 Subject: [PATCH 01/42] fix(aws_route53): cannot use CfnParameter.valueAsNumber for L2 RecordSet weight (#31823) ### Issue # (if applicable) Closes #31810. ### Reason for this change Could not use CfnParameter.valueAsNumber for L2 RecordSet weight. ### Description of changes Adding validation of weight property as a potential Token in RecordSet constructor. ### Description of how you validated changes Added unit and integration test. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...efaultTestDeployAssertB313B703.assets.json | 19 + ...aultTestDeployAssertB313B703.template.json | 36 ++ .../cdk.out | 1 + .../integ.json | 12 + .../manifest.json | 163 +++++++++ ...ecord-weight-from-cfnparameter.assets.json | 19 + ...ord-weight-from-cfnparameter.template.json | 184 ++++++++++ .../tree.json | 345 ++++++++++++++++++ .../integ.record-weight-from-cfnparameter.ts | 44 +++ .../aws-cdk-lib/aws-route53/lib/record-set.ts | 13 +- .../aws-route53/test/record-set.test.ts | 62 +++- 11 files changed, 894 insertions(+), 4 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/record-weight-from-cfnparameter.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/record-weight-from-cfnparameter.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.assets.json new file mode 100644 index 0000000000000..7490b2af331b6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/cdk.out new file mode 100644 index 0000000000000..c6e612584e352 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/integ.json new file mode 100644 index 0000000000000..c30c931da4d49 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "38.0.1", + "testCases": { + "Route53RecordWeightFromCfnParameterInteg/DefaultTest": { + "stacks": [ + "record-weight-from-cfnparameter" + ], + "assertionStack": "Route53RecordWeightFromCfnParameterInteg/DefaultTest/DeployAssert", + "assertionStackName": "Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/manifest.json new file mode 100644 index 0000000000000..097e080ec6024 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/manifest.json @@ -0,0 +1,163 @@ +{ + "version": "38.0.1", + "artifacts": { + "record-weight-from-cfnparameter.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "record-weight-from-cfnparameter.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "record-weight-from-cfnparameter": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "record-weight-from-cfnparameter.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "notificationArns": [], + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/9603704f36aac4a47218ab44a07a0ea096d4ef0e4c35203a39f72aef7b709c33.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "record-weight-from-cfnparameter.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "record-weight-from-cfnparameter.assets" + ], + "metadata": { + "/record-weight-from-cfnparameter/HostedZone/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "HostedZoneDB99F866" + } + ], + "/record-weight-from-cfnparameter/RecordWeight0": [ + { + "type": "aws:cdk:logicalId", + "data": "RecordWeight0" + } + ], + "/record-weight-from-cfnparameter/RecordWeight1": [ + { + "type": "aws:cdk:logicalId", + "data": "RecordWeight1" + } + ], + "/record-weight-from-cfnparameter/RecordWeight2": [ + { + "type": "aws:cdk:logicalId", + "data": "RecordWeight2" + } + ], + "/record-weight-from-cfnparameter/RecordWeight3": [ + { + "type": "aws:cdk:logicalId", + "data": "RecordWeight3" + } + ], + "/record-weight-from-cfnparameter/RecordWithParamWeight0/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RecordWithParamWeight01950FDF7" + } + ], + "/record-weight-from-cfnparameter/RecordWithParamWeight1/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RecordWithParamWeight182FF0BDE" + } + ], + "/record-weight-from-cfnparameter/RecordWithParamWeight2/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RecordWithParamWeight2C5120D0E" + } + ], + "/record-weight-from-cfnparameter/RecordWithParamWeight3/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "RecordWithParamWeight37D431545" + } + ], + "/record-weight-from-cfnparameter/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/record-weight-from-cfnparameter/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "record-weight-from-cfnparameter" + }, + "Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "notificationArns": [], + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "Route53RecordWeightFromCfnParameterIntegDefaultTestDeployAssertB313B703.assets" + ], + "metadata": { + "/Route53RecordWeightFromCfnParameterInteg/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/Route53RecordWeightFromCfnParameterInteg/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "Route53RecordWeightFromCfnParameterInteg/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/record-weight-from-cfnparameter.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/record-weight-from-cfnparameter.assets.json new file mode 100644 index 0000000000000..739fa4bf65e2e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/record-weight-from-cfnparameter.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "9603704f36aac4a47218ab44a07a0ea096d4ef0e4c35203a39f72aef7b709c33": { + "source": { + "path": "record-weight-from-cfnparameter.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "9603704f36aac4a47218ab44a07a0ea096d4ef0e4c35203a39f72aef7b709c33.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/record-weight-from-cfnparameter.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/record-weight-from-cfnparameter.template.json new file mode 100644 index 0000000000000..6a96397fb1b62 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/record-weight-from-cfnparameter.template.json @@ -0,0 +1,184 @@ +{ + "Resources": { + "HostedZoneDB99F866": { + "Type": "AWS::Route53::HostedZone", + "Properties": { + "Name": "cdk.dev." + } + }, + "RecordWithParamWeight01950FDF7": { + "Type": "AWS::Route53::RecordSet", + "Properties": { + "HostedZoneId": { + "Ref": "HostedZoneDB99F866" + }, + "Name": "www.cdk.dev.", + "ResourceRecords": [ + "1.2.3.4" + ], + "SetIdentifier": { + "Fn::Join": [ + "", + [ + "WEIGHT_", + { + "Ref": "RecordWeight0" + }, + "_ID_recordweightfromcfnpaecordWithParamWeight059BCC4E1" + ] + ] + }, + "TTL": "10", + "Type": "A", + "Weight": { + "Ref": "RecordWeight0" + } + } + }, + "RecordWithParamWeight182FF0BDE": { + "Type": "AWS::Route53::RecordSet", + "Properties": { + "HostedZoneId": { + "Ref": "HostedZoneDB99F866" + }, + "Name": "www.cdk.dev.", + "ResourceRecords": [ + "2.3.4.5" + ], + "SetIdentifier": { + "Fn::Join": [ + "", + [ + "WEIGHT_", + { + "Ref": "RecordWeight1" + }, + "_ID_recordweightfromcfnpaecordWithParamWeight1304B1475" + ] + ] + }, + "TTL": "10", + "Type": "A", + "Weight": { + "Ref": "RecordWeight1" + } + } + }, + "RecordWithParamWeight2C5120D0E": { + "Type": "AWS::Route53::RecordSet", + "Properties": { + "HostedZoneId": { + "Ref": "HostedZoneDB99F866" + }, + "Name": "www.cdk.dev.", + "ResourceRecords": [ + "3.4.5.6" + ], + "SetIdentifier": { + "Fn::Join": [ + "", + [ + "WEIGHT_", + { + "Ref": "RecordWeight2" + }, + "_ID_recordweightfromcfnpaecordWithParamWeight25B9D18F1" + ] + ] + }, + "TTL": "10", + "Type": "A", + "Weight": { + "Ref": "RecordWeight2" + } + } + }, + "RecordWithParamWeight37D431545": { + "Type": "AWS::Route53::RecordSet", + "Properties": { + "HostedZoneId": { + "Ref": "HostedZoneDB99F866" + }, + "Name": "www.cdk.dev.", + "ResourceRecords": [ + "4.5.6.7" + ], + "SetIdentifier": { + "Fn::Join": [ + "", + [ + "WEIGHT_", + { + "Ref": "RecordWeight3" + }, + "_ID_recordweightfromcfnpaecordWithParamWeight37DA83B23" + ] + ] + }, + "TTL": "10", + "Type": "A", + "Weight": { + "Ref": "RecordWeight3" + } + } + } + }, + "Parameters": { + "RecordWeight0": { + "Type": "Number", + "Default": 0, + "MaxValue": 255, + "MinValue": 0 + }, + "RecordWeight1": { + "Type": "Number", + "Default": 0, + "MaxValue": 255, + "MinValue": 0 + }, + "RecordWeight2": { + "Type": "Number", + "Default": 0, + "MaxValue": 255, + "MinValue": 0 + }, + "RecordWeight3": { + "Type": "Number", + "Default": 0, + "MaxValue": 255, + "MinValue": 0 + }, + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/tree.json new file mode 100644 index 0000000000000..17c358fac61fc --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.js.snapshot/tree.json @@ -0,0 +1,345 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "record-weight-from-cfnparameter": { + "id": "record-weight-from-cfnparameter", + "path": "record-weight-from-cfnparameter", + "children": { + "HostedZone": { + "id": "HostedZone", + "path": "record-weight-from-cfnparameter/HostedZone", + "children": { + "Resource": { + "id": "Resource", + "path": "record-weight-from-cfnparameter/HostedZone/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Route53::HostedZone", + "aws:cdk:cloudformation:props": { + "name": "cdk.dev." + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RecordWeight0": { + "id": "RecordWeight0", + "path": "record-weight-from-cfnparameter/RecordWeight0", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RecordWeight1": { + "id": "RecordWeight1", + "path": "record-weight-from-cfnparameter/RecordWeight1", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RecordWeight2": { + "id": "RecordWeight2", + "path": "record-weight-from-cfnparameter/RecordWeight2", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RecordWeight3": { + "id": "RecordWeight3", + "path": "record-weight-from-cfnparameter/RecordWeight3", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RecordWithParamWeight0": { + "id": "RecordWithParamWeight0", + "path": "record-weight-from-cfnparameter/RecordWithParamWeight0", + "children": { + "Resource": { + "id": "Resource", + "path": "record-weight-from-cfnparameter/RecordWithParamWeight0/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Route53::RecordSet", + "aws:cdk:cloudformation:props": { + "hostedZoneId": { + "Ref": "HostedZoneDB99F866" + }, + "name": "www.cdk.dev.", + "resourceRecords": [ + "1.2.3.4" + ], + "setIdentifier": { + "Fn::Join": [ + "", + [ + "WEIGHT_", + { + "Ref": "RecordWeight0" + }, + "_ID_recordweightfromcfnpaecordWithParamWeight059BCC4E1" + ] + ] + }, + "ttl": "10", + "type": "A", + "weight": { + "Ref": "RecordWeight0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RecordWithParamWeight1": { + "id": "RecordWithParamWeight1", + "path": "record-weight-from-cfnparameter/RecordWithParamWeight1", + "children": { + "Resource": { + "id": "Resource", + "path": "record-weight-from-cfnparameter/RecordWithParamWeight1/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Route53::RecordSet", + "aws:cdk:cloudformation:props": { + "hostedZoneId": { + "Ref": "HostedZoneDB99F866" + }, + "name": "www.cdk.dev.", + "resourceRecords": [ + "2.3.4.5" + ], + "setIdentifier": { + "Fn::Join": [ + "", + [ + "WEIGHT_", + { + "Ref": "RecordWeight1" + }, + "_ID_recordweightfromcfnpaecordWithParamWeight1304B1475" + ] + ] + }, + "ttl": "10", + "type": "A", + "weight": { + "Ref": "RecordWeight1" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RecordWithParamWeight2": { + "id": "RecordWithParamWeight2", + "path": "record-weight-from-cfnparameter/RecordWithParamWeight2", + "children": { + "Resource": { + "id": "Resource", + "path": "record-weight-from-cfnparameter/RecordWithParamWeight2/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Route53::RecordSet", + "aws:cdk:cloudformation:props": { + "hostedZoneId": { + "Ref": "HostedZoneDB99F866" + }, + "name": "www.cdk.dev.", + "resourceRecords": [ + "3.4.5.6" + ], + "setIdentifier": { + "Fn::Join": [ + "", + [ + "WEIGHT_", + { + "Ref": "RecordWeight2" + }, + "_ID_recordweightfromcfnpaecordWithParamWeight25B9D18F1" + ] + ] + }, + "ttl": "10", + "type": "A", + "weight": { + "Ref": "RecordWeight2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "RecordWithParamWeight3": { + "id": "RecordWithParamWeight3", + "path": "record-weight-from-cfnparameter/RecordWithParamWeight3", + "children": { + "Resource": { + "id": "Resource", + "path": "record-weight-from-cfnparameter/RecordWithParamWeight3/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Route53::RecordSet", + "aws:cdk:cloudformation:props": { + "hostedZoneId": { + "Ref": "HostedZoneDB99F866" + }, + "name": "www.cdk.dev.", + "resourceRecords": [ + "4.5.6.7" + ], + "setIdentifier": { + "Fn::Join": [ + "", + [ + "WEIGHT_", + { + "Ref": "RecordWeight3" + }, + "_ID_recordweightfromcfnpaecordWithParamWeight37DA83B23" + ] + ] + }, + "ttl": "10", + "type": "A", + "weight": { + "Ref": "RecordWeight3" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "record-weight-from-cfnparameter/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "record-weight-from-cfnparameter/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "Route53RecordWeightFromCfnParameterInteg": { + "id": "Route53RecordWeightFromCfnParameterInteg", + "path": "Route53RecordWeightFromCfnParameterInteg", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "Route53RecordWeightFromCfnParameterInteg/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "Route53RecordWeightFromCfnParameterInteg/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "Route53RecordWeightFromCfnParameterInteg/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "Route53RecordWeightFromCfnParameterInteg/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "Route53RecordWeightFromCfnParameterInteg/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.ts new file mode 100644 index 0000000000000..6d2d2160aa059 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-route53/test/integ.record-weight-from-cfnparameter.ts @@ -0,0 +1,44 @@ +import { App, CfnParameter, Duration, Stack, StackProps } from 'aws-cdk-lib'; +import { Construct } from 'constructs'; +import * as route53 from 'aws-cdk-lib/aws-route53'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +class TestStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const hostedZone = new route53.PublicHostedZone(this, 'HostedZone', { + zoneName: 'cdk.dev', + }); + + const weightParameterProps = { + type: 'Number', + default: 0, + minValue: 0, + maxValue: 255, + }; + + [ + { target: '1.2.3.4', weight: new CfnParameter(this, 'RecordWeight0', weightParameterProps) }, + { target: '2.3.4.5', weight: new CfnParameter(this, 'RecordWeight1', weightParameterProps) }, + { target: '3.4.5.6', weight: new CfnParameter(this, 'RecordWeight2', weightParameterProps) }, + { target: '4.5.6.7', weight: new CfnParameter(this, 'RecordWeight3', weightParameterProps) }, + ].forEach((data, index) => { + new route53.ARecord(this, `RecordWithParamWeight${index}`, { + zone: hostedZone, + recordName: 'www', + weight: data.weight.valueAsNumber, + ttl: Duration.seconds(10), + target: route53.RecordTarget.fromIpAddresses(data.target), + }); + }); + } +} + +const app = new App(); +const stack = new TestStack(app, 'record-weight-from-cfnparameter'); + +new IntegTest(app, 'Route53RecordWeightFromCfnParameterInteg', { + testCases: [stack], +}); +app.synth(); diff --git a/packages/aws-cdk-lib/aws-route53/lib/record-set.ts b/packages/aws-cdk-lib/aws-route53/lib/record-set.ts index 6706443b1f260..ef5982da54610 100644 --- a/packages/aws-cdk-lib/aws-route53/lib/record-set.ts +++ b/packages/aws-cdk-lib/aws-route53/lib/record-set.ts @@ -296,7 +296,7 @@ export class RecordSet extends Resource implements IRecordSet { constructor(scope: Construct, id: string, props: RecordSetProps) { super(scope, id); - if (props.weight && (props.weight < 0 || props.weight > 255)) { + if (props.weight && !Token.isUnresolved(props.weight) && (props.weight < 0 || props.weight > 255)) { throw new Error(`weight must be between 0 and 255 inclusive, got: ${props.weight}`); } if (props.setIdentifier && (props.setIdentifier.length < 1 || props.setIdentifier.length > 128)) { @@ -406,8 +406,15 @@ export class RecordSet extends Resource implements IRecordSet { } if (this.weight !== undefined) { - const idPrefix = `WEIGHT_${this.weight}_ID_`; - return this.createIdentifier(idPrefix); + if (Token.isUnresolved(this.weight)) { + const replacement = 'XXX'; // XXX simply because 255 is the highest value for a record weight + const idPrefix = `WEIGHT_${replacement}_ID_`; + const idTemplate = this.createIdentifier(idPrefix); + return idTemplate.replace(replacement, Token.asString(this.weight)); + } else { + const idPrefix = `WEIGHT_${this.weight}_ID_`; + return this.createIdentifier(idPrefix); + } } if (this.region) { diff --git a/packages/aws-cdk-lib/aws-route53/test/record-set.test.ts b/packages/aws-cdk-lib/aws-route53/test/record-set.test.ts index 20abd698ee68b..f66b283b1aaca 100644 --- a/packages/aws-cdk-lib/aws-route53/test/record-set.test.ts +++ b/packages/aws-cdk-lib/aws-route53/test/record-set.test.ts @@ -4,7 +4,7 @@ import * as cloudfront from '../../aws-cloudfront'; import * as origins from '../../aws-cloudfront-origins'; import * as iam from '../../aws-iam'; import * as targets from '../../aws-route53-targets'; -import { Duration, RemovalPolicy, Stack } from '../../core'; +import { CfnParameter, Duration, RemovalPolicy, Stack } from '../../core'; import * as route53 from '../lib'; describe('record set', () => { @@ -1248,6 +1248,66 @@ describe('record set', () => { }); }); + test('with weight provided by CfnParameter', () => { + // GIVEN + const stack = new Stack(); + + const zone = new route53.HostedZone(stack, 'HostedZone', { + zoneName: 'myzone', + }); + + const weightParameter = new CfnParameter(stack, 'RecordWeight', { + type: 'Number', + default: 0, + minValue: 0, + maxValue: 255, + }); + + // WHEN + new route53.RecordSet(stack, 'RecordSet', { + zone, + recordName: 'www', + recordType: route53.RecordType.CNAME, + target: route53.RecordTarget.fromValues('zzz'), + weight: weightParameter.valueAsNumber, + }); + + // THEN + Template.fromStack(stack).hasParameter('RecordWeight', { + Type: 'Number', + Default: 0, + MinValue: 0, + MaxValue: 255, + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Route53::RecordSet', { + Name: 'www.myzone.', + Type: 'CNAME', + HostedZoneId: { + Ref: 'HostedZoneDB99F866', + }, + ResourceRecords: [ + 'zzz', + ], + TTL: '1800', + Weight: { + Ref: 'RecordWeight', + }, + SetIdentifier: { + 'Fn::Join': [ + '', + [ + 'WEIGHT_', + { + Ref: 'RecordWeight', + }, + '_ID_RecordSet', + ], + ], + }, + }); + }); + test.each([ [-1], [256], From 7904f2a13d68cf664d52bc458985560000d0a075 Mon Sep 17 00:00:00 2001 From: Mohamed Elasmar <71043312+moelasmar@users.noreply.github.com> Date: Thu, 31 Oct 2024 16:31:57 -0700 Subject: [PATCH 02/42] chore(mergify): update queue rules minimum required conditions (#31945) ### Reason for this change Update the Mergify queue rules, so if the [mergify queue command](https://docs.mergify.com/commands/queue/) used it will use the correct queue based on the conditions added to each queue, and to avoid human mistakes if this command used and the PR does not fulfill the minimum requirements to be merged. ### Description of changes Updated the default-merge, and default-squash queues to add the minimum requirements before to be checked before adding a PR to that queue. ### Checklist - [X] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .mergify.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.mergify.yml b/.mergify.yml index 24f5698c49f27..55a700cee4e2f 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -4,7 +4,17 @@ queue_rules: update_method: merge merge_method: merge conditions: + - -title~=(WIP|wip) + - -label~=(blocked|do-not-merge) + # Only if no-squash is set + - label~=no-squash + - -merged + - -closed + - "#approved-reviews-by>=1" + - -approved-reviews-by~=author + - "#changes-requested-reviews-by=0" - status-success~=AWS CodeBuild us-east-1 + - status-success=validate-pr commit_message_template: |- {{ title }} (#{{ number }}) {{ body }} @@ -13,7 +23,16 @@ queue_rules: update_method: merge merge_method: squash conditions: + - base!=release + - -title~=(WIP|wip) + - -label~=(blocked|do-not-merge|no-squash) + - -merged + - -closed + - "#approved-reviews-by>=1" + - -approved-reviews-by~=author + - "#changes-requested-reviews-by=0" - status-success~=AWS CodeBuild us-east-1 + - status-success=validate-pr commit_message_template: |- {{ title }} (#{{ number }}) {{ body }} From f15de81fb94ab45d9e887fb1b7b506a921bed29f Mon Sep 17 00:00:00 2001 From: Mohamed Elasmar <71043312+moelasmar@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:24:07 -0700 Subject: [PATCH 03/42] chore: update CHANGELOG.v2.alpha.md to announce kinesisfirehose as developer preview (#31969) Update the Change log file to announce kinesisfirehose as developer preview ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- CHANGELOG.v2.alpha.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.v2.alpha.md b/CHANGELOG.v2.alpha.md index 41928fc5e1b5d..05f256ef79507 100644 --- a/CHANGELOG.v2.alpha.md +++ b/CHANGELOG.v2.alpha.md @@ -17,6 +17,7 @@ All notable changes to this project will be documented in this file. See [standa * **pipes-enrichments:** support API Gateway enrichment ([#31794](https://github.com/aws/aws-cdk/issues/31794)) ([09052c2](https://github.com/aws/aws-cdk/commit/09052c2060c410028896fd54e76a857b2141c8a4)), closes [#29384](https://github.com/aws/aws-cdk/issues/29384) * **pipes-targets:** add SageMaker ([#30696](https://github.com/aws/aws-cdk/issues/30696)) ([a5fdf57](https://github.com/aws/aws-cdk/commit/a5fdf570beb1456b1307276f56d90fd1ba0b46d8)) * **redshift-alpha:** query execution timeout setting during table creation ([#31818](https://github.com/aws/aws-cdk/issues/31818)) ([40f07ae](https://github.com/aws/aws-cdk/commit/40f07ae330d074cfa7861e24a0427da7ec427f68)), closes [#31329](https://github.com/aws/aws-cdk/issues/31329) +* **kinesisfirehose-alpha:** kinesis firehose and kinesis firehose destinations modules are now in Developer Preview ([#31952](https://github.com/aws/aws-cdk/pull/31952)) ### Bug Fixes From 18fbd6d5a1a3069b0fc1356d87e534a75239e668 Mon Sep 17 00:00:00 2001 From: Matsuda Date: Fri, 1 Nov 2024 09:58:47 +0900 Subject: [PATCH 04/42] feat(kinesis): support resource policy for a data stream (#31909) ### Issue # (if applicable) Closes #28814 . ### Reason for this change To support resource policy for a Kinesis Data stream. ### Description of changes * Add `ResourcePolicy` Construct. * Add `addToResourcePolicy` method to `Stream` Construct. ### Description of how you validated changes Add unit tests and integ test. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../integ.resource-policy.js.snapshot/cdk.out | 1 + .../integ.json | 13 ++ ...efaultTestDeployAssert52C5D16C.assets.json | 19 ++ ...aultTestDeployAssert52C5D16C.template.json | 36 +++ .../kinesis-resource-policy.assets.json | 19 ++ .../kinesis-resource-policy.template.json | 128 +++++++++++ .../manifest.json | 127 +++++++++++ .../tree.json | 211 ++++++++++++++++++ .../aws-kinesis/test/integ.resource-policy.ts | 23 ++ packages/aws-cdk-lib/aws-kinesis/README.md | 48 ++++ packages/aws-cdk-lib/aws-kinesis/lib/index.ts | 1 + .../aws-kinesis/lib/resource-policy.ts | 54 +++++ .../aws-cdk-lib/aws-kinesis/lib/stream.ts | 55 ++++- .../aws-kinesis/test/resource-policy.test.ts | 45 ++++ .../aws-kinesis/test/stream.test.ts | 28 +++ packages/aws-cdk-lib/awslint.json | 1 + 16 files changed, 806 insertions(+), 3 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/kinesis-resource-policy.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/kinesis-resource-policy.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.ts create mode 100644 packages/aws-cdk-lib/aws-kinesis/lib/resource-policy.ts create mode 100644 packages/aws-cdk-lib/aws-kinesis/test/resource-policy.test.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/cdk.out new file mode 100644 index 0000000000000..c6e612584e352 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integ.json new file mode 100644 index 0000000000000..b3f8f40c776a5 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integ.json @@ -0,0 +1,13 @@ +{ + "version": "38.0.1", + "testCases": { + "integ-kinesis-resource-policy/DefaultTest": { + "stacks": [ + "kinesis-resource-policy" + ], + "stackUpdateWorkflow": false, + "assertionStack": "integ-kinesis-resource-policy/DefaultTest/DeployAssert", + "assertionStackName": "integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.assets.json new file mode 100644 index 0000000000000..10ed04c6cb3b2 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/kinesis-resource-policy.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/kinesis-resource-policy.assets.json new file mode 100644 index 0000000000000..41aa262dfadaa --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/kinesis-resource-policy.assets.json @@ -0,0 +1,19 @@ +{ + "version": "38.0.1", + "files": { + "25f5843484c10a3b762cdda9cddcdbaf948c1d795dd2294a83ba77c6c1b732ef": { + "source": { + "path": "kinesis-resource-policy.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "25f5843484c10a3b762cdda9cddcdbaf948c1d795dd2294a83ba77c6c1b732ef.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/kinesis-resource-policy.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/kinesis-resource-policy.template.json new file mode 100644 index 0000000000000..7431a787d0228 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/kinesis-resource-policy.template.json @@ -0,0 +1,128 @@ +{ + "Resources": { + "MyStream5C050E93": { + "Type": "AWS::Kinesis::Stream", + "Properties": { + "RetentionPeriodHours": 24, + "ShardCount": 1, + "StreamEncryption": { + "Fn::If": [ + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + { + "Ref": "AWS::NoValue" + }, + { + "EncryptionType": "KMS", + "KeyId": "alias/aws/kinesis" + } + ] + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "MyStreamPolicyC34ACF94": { + "Type": "AWS::Kinesis::ResourcePolicy", + "Properties": { + "ResourceArn": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + }, + "ResourcePolicy": { + "Statement": [ + { + "Action": [ + "kinesis:DescribeStreamSummary", + "kinesis:GetRecords" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + } + } + } + }, + "Conditions": { + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions": { + "Fn::Or": [ + { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "cn-north-1" + ] + }, + { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "cn-northwest-1" + ] + } + ] + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/manifest.json new file mode 100644 index 0000000000000..5b7e1577fd04f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/manifest.json @@ -0,0 +1,127 @@ +{ + "version": "38.0.1", + "artifacts": { + "kinesis-resource-policy.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "kinesis-resource-policy.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "kinesis-resource-policy": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "kinesis-resource-policy.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "notificationArns": [], + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/25f5843484c10a3b762cdda9cddcdbaf948c1d795dd2294a83ba77c6c1b732ef.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "kinesis-resource-policy.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "kinesis-resource-policy.assets" + ], + "metadata": { + "/kinesis-resource-policy/MyStream/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyStream5C050E93" + } + ], + "/kinesis-resource-policy/MyStream/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyStreamPolicyC34ACF94" + } + ], + "/kinesis-resource-policy/AwsCdkKinesisEncryptedStreamsUnsupportedRegions": [ + { + "type": "aws:cdk:logicalId", + "data": "AwsCdkKinesisEncryptedStreamsUnsupportedRegions" + } + ], + "/kinesis-resource-policy/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/kinesis-resource-policy/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "kinesis-resource-policy" + }, + "integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "notificationArns": [], + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "integkinesisresourcepolicyDefaultTestDeployAssert52C5D16C.assets" + ], + "metadata": { + "/integ-kinesis-resource-policy/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/integ-kinesis-resource-policy/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "integ-kinesis-resource-policy/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/tree.json new file mode 100644 index 0000000000000..1cb4e4dd9901b --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.js.snapshot/tree.json @@ -0,0 +1,211 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "kinesis-resource-policy": { + "id": "kinesis-resource-policy", + "path": "kinesis-resource-policy", + "children": { + "MyStream": { + "id": "MyStream", + "path": "kinesis-resource-policy/MyStream", + "children": { + "Resource": { + "id": "Resource", + "path": "kinesis-resource-policy/MyStream/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Kinesis::Stream", + "aws:cdk:cloudformation:props": { + "retentionPeriodHours": 24, + "shardCount": 1, + "streamEncryption": { + "Fn::If": [ + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + { + "Ref": "AWS::NoValue" + }, + { + "EncryptionType": "KMS", + "KeyId": "alias/aws/kinesis" + } + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.CfnStream", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "kinesis-resource-policy/MyStream/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "kinesis-resource-policy/MyStream/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Kinesis::ResourcePolicy", + "aws:cdk:cloudformation:props": { + "resourceArn": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + }, + "resourcePolicy": { + "Statement": [ + { + "Action": [ + "kinesis:DescribeStreamSummary", + "kinesis:GetRecords" + ], + "Effect": "Allow", + "Principal": { + "AWS": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::", + { + "Ref": "AWS::AccountId" + }, + ":root" + ] + ] + } + }, + "Resource": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.CfnResourcePolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.ResourcePolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.Stream", + "version": "0.0.0" + } + }, + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions": { + "id": "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + "path": "kinesis-resource-policy/AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnCondition", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "kinesis-resource-policy/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "kinesis-resource-policy/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "integ-kinesis-resource-policy": { + "id": "integ-kinesis-resource-policy", + "path": "integ-kinesis-resource-policy", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "integ-kinesis-resource-policy/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "integ-kinesis-resource-policy/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "integ-kinesis-resource-policy/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "integ-kinesis-resource-policy/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "integ-kinesis-resource-policy/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.4.2" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.ts new file mode 100644 index 0000000000000..bd9911520e5c6 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-kinesis/test/integ.resource-policy.ts @@ -0,0 +1,23 @@ +import { App, Stack } from 'aws-cdk-lib'; +import { Stream } from 'aws-cdk-lib/aws-kinesis'; +import { AccountPrincipal, PolicyStatement } from 'aws-cdk-lib/aws-iam'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; + +const app = new App(); +const stack = new Stack(app, 'kinesis-resource-policy'); + +const stream = new Stream(stack, 'MyStream'); + +stream.addToResourcePolicy(new PolicyStatement({ + resources: [stream.streamArn], + actions: [ + 'kinesis:DescribeStreamSummary', + 'kinesis:GetRecords', + ], + principals: [new AccountPrincipal(stack.account)], +})); + +new IntegTest(app, 'integ-kinesis-resource-policy', { + testCases: [stack], + stackUpdateWorkflow: false, +}); diff --git a/packages/aws-cdk-lib/aws-kinesis/README.md b/packages/aws-cdk-lib/aws-kinesis/README.md index b8b22dffda657..27f89e65b7626 100644 --- a/packages/aws-cdk-lib/aws-kinesis/README.md +++ b/packages/aws-cdk-lib/aws-kinesis/README.md @@ -15,6 +15,8 @@ intake and aggregation. - [Write Permissions](#write-permissions) - [Custom Permissions](#custom-permissions) - [Metrics](#metrics) + - [Resource Policy](#resource-policy) + ## Streams @@ -186,3 +188,49 @@ stream.metricGetRecordsSuccess(); // using pre-defined and overriding the statistic stream.metricGetRecordsSuccess({ statistic: 'Maximum' }); ``` + +### Resource Policy + +You can create a resource policy for a data stream. +For more information, see [Controlling access to Amazon Kinesis Data Streams resources using IAM](https://docs.aws.amazon.com/streams/latest/dev/controlling-access.html). + +A resource policy is automatically created when `addToResourcePolicy` is called, if one doesn't already exist. + +Using `addToResourcePolicy` is the simplest way to add a resource policy: + +```ts +const stream = new kinesis.Stream(this, 'MyStream'); + +// create a resource policy via addToResourcePolicy method +stream.addToResourcePolicy(new iam.PolicyStatement({ + resources: [stream.streamArn], + actions: ['kinesis:GetRecords'], + principals: [new iam.AnyPrincipal()], +})); +``` + +You can create a resource manually by using `ResourcePolicy`. +Also, you can set a custom policy document to `ResourcePolicy`. +If not, a blank policy document will be set. + +```ts +const stream = new kinesis.Stream(this, 'MyStream'); + +// create a custom policy document +const policyDocument = new iam.PolicyDocument({ + assignSids: true, + statements: [ + new iam.PolicyStatement({ + actions: ['kinesis:GetRecords'], + resources: [stream.streamArn], + principals: [new iam.AnyPrincipal()], + }), + ], +}); + +// create a resource policy manually +new kinesis.ResourcePolicy(this, 'ResourcePolicy', { + stream, + policyDocument, +}); +``` \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-kinesis/lib/index.ts b/packages/aws-cdk-lib/aws-kinesis/lib/index.ts index bb8cedbc5558c..c239368eaa87c 100644 --- a/packages/aws-cdk-lib/aws-kinesis/lib/index.ts +++ b/packages/aws-cdk-lib/aws-kinesis/lib/index.ts @@ -1,4 +1,5 @@ export * from './stream'; +export * from './resource-policy'; // AWS::Kinesis CloudFormation Resources: export * from './kinesis.generated'; diff --git a/packages/aws-cdk-lib/aws-kinesis/lib/resource-policy.ts b/packages/aws-cdk-lib/aws-kinesis/lib/resource-policy.ts new file mode 100644 index 0000000000000..3987268f52bfe --- /dev/null +++ b/packages/aws-cdk-lib/aws-kinesis/lib/resource-policy.ts @@ -0,0 +1,54 @@ +import { Construct } from 'constructs'; +import { CfnResourcePolicy } from './kinesis.generated'; +import { IStream } from './stream'; +import { PolicyDocument } from '../../aws-iam'; +import { Resource } from '../../core'; + +/** + * Properties to associate a data stream with a policy + */ +export interface ResourcePolicyProps { + /** + * The stream this policy applies to. + */ + readonly stream: IStream; + + /** + * IAM policy document to apply to a data stream. + * + * @default - empty policy document + */ + readonly policyDocument?: PolicyDocument; +} + +/** + * The policy for a data stream or registered consumer. + * + * Policies define the operations that are allowed on this resource. + * + * You almost never need to define this construct directly. + * + * All AWS resources that support resource policies have a method called + * `addToResourcePolicy()`, which will automatically create a new resource + * policy if one doesn't exist yet, otherwise it will add to the existing + * policy. + * + * Prefer to use `addToResourcePolicy()` instead. + */ +export class ResourcePolicy extends Resource { + /** + * The IAM policy document for this policy. + */ + public readonly document = new PolicyDocument(); + + constructor(scope: Construct, id: string, props: ResourcePolicyProps) { + super(scope, id); + + this.document = props.policyDocument ?? this.document; + + new CfnResourcePolicy(this, 'Resource', { + resourcePolicy: this.document, + resourceArn: props.stream.streamArn, + }); + } +} diff --git a/packages/aws-cdk-lib/aws-kinesis/lib/stream.ts b/packages/aws-cdk-lib/aws-kinesis/lib/stream.ts index 59ee9d4ff5d87..0fb74df769f50 100644 --- a/packages/aws-cdk-lib/aws-kinesis/lib/stream.ts +++ b/packages/aws-cdk-lib/aws-kinesis/lib/stream.ts @@ -1,10 +1,11 @@ import { Construct } from 'constructs'; import { KinesisMetrics } from './kinesis-fixed-canned-metrics'; import { CfnStream } from './kinesis.generated'; +import { ResourcePolicy } from './resource-policy'; import * as cloudwatch from '../../aws-cloudwatch'; import * as iam from '../../aws-iam'; import * as kms from '../../aws-kms'; -import { ArnFormat, Aws, CfnCondition, Duration, Fn, IResolvable, IResource, RemovalPolicy, Resource, Stack, Token } from '../../core'; +import { ArnFormat, Aws, CfnCondition, Duration, Fn, IResolvable, IResource, RemovalPolicy, Resource, ResourceProps, Stack, Token } from '../../core'; const READ_OPERATIONS = [ 'kinesis:DescribeStreamSummary', @@ -46,6 +47,15 @@ export interface IStream extends IResource { */ readonly encryptionKey?: kms.IKey; + /** + * Adds a statement to the IAM resource policy associated with this stream. + * + * If this stream was created in this stack (`new Stream`), a resource policy + * will be automatically created upon the first call to `addToResourcePolicy`. If + * the stream is imported (`Stream.import`), then this is a no-op. + */ + addToResourcePolicy(statement: iam.PolicyStatement): iam.AddToResourcePolicyResult; + /** * Grant read permissions for this stream and its contents to an IAM * principal (Role/Group/User). @@ -328,6 +338,41 @@ abstract class StreamBase extends Resource implements IStream { */ public abstract readonly encryptionKey?: kms.IKey; + /** + * Indicates if a stream resource policy should automatically be created upon + * the first call to `addToResourcePolicy`. + * + * Set by subclasses. + */ + protected abstract readonly autoCreatePolicy: boolean; + + private resourcePolicy?: ResourcePolicy; + + constructor(scope: Construct, id: string, props: ResourceProps = {}) { + super(scope, id, props); + + this.node.addValidation({ validate: () => this.resourcePolicy?.document.validateForResourcePolicy() ?? [] }); + } + + /** + * Adds a statement to the IAM resource policy associated with this stream. + * + * If this stream was created in this stack (`new Strem`), a resource policy + * will be automatically created upon the first call to `addToResourcePolicy`. If + * the stream is imported (`Stream.import`), then this is a no-op. + */ + public addToResourcePolicy(statement: iam.PolicyStatement): iam.AddToResourcePolicyResult { + if (!this.resourcePolicy && this.autoCreatePolicy) { + this.resourcePolicy = new ResourcePolicy(this, 'Policy', { stream: this }); + } + + if (this.resourcePolicy) { + this.resourcePolicy.document.addStatements(statement); + return { statementAdded: true, policyDependable: this.resourcePolicy }; + } + return { statementAdded: false }; + } + /** * Grant read permissions for this stream and its contents to an IAM * principal (Role/Group/User). @@ -747,6 +792,8 @@ export class Stream extends StreamBase { public readonly streamArn = attrs.streamArn; public readonly streamName = Stack.of(scope).splitArn(attrs.streamArn, ArnFormat.SLASH_RESOURCE_NAME).resourceName!; public readonly encryptionKey = attrs.encryptionKey; + + protected readonly autoCreatePolicy = false; } return new Import(scope, id, { @@ -760,6 +807,8 @@ export class Stream extends StreamBase { private readonly stream: CfnStream; + protected readonly autoCreatePolicy = true; + constructor(scope: Construct, id: string, props: StreamProps = {}) { super(scope, id, { physicalName: props.streamName, @@ -771,7 +820,7 @@ export class Stream extends StreamBase { if (streamMode === StreamMode.ON_DEMAND && shardCount !== undefined) { throw new Error(`streamMode must be set to ${StreamMode.PROVISIONED} (default) when specifying shardCount`); } - if ( (streamMode === StreamMode.PROVISIONED || streamMode === undefined) && shardCount === undefined) { + if ((streamMode === StreamMode.PROVISIONED || streamMode === undefined) && shardCount === undefined) { shardCount = 1; } @@ -849,7 +898,7 @@ export class Stream extends StreamBase { } if (encryptionType === StreamEncryption.UNENCRYPTED) { - return { }; + return {}; } if (encryptionType === StreamEncryption.MANAGED) { diff --git a/packages/aws-cdk-lib/aws-kinesis/test/resource-policy.test.ts b/packages/aws-cdk-lib/aws-kinesis/test/resource-policy.test.ts new file mode 100644 index 0000000000000..01cd727cf8aed --- /dev/null +++ b/packages/aws-cdk-lib/aws-kinesis/test/resource-policy.test.ts @@ -0,0 +1,45 @@ +import { Template } from '../../assertions'; +import * as iam from '../../aws-iam'; +import { Stack } from '../../core'; +import { ResourcePolicy, Stream } from '../lib'; + +describe('Kinesis resource policy', () => { + test('create resource policy', () => { + // GIVEN + const stack = new Stack(); + const stream = new Stream(stack, 'Stream', {}); + + // WHEN + const policyDocument = new iam.PolicyDocument({ + assignSids: true, + statements: [ + new iam.PolicyStatement({ + actions: ['kinesis:GetRecords'], + principals: [new iam.AnyPrincipal()], + resources: [stream.streamArn], + }), + ], + }); + + new ResourcePolicy(stack, 'ResourcePolicy', { + stream, + policyDocument, + }); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Kinesis::ResourcePolicy', { + ResourcePolicy: { + Version: '2012-10-17', + Statement: [ + { + Sid: '0', + Action: 'kinesis:GetRecords', + Effect: 'Allow', + Principal: { AWS: '*' }, + Resource: stack.resolve(stream.streamArn), + }, + ], + }, + }); + }); +}); diff --git a/packages/aws-cdk-lib/aws-kinesis/test/stream.test.ts b/packages/aws-cdk-lib/aws-kinesis/test/stream.test.ts index 841c95877ef53..c9e7569bdf1d8 100644 --- a/packages/aws-cdk-lib/aws-kinesis/test/stream.test.ts +++ b/packages/aws-cdk-lib/aws-kinesis/test/stream.test.ts @@ -1289,4 +1289,32 @@ describe('Kinesis data streams', () => { DeletionPolicy: CfnDeletionPolicy.DELETE, }); }); + + test('addToResourcePolicy will automatically create a policy for this stream', () => { + // GIVEN + const stack = new Stack(); + const stream = new Stream(stack, 'Stream', {}); + + // WHEN + stream.addToResourcePolicy(new iam.PolicyStatement({ + actions: ['kinesis:GetRecords'], + principals: [new iam.AnyPrincipal()], + resources: [stream.streamArn], + })); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Kinesis::ResourcePolicy', { + ResourcePolicy: { + Version: '2012-10-17', + Statement: [ + { + Action: 'kinesis:GetRecords', + Effect: 'Allow', + Principal: { AWS: '*' }, + Resource: stack.resolve(stream.streamArn), + }, + ], + }, + }); + }); }); diff --git a/packages/aws-cdk-lib/awslint.json b/packages/aws-cdk-lib/awslint.json index d85aaef4834d9..987770519230f 100644 --- a/packages/aws-cdk-lib/awslint.json +++ b/packages/aws-cdk-lib/awslint.json @@ -124,6 +124,7 @@ "props-physical-name:aws-cdk-lib.aws_iam.OpenIdConnectProviderProps", "props-physical-name:aws-cdk-lib.aws_iam.SamlProviderProps", "props-physical-name:aws-cdk-lib.aws_kms.KeyProps", + "props-physical-name:aws-cdk-lib.aws_kinesis.ResourcePolicyProps", "props-physical-name:aws-cdk-lib.aws_lambda.CodeSigningConfigProps", "props-physical-name:aws-cdk-lib.aws_lambda.EventInvokeConfigProps", "props-physical-name:aws-cdk-lib.aws_lambda.EventSourceMappingProps", From efb4232b8893044a0dae2378691ce8e24893337f Mon Sep 17 00:00:00 2001 From: AWS CDK Automation <43080478+aws-cdk-automation@users.noreply.github.com> Date: Thu, 31 Oct 2024 18:31:14 -0700 Subject: [PATCH 05/42] chore: update Contributors File (#31970) Automated changes by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action --- CONTRIBUTORS.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 61a37615ded13..853cd33e87bc2 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -17,16 +17,16 @@ Shout out to our top contributors! - [comcalvi](https://github.com/comcalvi) - [madeline-k](https://github.com/madeline-k) - [NetaNir](https://github.com/NetaNir) -- [robertd](https://github.com/robertd) - [go-to-k](https://github.com/go-to-k) +- [robertd](https://github.com/robertd) +- [mazyu36](https://github.com/mazyu36) - [MrArnoldPalmer](https://github.com/MrArnoldPalmer) - [lpizzinidev](https://github.com/lpizzinidev) - [peterwoodworth](https://github.com/peterwoodworth) -- [mazyu36](https://github.com/mazyu36) -- [colifran](https://github.com/colifran) - [badmintoncryer](https://github.com/badmintoncryer) +- [colifran](https://github.com/colifran) - [msambol](https://github.com/msambol) - [watany-dev](https://github.com/watany-dev) -_Last updated: Tue, 01 Oct 24 00:12:17 +0000_ \ No newline at end of file +_Last updated: Fri, 01 Nov 24 00:12:22 +0000_ \ No newline at end of file From 0fb610678495deb150fad1adebde259fc5fc0993 Mon Sep 17 00:00:00 2001 From: Kazuho Cryer-Shinozuka Date: Fri, 1 Nov 2024 11:04:31 +0900 Subject: [PATCH 06/42] feat(rds): configure `autoMinorVersionUpgrade` for a database cluster (#31962) ### Issue # (if applicable) None ### Reason for this change We can configure `autoMinorVersionUpgrade' for a database cluster, but AWS CDK cannot do this. ### Description of changes Add `autoMinorVersionUpgrade` to `DatabaseClusterBaseProps`. ### Description of how you validated changes Add both unit and integ tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- ...dk-rds-integ-with-feature-flag.assets.json | 6 +- ...-rds-integ-with-feature-flag.template.json | 1 + .../aws-cdk-rds-integ.assets.json | 6 +- .../aws-cdk-rds-integ.template.json | 1 + .../test/integ.cluster.js.snapshot/cdk.out | 2 +- .../test/integ.cluster.js.snapshot/integ.json | 2 +- .../integ.cluster.js.snapshot/manifest.json | 6 +- ...efaultTestDeployAssert23E53F17.assets.json | 2 +- ...efaultTestDeployAssert8E2E540B.assets.json | 2 +- .../test/integ.cluster.js.snapshot/tree.json | 135 +++++++++--------- .../test/aws-rds/test/integ.cluster.ts | 1 + packages/aws-cdk-lib/aws-rds/README.md | 14 ++ packages/aws-cdk-lib/aws-rds/lib/cluster.ts | 8 ++ .../aws-cdk-lib/aws-rds/test/cluster.test.ts | 21 +++ 14 files changed, 128 insertions(+), 79 deletions(-) diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.assets.json index 46c75d649acf8..2ecc1dbe4c465 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.assets.json @@ -1,7 +1,7 @@ { - "version": "36.0.5", + "version": "38.0.1", "files": { - "b7b22a9a62bca0a9ce298b17646786419075ea2ea6323de0a850a69e803f8861": { + "88280b03c5b1be25a757aec1dc08c8df2c722de34a69963dfde75905ceaae61e": { "source": { "path": "aws-cdk-rds-integ-with-feature-flag.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "b7b22a9a62bca0a9ce298b17646786419075ea2ea6323de0a850a69e803f8861.json", + "objectKey": "88280b03c5b1be25a757aec1dc08c8df2c722de34a69963dfde75905ceaae61e.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.template.json index 8dcc7c8de25d1..6aa2bda2f1bef 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ-with-feature-flag.template.json @@ -495,6 +495,7 @@ "DatabaseB269D8BB": { "Type": "AWS::RDS::DBCluster", "Properties": { + "AutoMinorVersionUpgrade": false, "CopyTagsToSnapshot": true, "DBClusterParameterGroupName": { "Ref": "ParamsA8366201" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json index da8c0a49de36b..e4813a656fbd4 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.assets.json @@ -1,7 +1,7 @@ { - "version": "36.0.5", + "version": "38.0.1", "files": { - "cdaee25b7715132e6f696fc6d6103ce36892dcd0d7404cd3206ab2bd8e456dfa": { + "c5c41991477732fc96052ff5ee9b37386fd014657c4e5c15836e6075551961b5": { "source": { "path": "aws-cdk-rds-integ.template.json", "packaging": "file" @@ -9,7 +9,7 @@ "destinations": { "current_account-current_region": { "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", - "objectKey": "cdaee25b7715132e6f696fc6d6103ce36892dcd0d7404cd3206ab2bd8e456dfa.json", + "objectKey": "c5c41991477732fc96052ff5ee9b37386fd014657c4e5c15836e6075551961b5.json", "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" } } diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json index 6f847574d85ea..8e864fd4fc053 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/aws-cdk-rds-integ.template.json @@ -495,6 +495,7 @@ "DatabaseB269D8BB": { "Type": "AWS::RDS::DBCluster", "Properties": { + "AutoMinorVersionUpgrade": false, "CopyTagsToSnapshot": true, "DBClusterParameterGroupName": { "Ref": "ParamsA8366201" diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out index bd5311dc372de..c6e612584e352 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/cdk.out @@ -1 +1 @@ -{"version":"36.0.5"} \ No newline at end of file +{"version":"38.0.1"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json index f777a0b6e162b..a4563c58af824 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/integ.json @@ -1,5 +1,5 @@ { - "version": "36.0.5", + "version": "38.0.1", "testCases": { "test-rds-cluster-with-feature-flag/DefaultTest": { "stacks": [ diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json index a45b9d8db7386..7a2508d7dbe9f 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/manifest.json @@ -1,5 +1,5 @@ { - "version": "36.0.5", + "version": "38.0.1", "artifacts": { "aws-cdk-rds-integ-with-feature-flag.assets": { "type": "cdk:asset-manifest", @@ -16,9 +16,10 @@ "templateFile": "aws-cdk-rds-integ-with-feature-flag.template.json", "terminationProtection": false, "validateOnSynth": false, + "notificationArns": [], "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", - "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b7b22a9a62bca0a9ce298b17646786419075ea2ea6323de0a850a69e803f8861.json", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/88280b03c5b1be25a757aec1dc08c8df2c722de34a69963dfde75905ceaae61e.json", "requiresBootstrapStackVersion": 6, "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", "additionalDependencies": [ @@ -280,6 +281,7 @@ "templateFile": "testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.template.json", "terminationProtection": false, "validateOnSynth": false, + "notificationArns": [], "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterDefaultTestDeployAssert23E53F17.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterDefaultTestDeployAssert23E53F17.assets.json index 539e4db9a6b79..4418321ac7c58 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterDefaultTestDeployAssert23E53F17.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterDefaultTestDeployAssert23E53F17.assets.json @@ -1,5 +1,5 @@ { - "version": "36.0.5", + "version": "38.0.1", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.assets.json index ff52cfa50053b..0509595126662 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.assets.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/testrdsclusterwithfeatureflagDefaultTestDeployAssert8E2E540B.assets.json @@ -1,5 +1,5 @@ { - "version": "36.0.5", + "version": "38.0.1", "files": { "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { "source": { diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json index d60ebda5b37ab..fabfe7323f23b 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.js.snapshot/tree.json @@ -32,7 +32,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "PublicSubnet1": { @@ -76,7 +76,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Acl": { @@ -84,7 +84,7 @@ "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet1/Acl", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "RouteTable": { @@ -106,7 +106,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "RouteTableAssociation": { @@ -125,7 +125,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "DefaultRoute": { @@ -145,7 +145,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "EIP": { @@ -165,7 +165,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "NATGateway": { @@ -193,13 +193,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "PublicSubnet2": { @@ -243,7 +243,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Acl": { @@ -251,7 +251,7 @@ "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PublicSubnet2/Acl", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "RouteTable": { @@ -273,7 +273,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "RouteTableAssociation": { @@ -292,7 +292,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "DefaultRoute": { @@ -312,7 +312,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "EIP": { @@ -332,7 +332,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "NATGateway": { @@ -360,13 +360,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "PrivateSubnet1": { @@ -410,7 +410,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Acl": { @@ -418,7 +418,7 @@ "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet1/Acl", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "RouteTable": { @@ -440,7 +440,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "RouteTableAssociation": { @@ -459,7 +459,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "DefaultRoute": { @@ -479,13 +479,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "PrivateSubnet2": { @@ -529,7 +529,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Acl": { @@ -537,7 +537,7 @@ "path": "aws-cdk-rds-integ-with-feature-flag/VPC/PrivateSubnet2/Acl", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "RouteTable": { @@ -559,7 +559,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "RouteTableAssociation": { @@ -578,7 +578,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "DefaultRoute": { @@ -598,13 +598,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "IGW": { @@ -623,7 +623,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "VPCGW": { @@ -642,13 +642,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Params": { @@ -670,13 +670,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "DbSecurity": { @@ -721,13 +721,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Database": { @@ -757,13 +757,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "SecurityGroup": { @@ -791,7 +791,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "from 0.0.0.0_0:{IndirectPort}": { @@ -825,13 +825,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Resource": { @@ -840,6 +840,7 @@ "attributes": { "aws:cdk:cloudformation:type": "AWS::RDS::DBCluster", "aws:cdk:cloudformation:props": { + "autoMinorVersionUpgrade": false, "copyTagsToSnapshot": true, "dbClusterParameterGroupName": { "Ref": "ParamsA8366201" @@ -870,7 +871,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Instance1Wrapper": { @@ -878,7 +879,7 @@ "path": "aws-cdk-rds-integ-with-feature-flag/Database/Instance1Wrapper", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Instance1": { @@ -901,7 +902,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Instance2Wrapper": { @@ -925,19 +926,19 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Instance2": { @@ -963,7 +964,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Instance3Wrapper": { @@ -987,19 +988,19 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Instance3": { @@ -1025,13 +1026,13 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "ClusterIamAccess": { @@ -1043,7 +1044,7 @@ "path": "aws-cdk-rds-integ-with-feature-flag/ClusterIamAccess/ImportClusterIamAccess", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "Resource": { @@ -1068,7 +1069,7 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "DefaultPolicy": { @@ -1127,19 +1128,19 @@ }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "BootstrapVersion": { @@ -1147,7 +1148,7 @@ "path": "aws-cdk-rds-integ-with-feature-flag/BootstrapVersion", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "CheckBootstrapVersion": { @@ -1155,13 +1156,13 @@ "path": "aws-cdk-rds-integ-with-feature-flag/CheckBootstrapVersion", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "test-rds-cluster-with-feature-flag": { @@ -1177,7 +1178,7 @@ "path": "test-rds-cluster-with-feature-flag/DefaultTest/Default", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "DeployAssert": { @@ -1189,7 +1190,7 @@ "path": "test-rds-cluster-with-feature-flag/DefaultTest/DeployAssert/BootstrapVersion", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } }, "CheckBootstrapVersion": { @@ -1197,13 +1198,13 @@ "path": "test-rds-cluster-with-feature-flag/DefaultTest/DeployAssert/CheckBootstrapVersion", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, @@ -1223,13 +1224,13 @@ "path": "Tree", "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } }, "constructInfo": { "fqn": "constructs.Construct", - "version": "10.3.0" + "version": "10.4.2" } } } \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts index 8953dbda110dd..66caa47941fa0 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-rds/test/integ.cluster.ts @@ -62,6 +62,7 @@ class TestStack extends cdk.Stack { readers: readers, parameterGroup: params, storageEncryptionKey: kmsKey, + autoMinorVersionUpgrade: false, }); cluster.connections.allowDefaultPortFromAnyIpv4('Open to the world'); diff --git a/packages/aws-cdk-lib/aws-rds/README.md b/packages/aws-cdk-lib/aws-rds/README.md index 0119f877a3526..3cb3afc681fd1 100644 --- a/packages/aws-cdk-lib/aws-rds/README.md +++ b/packages/aws-cdk-lib/aws-rds/README.md @@ -118,6 +118,20 @@ new rds.DatabaseClusterFromSnapshot(this, 'Database', { }); ``` +By default, automatic minor version upgrades for the engine type are enabled in a cluster, but you can also disable this. +To do so, set `autoMinorVersionUpgrade` to `false`. + +```ts +declare const vpc: ec2.IVpc; + +new rds.DatabaseCluster(this, 'DatabaseCluster', { + engine: rds.DatabaseClusterEngine.auroraMysql({ version: rds.AuroraMysqlEngineVersion.VER_3_07_0 }), + writer: rds.ClusterInstance.serverlessV2('writerInstance'), + vpc, + autoMinorVersionUpgrade: false, +}); +``` + ### Updating the database instances in a cluster Database cluster instances may be updated in bulk or on a rolling basis. diff --git a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts index 497447811fbad..e858c462795d1 100644 --- a/packages/aws-cdk-lib/aws-rds/lib/cluster.ts +++ b/packages/aws-cdk-lib/aws-rds/lib/cluster.ts @@ -419,6 +419,13 @@ interface DatabaseClusterBaseProps { * @default - default master key */ readonly performanceInsightEncryptionKey?: kms.IKey; + + /** + * Specifies whether minor engine upgrades are applied automatically to the DB cluster during the maintenance window. + * + * @default true + */ + readonly autoMinorVersionUpgrade?: boolean; } /** @@ -795,6 +802,7 @@ abstract class DatabaseClusterNew extends DatabaseClusterBase { performanceInsightsEnabled: this.performanceInsightsEnabled || props.enablePerformanceInsights, // fall back to undefined if not set performanceInsightsKmsKeyId: this.performanceInsightEncryptionKey?.keyArn, performanceInsightsRetentionPeriod: this.performanceInsightRetention, + autoMinorVersionUpgrade: props.autoMinorVersionUpgrade, }; } diff --git a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts index c3e4dcbe27eff..b9018199b1376 100644 --- a/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts +++ b/packages/aws-cdk-lib/aws-rds/test/cluster.test.ts @@ -143,6 +143,27 @@ describe('cluster new api', () => { }); describe('cluster options', () => { + test.each([true, false])('specify auto minor version upgrade', (autoMinorVersionUpgrade) => { + // GIVEN + const stack = testStack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + + // WHEN + new DatabaseCluster(stack, 'Database', { + engine: DatabaseClusterEngine.AURORA_MYSQL, + vpc, + autoMinorVersionUpgrade, + writer: ClusterInstance.serverlessV2('writer'), + }); + + // THEN + const template = Template.fromStack(stack); + template.hasResourceProperties('AWS::RDS::DBCluster', { + Engine: 'aurora-mysql', + AutoMinorVersionUpgrade: autoMinorVersionUpgrade, + }); + }); + test('with serverless instances', () => { // GIVEN const stack = testStack(); From 4e715b830b7790cab1f4c01361a7c5a72851a297 Mon Sep 17 00:00:00 2001 From: Rico Hermans Date: Fri, 1 Nov 2024 11:43:15 +0100 Subject: [PATCH 07/42] refactor: gate access to environment SDK behind new class (#31904) Previously there were methods on the `Deployments` class that made it possible to directly get an SDK from the `SdkProvider` for a particular environment. Calling these methods made it possible to get an SDK without thinking of assuming roles to go into a different account. This PR introduces a new class, `EnvironmentAccess`, with a couple of public methods that are the only ones allowed to obtain SDKs with credentials. It has the methods: - accessStackForStackOperations(stack) - accessStackForLookup(stack) - accessStackForReading(stack) These will always respect the role information on the stack. Ideally there would have been similar methods for assets as well, but the `cdk-assets` library is entirely handling asset roles itself, and it's not in the scope of this PR to change that. That keeps on using a plain `SdkProvider`. Hotswap deployments will also just use CLI credentials and not assume role, so that also keeps on using an `SdkProvider`. All other uses have moved to `EnvironmentAccess`. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../lib/api/bootstrap/bootstrap-props.ts | 3 +- packages/aws-cdk/lib/api/deploy-stack.ts | 22 +- packages/aws-cdk/lib/api/deployments.ts | 354 ++++-------------- .../aws-cdk/lib/api/environment-access.ts | 272 ++++++++++++++ .../lib/api/logs/find-cloudwatch-logs.ts | 9 +- .../aws-cdk/lib/api/util/cloudformation.ts | 12 +- packages/aws-cdk/lib/api/util/placeholders.ts | 8 +- packages/aws-cdk/lib/util/type-brands.ts | 44 +++ .../api/cloudformation-deployments.test.ts | 31 ++ packages/aws-cdk/test/cdk-toolkit.test.ts | 18 +- packages/aws-cdk/test/version.test.ts | 5 + 11 files changed, 473 insertions(+), 305 deletions(-) create mode 100644 packages/aws-cdk/lib/api/environment-access.ts create mode 100644 packages/aws-cdk/lib/util/type-brands.ts diff --git a/packages/aws-cdk/lib/api/bootstrap/bootstrap-props.ts b/packages/aws-cdk/lib/api/bootstrap/bootstrap-props.ts index 47ce8e2a78532..3f01a6ebbbe42 100644 --- a/packages/aws-cdk/lib/api/bootstrap/bootstrap-props.ts +++ b/packages/aws-cdk/lib/api/bootstrap/bootstrap-props.ts @@ -1,4 +1,5 @@ import { Tag } from '../../cdk-toolkit'; +import { StringWithoutPlaceholders } from '../util/placeholders'; export const BUCKET_NAME_OUTPUT = 'BucketName'; export const REPOSITORY_NAME_OUTPUT = 'ImageRepositoryName'; @@ -17,7 +18,7 @@ export const DEFAULT_BOOTSTRAP_VARIANT = 'AWS CDK: Default Resources'; */ export interface BootstrapEnvironmentOptions { readonly toolkitStackName?: string; - readonly roleArn?: string; + readonly roleArn?: StringWithoutPlaceholders; readonly parameters?: BootstrappingParameters; readonly force?: boolean; diff --git a/packages/aws-cdk/lib/api/deploy-stack.ts b/packages/aws-cdk/lib/api/deploy-stack.ts index 16da0447b81f5..fff70866b617c 100644 --- a/packages/aws-cdk/lib/api/deploy-stack.ts +++ b/packages/aws-cdk/lib/api/deploy-stack.ts @@ -19,6 +19,7 @@ import { TemplateBodyParameter, makeBodyParameter } from './util/template-body-p import { AssetManifestBuilder } from '../util/asset-manifest-builder'; import { determineAllowCrossAccountAssetPublishing } from './util/checks'; import { publishAssets } from '../util/asset-publishing'; +import { StringWithoutPlaceholders } from './util/placeholders'; export interface DeployStackResult { readonly noOp: boolean; @@ -51,14 +52,13 @@ export interface DeployStackOptions { /** * SDK provider (seeded with default credentials) * - * Will exclusively be used to assume publishing credentials (which must - * start out from current credentials regardless of whether we've assumed an - * action role to touch the stack or not). + * Will be used to: * - * Used for the following purposes: - * - * - Publish legacy assets. - * - Upload large CloudFormation templates to the staging bucket. + * - Publish assets, either legacy assets or large CFN templates + * that aren't themselves assets from a manifest. (Needs an SDK + * Provider because the file publishing role is declared as part + * of the asset). + * - Hotswap */ readonly sdkProvider: SdkProvider; @@ -70,9 +70,13 @@ export interface DeployStackOptions { /** * Role to pass to CloudFormation to execute the change set * - * @default - Role specified on stack, otherwise current + * To obtain a `StringWithoutPlaceholders`, run a regular + * string though `TargetEnvironment.replacePlaceholders`. + * + * @default - No execution role; CloudFormation either uses the role currently associated with + * the stack, or otherwise uses current AWS credentials. */ - readonly roleArn?: string; + readonly roleArn?: StringWithoutPlaceholders; /** * Notification ARNs to pass to CloudFormation to notify when the change set has completed diff --git a/packages/aws-cdk/lib/api/deployments.ts b/packages/aws-cdk/lib/api/deployments.ts index 6231aa9a70567..1240127469804 100644 --- a/packages/aws-cdk/lib/api/deployments.ts +++ b/packages/aws-cdk/lib/api/deployments.ts @@ -4,56 +4,25 @@ import * as cdk_assets from 'cdk-assets'; import { AssetManifest, IManifestEntry } from 'cdk-assets'; import * as chalk from 'chalk'; import { Tag } from '../cdk-toolkit'; -import { debug, warning, error } from '../logging'; -import { Mode } from './aws-auth/credentials'; -import { ISDK } from './aws-auth/sdk'; -import { CredentialsOptions, SdkForEnvironment, SdkProvider } from './aws-auth/sdk-provider'; +import { debug, warning } from '../logging'; +import { SdkProvider } from './aws-auth/sdk-provider'; import { deployStack, DeployStackResult, destroyStack, DeploymentMethod } from './deploy-stack'; -import { EnvironmentResources, EnvironmentResourcesRegistry } from './environment-resources'; +import { EnvironmentAccess } from './environment-access'; +import { EnvironmentResources } from './environment-resources'; import { HotswapMode, HotswapPropertyOverrides } from './hotswap/common'; import { loadCurrentTemplateWithNestedStacks, loadCurrentTemplate, RootTemplateWithNestedStacks } from './nested-stack-helpers'; +import { DEFAULT_TOOLKIT_STACK_NAME } from './toolkit-info'; import { determineAllowCrossAccountAssetPublishing } from './util/checks'; import { CloudFormationStack, Template, ResourcesToImport, ResourceIdentifierSummaries, stabilizeStack, uploadStackTemplateAssets } from './util/cloudformation'; import { StackActivityMonitor, StackActivityProgress } from './util/cloudformation/stack-activity-monitor'; import { StackEventPoller } from './util/cloudformation/stack-event-poller'; import { RollbackChoice } from './util/cloudformation/stack-status'; -import { replaceEnvPlaceholders } from './util/placeholders'; import { makeBodyParameter } from './util/template-body-parameter'; import { AssetManifestBuilder } from '../util/asset-manifest-builder'; import { buildAssets, publishAssets, BuildAssetsOptions, PublishAssetsOptions, PublishingAws, EVENT_TO_LOGGER } from '../util/asset-publishing'; const BOOTSTRAP_STACK_VERSION_FOR_ROLLBACK = 23; -/** - * SDK obtained by assuming the lookup role - * for a given environment - */ -export interface PreparedSdkWithLookupRoleForEnvironment { - /** - * The SDK for the given environment - */ - readonly sdk: ISDK; - - /** - * The resolved environment for the stack - * (no more 'unknown-account/unknown-region') - */ - readonly resolvedEnvironment: cxapi.Environment; - - /** - * Whether or not the assume role was successful. - * If the assume role was not successful (false) - * then that means that the 'sdk' returned contains - * the default credentials (not the assume role credentials) - */ - readonly didAssumeRole: boolean; - - /** - * An object for accessing the bootstrap resources in this environment - */ - readonly envResources: EnvironmentResources; -} - export interface DeployStackOptions { /** * Stack to deploy @@ -352,69 +321,61 @@ export interface DeploymentsProps { } /** - * SDK obtained by assuming the deploy role - * for a given environment + * Scope for a single set of deployments from a set of Cloud Assembly Artifacts + * + * Manages lookup of SDKs, Bootstrap stacks, etc. */ -export interface PreparedSdkForEnvironment { - /** - * The SDK for the given environment - */ - readonly stackSdk: ISDK; +export class Deployments { + public readonly envs: EnvironmentAccess; /** - * The resolved environment for the stack - * (no more 'unknown-account/unknown-region') - */ - readonly resolvedEnvironment: cxapi.Environment; - /** - * The Execution Role that should be passed to CloudFormation. + * SDK provider for asset publishing (do not use for anything else). + * + * This SDK provider is only allowed to be used for that purpose, nothing else. * - * @default - no execution role is used + * It's not a different object, but the field name should imply that this + * object should not be used directly, except to pass to asset handling routines. */ - readonly cloudFormationRoleArn?: string; + private readonly assetSdkProvider: SdkProvider; /** - * Access class for environmental resources to help the deployment + * SDK provider for passing to deployStack + * + * This SDK provider is only allowed to be used for that purpose, nothing else. + * + * It's not a different object, but the field name should imply that this + * object should not be used directly, except to pass to `deployStack`. */ - readonly envResources: EnvironmentResources; -} + private readonly deployStackSdkProvider: SdkProvider; -/** - * Scope for a single set of deployments from a set of Cloud Assembly Artifacts - * - * Manages lookup of SDKs, Bootstrap stacks, etc. - */ -export class Deployments { - private readonly sdkProvider: SdkProvider; - private readonly sdkCache = new Map(); private readonly publisherCache = new Map(); - private readonly environmentResources: EnvironmentResourcesRegistry; private _allowCrossAccountAssetPublishing: boolean | undefined; constructor(private readonly props: DeploymentsProps) { - this.sdkProvider = props.sdkProvider; - this.environmentResources = new EnvironmentResourcesRegistry(props.toolkitStackName); + this.assetSdkProvider = props.sdkProvider; + this.deployStackSdkProvider = props.sdkProvider; + this.envs = new EnvironmentAccess(props.sdkProvider, props.toolkitStackName ?? DEFAULT_TOOLKIT_STACK_NAME); } /** * Resolves the environment for a stack. */ public async resolveEnvironment(stack: cxapi.CloudFormationStackArtifact): Promise { - return this.sdkProvider.resolveEnvironment(stack.environment); + return this.envs.resolveStackEnvironment(stack); } public async readCurrentTemplateWithNestedStacks( rootStackArtifact: cxapi.CloudFormationStackArtifact, retrieveProcessedTemplate: boolean = false, ): Promise { - const sdk = (await this.prepareSdkWithLookupOrDeployRole(rootStackArtifact)).stackSdk; - return loadCurrentTemplateWithNestedStacks(rootStackArtifact, sdk, retrieveProcessedTemplate); + const env = await this.envs.accessStackForLookupBestEffort(rootStackArtifact); + return loadCurrentTemplateWithNestedStacks(rootStackArtifact, env.sdk, retrieveProcessedTemplate); } public async readCurrentTemplate(stackArtifact: cxapi.CloudFormationStackArtifact): Promise