From cfa7a342b524b82b187b64405aab5f767ca49669 Mon Sep 17 00:00:00 2001 From: Mike Dial Date: Tue, 28 Nov 2023 22:47:34 -0500 Subject: [PATCH 1/3] Apply bucket policies in a different way, to temporarily get around cms active remediation race conditions --- src/services/uploads/serverless.yml | 32 ++++++++++++++++++------- src/services/uploads/src/applyPolicy.ts | 25 +++++++++++++++++++ 2 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 src/services/uploads/src/applyPolicy.ts diff --git a/src/services/uploads/serverless.yml b/src/services/uploads/serverless.yml index 280c152962..8c067cde1d 100644 --- a/src/services/uploads/serverless.yml +++ b/src/services/uploads/serverless.yml @@ -43,6 +43,13 @@ provider: - lambda:InvokeFunction Resource: - !Sub arn:aws:lambda:${self:provider.region}:${AWS::AccountId}:function:${self:service}-${sls:stage}-avDownloadDefinitions + - Effect: "Allow" + Action: + - "s3:GetBucketPolicy" + - "s3:PutBucketPolicy" + Resource: + - !Sub "arn:aws:s3:::${self:service}-${sls:stage}-attachments-${AWS::AccountId}" + - !Sub "arn:aws:s3:::${self:service}-${sls:stage}-avscan-${AWS::AccountId}" custom: project: ${env:PROJECT} @@ -93,6 +100,10 @@ functions: handler: src/triggerInitialDownload.handler timeout: 300 # 300 seconds = 5 minutes memorySize: 1024 + applyPolicy: + handler: src/applyPolicy.handler + timeout: 300 + memorySize: 1024 resources: Resources: AttachmentsBucket: @@ -120,12 +131,13 @@ resources: - Event: s3:ObjectCreated:* Function: !GetAtt AvScanLambdaFunction.Arn DependsOn: LambdaInvokePermission - S3CMSReadBucketPolicy: - Type: AWS::S3::BucketPolicy + AttachmentsBucketPolicy: + Type: Custom::AttachmentsBucketPolicy Properties: - Bucket: - Ref: AttachmentsBucket - PolicyDocument: + ServiceToken: !GetAtt ApplyPolicyLambdaFunction.Arn + Bucket: !Ref AttachmentsBucket + Policy: + Version: "2012-10-17" Statement: - Effect: Deny Principal: "*" @@ -165,11 +177,13 @@ resources: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 ClamDefsBucketPolicy: - Type: AWS::S3::BucketPolicy + Type: Custom::ClamDefsBucketPolicy Properties: - Bucket: - Ref: ClamDefsBucket - PolicyDocument: + ServiceToken: !GetAtt ApplyPolicyLambdaFunction.Arn + Bucket: !Ref ClamDefsBucket + a: a + Policy: + Version: "2012-10-17" Statement: - Effect: Deny Principal: "*" diff --git a/src/services/uploads/src/applyPolicy.ts b/src/services/uploads/src/applyPolicy.ts new file mode 100644 index 0000000000..a8db3fe701 --- /dev/null +++ b/src/services/uploads/src/applyPolicy.ts @@ -0,0 +1,25 @@ +import { Handler } from "aws-lambda"; +import { send, SUCCESS, FAILED } from "cfn-response-async"; +type ResponseStatus = typeof SUCCESS | typeof FAILED; +import { S3Client, PutBucketPolicyCommand } from '@aws-sdk/client-s3'; +const s3 = new S3Client(); + +export const handler: Handler = async (event, context) => { + console.log("request:", JSON.stringify(event, undefined, 2)); + const responseData = {}; + let responseStatus: ResponseStatus = SUCCESS; + let Bucket = event.ResourceProperties.Bucket; + let Policy = JSON.stringify(event.ResourceProperties.Policy); + try { + if (event.RequestType == "Create" || event.RequestType == "Update") { + let resp = await s3.send(new PutBucketPolicyCommand({ Bucket, Policy })); + console.log(resp) + } + } catch (error) { + console.log(error); + responseStatus = FAILED; + } finally { + console.log("finally"); + await send(event, context, responseStatus, responseData); + } +}; From 340cd80cc935babf62b9d8293f689a02664c1fc7 Mon Sep 17 00:00:00 2001 From: Mike Dial Date: Wed, 29 Nov 2023 12:41:56 -0500 Subject: [PATCH 2/3] Add a force override --- src/services/uploads/serverless.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/uploads/serverless.yml b/src/services/uploads/serverless.yml index 8c067cde1d..b034369078 100644 --- a/src/services/uploads/serverless.yml +++ b/src/services/uploads/serverless.yml @@ -55,6 +55,7 @@ custom: project: ${env:PROJECT} accountId: !Sub "${AWS::AccountId}" stage: ${opt:stage, self:provider.stage} + forceApplyBucketPolicies: ${ssm:/aws/reference/secretsmanager/${self:custom.project}/${sls:stage}/forceApplyBucketPolicies, ssm:/aws/reference/secretsmanager/${self:custom.project}/default/forceApplyBucketPolicies, "blank"} serverlessTerminationProtection: stages: # Apply CloudFormation termination protection for these stages - master @@ -135,6 +136,7 @@ resources: Type: Custom::AttachmentsBucketPolicy Properties: ServiceToken: !GetAtt ApplyPolicyLambdaFunction.Arn + ForceApply: ${self:custom.forceApplyBucketPolicies} Bucket: !Ref AttachmentsBucket Policy: Version: "2012-10-17" @@ -180,8 +182,8 @@ resources: Type: Custom::ClamDefsBucketPolicy Properties: ServiceToken: !GetAtt ApplyPolicyLambdaFunction.Arn + ForceApply: ${self:custom.forceApplyBucketPolicies} Bucket: !Ref ClamDefsBucket - a: a Policy: Version: "2012-10-17" Statement: From 27d06d3f8e7e3b85bec3742539c31ca85c3403fe Mon Sep 17 00:00:00 2001 From: Mike Dial Date: Wed, 29 Nov 2023 12:43:15 -0500 Subject: [PATCH 3/3] Make it clear that these are custom resources --- src/services/uploads/serverless.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/uploads/serverless.yml b/src/services/uploads/serverless.yml index b034369078..a572c3f0d3 100644 --- a/src/services/uploads/serverless.yml +++ b/src/services/uploads/serverless.yml @@ -132,7 +132,7 @@ resources: - Event: s3:ObjectCreated:* Function: !GetAtt AvScanLambdaFunction.Arn DependsOn: LambdaInvokePermission - AttachmentsBucketPolicy: + AttachmentsBucketPolicyCustomResource: Type: Custom::AttachmentsBucketPolicy Properties: ServiceToken: !GetAtt ApplyPolicyLambdaFunction.Arn @@ -178,7 +178,7 @@ resources: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: AES256 - ClamDefsBucketPolicy: + ClamDefsBucketPolicyCustomResource: Type: Custom::ClamDefsBucketPolicy Properties: ServiceToken: !GetAtt ApplyPolicyLambdaFunction.Arn