From 422a8e1d6964a48bcd4338efe27b997c3da478b0 Mon Sep 17 00:00:00 2001 From: George Heming Date: Mon, 1 Apr 2024 01:47:28 +0000 Subject: [PATCH] feat(s3-deployment): add security groups expose securityGroups attribute of lambda underlying s3 bucket deployment to provide more control over connectivity rules --- .../test/integ.bucket-deployment.ts | 17 +++++++++++++++++ .../aws-cdk-lib/aws-s3-deployment/README.md | 18 ++++++++++++++++++ .../aws-s3-deployment/lib/bucket-deployment.ts | 8 ++++++++ .../test/bucket-deployment.test.ts | 13 +++++++++++-- 4 files changed, 54 insertions(+), 2 deletions(-) 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 bf74e108d345f..8c47b541dd43d 100644 --- a/packages/aws-cdk-lib/aws-s3-deployment/README.md +++ b/packages/aws-cdk-lib/aws-s3-deployment/README.md @@ -356,6 +356,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, 'DeployMeWithVpc', { + 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 fa7df6a1cbf51..9f134d1f0792e 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. @@ -349,6 +356,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', ], },