From 1fa399ec0b8db69da19268235403c2c75d423560 Mon Sep 17 00:00:00 2001 From: Benjamin Genz Date: Thu, 9 Nov 2023 21:19:11 +0100 Subject: [PATCH] fix(s3): InventoryConfiguration[].Id exceeds maximum size allowed by the PutBucketInventoryConfiguration API (#27794) Truncate the inventory-id to 64 characters, such that it conforms to the S3 PutBucketInventoryConfiguration API. Also remove non-allowed characters. Closes #27793. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license* --- .../aws-cdk-bucket-inventory.assets.json | 19 ++ .../aws-cdk-bucket-inventory.template.json | 119 +++++++++ .../cdk.out | 1 + ...efaultTestDeployAssertDAAFB0C3.assets.json | 19 ++ ...aultTestDeployAssertDAAFB0C3.template.json | 36 +++ .../integ.json | 12 + .../manifest.json | 125 ++++++++++ .../tree.json | 233 ++++++++++++++++++ .../aws-s3/test/integ.bucket.inventory.ts | 27 ++ packages/aws-cdk-lib/aws-s3/lib/bucket.ts | 7 +- .../aws-cdk-lib/aws-s3/test/bucket.test.ts | 44 ++++ 11 files changed, 641 insertions(+), 1 deletion(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/aws-cdk-bucket-inventory.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/aws-cdk-bucket-inventory.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/aws-cdk-bucket-inventory.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/aws-cdk-bucket-inventory.assets.json new file mode 100644 index 0000000000000..349b266354999 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/aws-cdk-bucket-inventory.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "180347a36a33dec659d066b88751795b94fb6d6aa81d1ad4855a84043e9cc314": { + "source": { + "path": "aws-cdk-bucket-inventory.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "180347a36a33dec659d066b88751795b94fb6d6aa81d1ad4855a84043e9cc314.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-s3/test/integ.bucket.inventory.js.snapshot/aws-cdk-bucket-inventory.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/aws-cdk-bucket-inventory.template.json new file mode 100644 index 0000000000000..429fb513bb965 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/aws-cdk-bucket-inventory.template.json @@ -0,0 +1,119 @@ +{ + "Resources": { + "InventoryBucketA869B8CB": { + "Type": "AWS::S3::Bucket", + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "InventoryBucketPolicyEDF94353": { + "Type": "AWS::S3::BucketPolicy", + "Properties": { + "Bucket": { + "Ref": "InventoryBucketA869B8CB" + }, + "PolicyDocument": { + "Statement": [ + { + "Action": "s3:PutObject", + "Condition": { + "ArnLike": { + "aws:SourceArn": { + "Fn::GetAtt": [ + "AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongNodeIdName525AF55D", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "s3.amazonaws.com" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "InventoryBucketA869B8CB", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "InventoryBucketA869B8CB", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongNodeIdName525AF55D": { + "Type": "AWS::S3::Bucket", + "Properties": { + "InventoryConfigurations": [ + { + "Destination": { + "BucketArn": { + "Fn::GetAtt": [ + "InventoryBucketA869B8CB", + "Arn" + ] + }, + "Format": "CSV" + }, + "Enabled": true, + "Id": "VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongNodeIdNameInventory0", + "IncludedObjectVersions": "All", + "ScheduleFrequency": "Weekly" + } + ] + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + } + }, + "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-s3/test/integ.bucket.inventory.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdk.out new file mode 100644 index 0000000000000..2313ab5436501 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"34.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets.json new file mode 100644 index 0000000000000..afbe7e4f769df --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets.json @@ -0,0 +1,19 @@ +{ + "version": "34.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.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-s3/test/integ.bucket.inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.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-s3/test/integ.bucket.inventory.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/integ.json new file mode 100644 index 0000000000000..bc3dd8d41770e --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "34.0.0", + "testCases": { + "cdk-integ-bucket-inventory/DefaultTest": { + "stacks": [ + "aws-cdk-bucket-inventory" + ], + "assertionStack": "cdk-integ-bucket-inventory/DefaultTest/DeployAssert", + "assertionStackName": "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/manifest.json new file mode 100644 index 0000000000000..6acb931491408 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/manifest.json @@ -0,0 +1,125 @@ +{ + "version": "34.0.0", + "artifacts": { + "aws-cdk-bucket-inventory.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-bucket-inventory.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-bucket-inventory": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-bucket-inventory.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "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}/180347a36a33dec659d066b88751795b94fb6d6aa81d1ad4855a84043e9cc314.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-bucket-inventory.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": [ + "aws-cdk-bucket-inventory.assets" + ], + "metadata": { + "/aws-cdk-bucket-inventory/InventoryBucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InventoryBucketA869B8CB" + } + ], + "/aws-cdk-bucket-inventory/InventoryBucket/Policy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "InventoryBucketPolicyEDF94353" + } + ], + "/aws-cdk-bucket-inventory/AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVery@#$+:;?!&LongNodeIdName/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongNodeIdName525AF55D" + } + ], + "/aws-cdk-bucket-inventory/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-bucket-inventory/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-bucket-inventory" + }, + "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.template.json", + "terminationProtection": false, + "validateOnSynth": false, + "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": [ + "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.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": [ + "cdkintegbucketinventoryDefaultTestDeployAssertDAAFB0C3.assets" + ], + "metadata": { + "/cdk-integ-bucket-inventory/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/cdk-integ-bucket-inventory/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "cdk-integ-bucket-inventory/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-s3/test/integ.bucket.inventory.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/tree.json new file mode 100644 index 0000000000000..395c273ed3980 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.js.snapshot/tree.json @@ -0,0 +1,233 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-bucket-inventory": { + "id": "aws-cdk-bucket-inventory", + "path": "aws-cdk-bucket-inventory", + "children": { + "InventoryBucket": { + "id": "InventoryBucket", + "path": "aws-cdk-bucket-inventory/InventoryBucket", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-bucket-inventory/InventoryBucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucket", + "version": "0.0.0" + } + }, + "Policy": { + "id": "Policy", + "path": "aws-cdk-bucket-inventory/InventoryBucket/Policy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-bucket-inventory/InventoryBucket/Policy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::BucketPolicy", + "aws:cdk:cloudformation:props": { + "bucket": { + "Ref": "InventoryBucketA869B8CB" + }, + "policyDocument": { + "Statement": [ + { + "Action": "s3:PutObject", + "Condition": { + "ArnLike": { + "aws:SourceArn": { + "Fn::GetAtt": [ + "AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongNodeIdName525AF55D", + "Arn" + ] + } + } + }, + "Effect": "Allow", + "Principal": { + "Service": "s3.amazonaws.com" + }, + "Resource": [ + { + "Fn::GetAtt": [ + "InventoryBucketA869B8CB", + "Arn" + ] + }, + { + "Fn::Join": [ + "", + [ + { + "Fn::GetAtt": [ + "InventoryBucketA869B8CB", + "Arn" + ] + }, + "/*" + ] + ] + } + ] + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucketPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.Bucket", + "version": "0.0.0" + } + }, + "AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVery@#$+:;?!&LongNodeIdName": { + "id": "AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVery@#$+:;?!&LongNodeIdName", + "path": "aws-cdk-bucket-inventory/AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVery@#$+:;?!&LongNodeIdName", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-bucket-inventory/AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVery@#$+:;?!&LongNodeIdName/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "inventoryConfigurations": [ + { + "id": "VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongNodeIdNameInventory0", + "destination": { + "bucketArn": { + "Fn::GetAtt": [ + "InventoryBucketA869B8CB", + "Arn" + ] + }, + "format": "CSV" + }, + "enabled": true, + "includedObjectVersions": "All", + "scheduleFrequency": "Weekly" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucket", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.Bucket", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-bucket-inventory/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-bucket-inventory/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "cdk-integ-bucket-inventory": { + "id": "cdk-integ-bucket-inventory", + "path": "cdk-integ-bucket-inventory", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "cdk-integ-bucket-inventory/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "cdk-integ-bucket-inventory/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.2.70" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "cdk-integ-bucket-inventory/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "cdk-integ-bucket-inventory/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "cdk-integ-bucket-inventory/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.2.70" + } + } + }, + "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-s3/test/integ.bucket.inventory.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.ts new file mode 100644 index 0000000000000..5d0f7a6f822f4 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3/test/integ.bucket.inventory.ts @@ -0,0 +1,27 @@ +import { Construct } from 'constructs'; +import { App, Stack, StackProps } from 'aws-cdk-lib/core'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { Bucket } from 'aws-cdk-lib/aws-s3'; + +class TestStack extends Stack { + constructor(scope: Construct, id: string, props?: StackProps) { + super(scope, id, props); + + const inventoryBucket = new Bucket(this, 'InventoryBucket'); + new Bucket(this, 'AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVery@#$+:;?!&LongNodeIdName', { + inventories: [ + { + destination: { + bucket: inventoryBucket, + }, + }, + ], + }); + } +} + +const app = new App(); + +new IntegTest(app, 'cdk-integ-bucket-inventory', { + testCases: [new TestStack(app, 'aws-cdk-bucket-inventory')], +}); diff --git a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts index 8b3e2fa5b6a61..9f4cd6b122163 100644 --- a/packages/aws-cdk-lib/aws-s3/lib/bucket.ts +++ b/packages/aws-cdk-lib/aws-s3/lib/bucket.ts @@ -1250,6 +1250,7 @@ export interface Inventory { readonly enabled?: boolean; /** * The inventory configuration ID. + * Should be limited to 64 characters and can only contain letters, numbers, periods, dashes, and underscores. * * @default - generated ID. */ @@ -2420,11 +2421,15 @@ export class Bucket extends BucketBase { if (!this.inventories || this.inventories.length === 0) { return undefined; } + const inventoryIdValidationRegex = /[^\w\.\-]/g; return this.inventories.map((inventory, index) => { const format = inventory.format ?? InventoryFormat.CSV; const frequency = inventory.frequency ?? InventoryFrequency.WEEKLY; - const id = inventory.inventoryId ?? `${this.node.id}Inventory${index}`; + if (inventory.inventoryId !== undefined && (inventory.inventoryId.length > 64 || inventoryIdValidationRegex.test(inventory.inventoryId))) { + throw new Error(`inventoryId should not exceed 64 characters and should not contain special characters except . and -, got ${inventory.inventoryId}`); + } + const id = inventory.inventoryId ?? `${this.node.id}Inventory${index}`.replace(inventoryIdValidationRegex, '').slice(-64); if (inventory.destination.bucket instanceof Bucket) { inventory.destination.bucket.addToResourcePolicy(new iam.PolicyStatement({ diff --git a/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts b/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts index 88cc9d33dd97d..14f076c419852 100644 --- a/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts +++ b/packages/aws-cdk-lib/aws-s3/test/bucket.test.ts @@ -3134,6 +3134,49 @@ describe('bucket', () => { }); }); + test('Inventory Ids are shortened to 64 characters', () => { + // Given + const stack = new cdk.Stack(); + + const inventoryBucket = new s3.Bucket(stack, 'InventoryBucket'); + new s3.Bucket(stack, 'AVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVery@#$+:;?!&LongNodeIdName', { + inventories: [ + { + destination: { + bucket: inventoryBucket, + }, + }, + ], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::S3::Bucket', { + InventoryConfigurations: Match.arrayWith([ + Match.objectLike({ + Id: 'VeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongNodeIdNameInventory0', + }), + ]), + }); + }); + + test('throws when inventoryid is invalid', () => { + // Given + const stack = new cdk.Stack(); + + const inventoryBucket = new s3.Bucket(stack, 'InventoryBucket'); + new s3.Bucket(stack, 'MyBucket2', { + inventories: [ + { + destination: { + bucket: inventoryBucket, + }, + inventoryId: 'InvalidId&123', + }, + ], + }); + + expect(() => Template.fromStack(stack)).toThrow(/inventoryId should not exceed 64 characters and should not contain special characters except . and -, got InvalidId&123/); + }); + test('Bucket with objectOwnership set to BUCKET_OWNER_ENFORCED', () => { const stack = new cdk.Stack(); new s3.Bucket(stack, 'MyBucket', { @@ -3644,3 +3687,4 @@ describe('bucket', () => { }); }); }); +