diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-deployment/test/integ.bucket-deployment.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-deployment/test/integ.bucket-deployment.ts index b067b0b50d6b4..8e80254b955a9 100644 --- a/packages/@aws-cdk-testing/framework-integ/test/aws-s3-deployment/test/integ.bucket-deployment.ts +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-s3-deployment/test/integ.bucket-deployment.ts @@ -34,6 +34,23 @@ class TestBucketDeployment extends cdk.Stack { retainOnDelete: false, // default is true, which will block the integration test cleanup }); + const vpc = new ec2.Vpc(this, 'InlineVpc', { restrictDefaultSecurityGroup: false }) + const sg1 = new ec2.SecurityGroup(this, 's3deploy-sg', { + vpc, + allowAllOutbound: false, + disableInlineRules: false, + }) + sg1.addEgressRule(ec2.Peer.ipv4('10.0.0.0/8'), ec2.Port.tcp(443)) + + new s3deploy.BucketDeployment(this, 'DeployWithSecurityGroup', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'my-website'))], + destinationBucket, + destinationKeyPrefix: 'data/', + vpc, + securityGroups: [sg1], + retainOnDelete: false, // default is true, which will block the integration test cleanup + }); + const bucket2 = new s3.Bucket(this, 'Destination2', { removalPolicy: cdk.RemovalPolicy.DESTROY, autoDeleteObjects: true, // needed for integration test cleanup diff --git a/packages/aws-cdk-lib/aws-s3-deployment/README.md b/packages/aws-cdk-lib/aws-s3-deployment/README.md index 1c290c61d7a68..d6aecd5ada90a 100644 --- a/packages/aws-cdk-lib/aws-s3-deployment/README.md +++ b/packages/aws-cdk-lib/aws-s3-deployment/README.md @@ -304,6 +304,24 @@ resource handler. > NOTE: a new AWS Lambda handler will be created in your stack for each combination > of memory and storage size. +## Connectivity Control +To constraint the network connectivity of the underlying lambda function you can provide `vpc`, `subnets` and `securityGroup` properties + +```ts +declare const destinationBucket: s3.Bucket; +declare const vpc: ec2.Vpc; +declare const subnets: ec2.SubnetSelection +declare const securityGroups: ec2.SecurityGroup[] + +new s3deploy.BucketDeployment(this, 'DeployMeWithEfsStorage', { + sources: [s3deploy.Source.asset(path.join(__dirname, 'content'))], + destinationBucket, + vpcSubnets, + securityGroups, + vpc, +}); +``` + ## EFS Support If your workflow needs more disk space than default (512 MB) disk space, you may attach an EFS storage to underlying diff --git a/packages/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.ts b/packages/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.ts index 5d782dfb6bc49..f4d8ec7d2f4e2 100644 --- a/packages/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.ts +++ b/packages/aws-cdk-lib/aws-s3-deployment/lib/bucket-deployment.ts @@ -258,6 +258,13 @@ export interface BucketDeploymentProps { */ readonly vpcSubnets?: ec2.SubnetSelection; + /** + * Security group to use with the vpc and subnet. + * + * @default - the Vpc default strategy if not specified + */ + readonly securityGroups?: ec2.SecurityGroup[]; + /** * If set to true, uploads will precompute the value of `x-amz-content-sha256` * and include it in the signed S3 request headers. @@ -345,6 +352,7 @@ export class BucketDeployment extends Construct { ephemeralStorageSize: props.ephemeralStorageSize, vpc: props.vpc, vpcSubnets: props.vpcSubnets, + securityGroups: props.securityGroups, filesystem: accessPoint ? lambda.FileSystem.fromEfsAccessPoint( accessPoint, mountPath, diff --git a/packages/aws-cdk-lib/aws-s3-deployment/test/bucket-deployment.test.ts b/packages/aws-cdk-lib/aws-s3-deployment/test/bucket-deployment.test.ts index 34801b97bb58b..fa0457eca0df5 100644 --- a/packages/aws-cdk-lib/aws-s3-deployment/test/bucket-deployment.test.ts +++ b/packages/aws-cdk-lib/aws-s3-deployment/test/bucket-deployment.test.ts @@ -1090,7 +1090,7 @@ test('deployment allows vpc to be implicitly supplied to lambda', () => { }); }); -test('deployment allows vpc and subnets to be implicitly supplied to lambda', () => { +test('deployment allows vpc, subnets and security groups to be explicitly supplied to lambda', () => { // GIVEN const stack = new cdk.Stack(); @@ -1101,6 +1101,14 @@ test('deployment allows vpc and subnets to be implicitly supplied to lambda', () availabilityZone: vpc.availabilityZones[0], cidrBlock: vpc.vpcCidrBlock, }); + const sg: ec2.SecurityGroup[] = [ + new ec2.SecurityGroup(stack, 'sg1', { + vpc, + allowAllOutbound: false, + description: 'custom security group', + securityGroupName: 'controlled egress', + }), + ]; // WHEN new s3deploy.BucketDeployment(stack, 'DeployWithVpc2', { @@ -1110,6 +1118,7 @@ test('deployment allows vpc and subnets to be implicitly supplied to lambda', () vpcSubnets: { availabilityZones: [vpc.availabilityZones[0]], }, + securityGroups: sg, }); // THEN @@ -1118,7 +1127,7 @@ test('deployment allows vpc and subnets to be implicitly supplied to lambda', () SecurityGroupIds: [ { 'Fn::GetAtt': [ - 'CustomCDKBucketDeployment8693BB64968944B69AAFB0CC9EB8756Cc8a39596cb8641929fcf6a288bc9db5ab7b0f656adSecurityGroup11274779', + 'sg15CEFF4E3', 'GroupId', ], },