Skip to content

Commit

Permalink
Merge pull request #757 from Enterprise-CMCS/main
Browse files Browse the repository at this point in the history
Release to val
  • Loading branch information
mdial89f committed Sep 9, 2024
2 parents a4984cd + b679a3a commit 57540d6
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 180 deletions.
12 changes: 6 additions & 6 deletions .envrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,6 @@ export PROJECT=mako
# Define the regions for deployment
export REGION_A=us-east-1

# Put top level node_modules on the path. This includes serverless, typescript, etc.
PATH_add ./node_modules/.bin

# Put this dir on path, to include the run script
PATH_add .

# setup for nvm use command
use_nvm() {
local node_version=$1
Expand All @@ -24,4 +18,10 @@ use_nvm() {

use nvm

# Put top level node_modules on the path. This includes serverless, typescript, etc.
PATH_add ./node_modules/.bin

# Put this dir on path, to include the run script
PATH_add .

export TURBO_TELEMETRY_DISABLED=1
Binary file modified bun.lockb
Binary file not shown.
19 changes: 8 additions & 11 deletions lib/local-constructs/clamav-scanning/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,28 +24,25 @@ interface ClamScanScannerProps {
}

export class ClamScanScanner extends Construct {
public readonly clamDefsBucket: s3.Bucket;
public readonly lambdaRole: iam.Role;

constructor(scope: Construct, id: string, props: ClamScanScannerProps) {
super(scope, id);
const { fileBucket } = props;

// S3 Bucket
this.clamDefsBucket = new s3.Bucket(this, `ClamDefsBucket`, {
const clamDefsBucket = new s3.Bucket(this, `ClamDefsBucket`, {
versioned: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: true,
});

this.clamDefsBucket.addToResourcePolicy(
clamDefsBucket.addToResourcePolicy(
new iam.PolicyStatement({
effect: iam.Effect.DENY,
principals: [new iam.AnyPrincipal()],
actions: ["s3:*"],
resources: [
this.clamDefsBucket.bucketArn,
`${this.clamDefsBucket.bucketArn}/*`,
],
resources: [clamDefsBucket.bucketArn, `${clamDefsBucket.bucketArn}/*`],
conditions: {
Bool: { "aws:SecureTransport": "false" },
},
Expand Down Expand Up @@ -142,8 +139,8 @@ export class ClamScanScanner extends Construct {
resources: [
fileBucket.bucketArn,
`${fileBucket.bucketArn}/*`,
this.clamDefsBucket.bucketArn,
`${this.clamDefsBucket.bucketArn}/*`,
clamDefsBucket.bucketArn,
`${clamDefsBucket.bucketArn}/*`,
],
}),
new iam.PolicyStatement({
Expand Down Expand Up @@ -183,7 +180,7 @@ export class ClamScanScanner extends Construct {
onSuccess: new destinations.SqsDestination(successQueue),
onFailure: new destinations.SqsDestination(failureQueue),
environment: {
CLAMAV_BUCKET_NAME: this.clamDefsBucket.bucketName,
CLAMAV_BUCKET_NAME: clamDefsBucket.bucketName,
PATH_TO_AV_DEFINITIONS: "lambda/s3-antivirus/av-definitions",
},
});
Expand All @@ -205,7 +202,7 @@ export class ClamScanScanner extends Construct {
onSuccess: new destinations.SqsDestination(successQueue),
onFailure: new destinations.SqsDestination(failureQueue),
environment: {
CLAMAV_BUCKET_NAME: this.clamDefsBucket.bucketName,
CLAMAV_BUCKET_NAME: clamDefsBucket.bucketName,
PATH_TO_AV_DEFINITIONS: "lambda/s3-antivirus/av-definitions",
},
reservedConcurrentExecutions: 1,
Expand Down
48 changes: 30 additions & 18 deletions lib/local-constructs/empty-buckets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,35 @@ export class EmptyBuckets extends Construct {
const bucketArns = buckets.map((bucket) => bucket.bucketArn);
const bucketNames = buckets.map((bucket) => bucket.bucketName);

// Define the statements array and conditionally add the S3 policy statement
const statements = [];

// Add S3 policy only if bucketArns is not empty
if (bucketArns.length > 0) {
statements.push(
new PolicyStatement({
actions: [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:PutBucketPolicy",
"s3:GetBucketPolicy",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
],
resources: bucketArns,
}),
);
}

// Add the DENY logs:CreateLogGroup policy statement
statements.push(
new PolicyStatement({
effect: Effect.DENY,
actions: ["logs:CreateLogGroup"],
resources: ["*"],
}),
);

const lambdaRole = new Role(this, "LambdaRole", {
assumedBy: new ServicePrincipal("lambda.amazonaws.com"),
managedPolicies: [
Expand All @@ -42,24 +71,7 @@ export class EmptyBuckets extends Construct {
],
inlinePolicies: {
LambdaPolicy: new PolicyDocument({
statements: [
new PolicyStatement({
actions: [
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:PutBucketPolicy",
"s3:GetBucketPolicy",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
],
resources: bucketArns,
}),
new PolicyStatement({
effect: Effect.DENY,
actions: ["logs:CreateLogGroup"],
resources: ["*"],
}),
],
statements: statements,
}),
},
});
Expand Down
126 changes: 3 additions & 123 deletions lib/local-constructs/empty-buckets/src/emptyBuckets.ts
Original file line number Diff line number Diff line change
@@ -1,126 +1,6 @@
import {
S3Client,
ListObjectVersionsCommand,
DeleteObjectsCommand,
ObjectIdentifier,
ObjectVersion,
DeleteMarkerEntry,
PutBucketPolicyCommand,
GetBucketPolicyCommand,
} from "@aws-sdk/client-s3";

const s3 = new S3Client({ region: process.env.AWS_REGION });

export const handler = async function (event: any) {
console.log("Request received:\n", JSON.stringify(event, null, 2));

if (event.RequestType === "Delete") {
const buckets = event.ResourceProperties.Buckets;
for (const bucket of buckets) {
await blockAllUploads(bucket);
await deleteAllObjects(bucket);
}
}
console.log(
"This pattern is OBE. For lifecycle reasons, it will remain until it's released, then removed entirely",
);
};

async function blockAllUploads(bucket: string) {
let existingPolicy;

try {
const getBucketPolicyParams = {
Bucket: bucket,
};
const response = await s3.send(
new GetBucketPolicyCommand(getBucketPolicyParams),
);
console.log(response);
existingPolicy = response.Policy
? JSON.parse(response.Policy)
: {
Version: "2012-10-17",
Statement: [],
};
} catch (error) {
if (error.name === "NoSuchBucketPolicy") {
existingPolicy = {
Version: "2012-10-17",
Statement: [],
};
} else {
throw error;
}
}

const newStatement = {
Effect: "Deny",
Principal: "*",
Action: "s3:PutObject",
Resource: `arn:aws:s3:::${bucket}/*`,
};

existingPolicy.Statement.push(newStatement);

const putBucketPolicyParams = {
Bucket: bucket,
Policy: JSON.stringify(existingPolicy),
};

await s3.send(new PutBucketPolicyCommand(putBucketPolicyParams));
}

async function listAllObjects(bucket: string): Promise<ObjectIdentifier[]> {
let contents: ObjectIdentifier[] = [];
let isTruncated = true;
let keyMarker: string | undefined;
let versionIdMarker: string | undefined;

while (isTruncated) {
const response = await s3.send(
new ListObjectVersionsCommand({
Bucket: bucket,
KeyMarker: keyMarker,
VersionIdMarker: versionIdMarker,
}),
);

if (response.Versions) {
contents = contents.concat(
response.Versions.map((version: ObjectVersion) => ({
Key: version.Key!,
VersionId: version.VersionId,
})),
);
}

if (response.DeleteMarkers) {
contents = contents.concat(
response.DeleteMarkers.map((marker: DeleteMarkerEntry) => ({
Key: marker.Key!,
VersionId: marker.VersionId,
})),
);
}

isTruncated = response.IsTruncated!;
keyMarker = response.NextKeyMarker;
versionIdMarker = response.NextVersionIdMarker;
}

return contents;
}

async function deleteAllObjects(bucket: string) {
const objects = await listAllObjects(bucket);

const chunkSize = 1000; // Max 1000 objects per batch
for (let i = 0; i < objects.length; i += chunkSize) {
const chunk = objects.slice(i, i + chunkSize);
const deleteParams = {
Bucket: bucket,
Delete: {
Objects: chunk,
},
};
await s3.send(new DeleteObjectsCommand(deleteParams));
}
}
18 changes: 8 additions & 10 deletions lib/stacks/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export class Api extends cdk.NestedStack {
private initializeResources(props: ApiStackProps): {
apiGateway: cdk.aws_apigateway.RestApi;
} {
const { project, stage, stack } = props;
const { project, stage, isDev, stack } = props;
const {
vpc,
privateSubnets,
Expand Down Expand Up @@ -566,6 +566,7 @@ export class Api extends cdk.NestedStack {
encryption: BucketEncryption.S3_MANAGED,
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: isDev,
});

logBucket.addToResourcePolicy(
Expand All @@ -580,19 +581,16 @@ export class Api extends cdk.NestedStack {
}),
);

const emptyBuckets = new LC.EmptyBuckets(this, "EmptyBuckets", {
buckets: [logBucket],
new LC.EmptyBuckets(this, "EmptyBuckets", {
buckets: [],
});

const cloudwatchToS3 = new LC.CloudWatchToS3(
this,
"CloudWatchToS3Construct",
{
if (!isDev) {
new LC.CloudWatchToS3(this, "CloudWatchToS3Construct", {
logGroup: waf.logGroup,
bucket: logBucket,
},
);
cloudwatchToS3.node.addDependency(emptyBuckets);
});
}

return { apiGateway: api };
}
Expand Down
3 changes: 3 additions & 0 deletions lib/stacks/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as LC from "local-constructs";
interface EmailServiceStackProps extends cdk.StackProps {
project: string;
stage: string;
isDev: boolean;
stack: string;
vpc: cdk.aws_ec2.IVpc;
applicationEndpoint: string;
Expand All @@ -30,6 +31,7 @@ export class Email extends cdk.NestedStack {
const {
project,
stage,
isDev,
stack,
vpc,
emailFromIdentity,
Expand Down Expand Up @@ -90,6 +92,7 @@ export class Email extends cdk.NestedStack {
const emailDataBucket = new cdk.aws_s3.Bucket(this, "EmailDataBucket", {
versioned: true,
removalPolicy: cdk.RemovalPolicy.DESTROY,
autoDeleteObjects: isDev,
});

emailDataBucket.addToResourcePolicy(
Expand Down
Loading

0 comments on commit 57540d6

Please sign in to comment.