Skip to content

Commit eb14a27

Browse files
Update: [AEA-5930] - Add S3 Policies (#292)
## Summary - Add Policies for modifying buckets
1 parent fa8a7aa commit eb14a27

3 files changed

Lines changed: 66 additions & 4 deletions

File tree

packages/cdk/constructs/S3Bucket.ts

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,19 @@ import {
88
CfnBucket,
99
CfnBucketPolicy
1010
} from "aws-cdk-lib/aws-s3"
11-
import {Key} from "aws-cdk-lib/aws-kms"
11+
import {CfnKey, Key} from "aws-cdk-lib/aws-kms"
12+
import {
13+
AccountRootPrincipal,
14+
Effect,
15+
IPrincipal,
16+
PolicyDocument,
17+
PolicyStatement
18+
} from "aws-cdk-lib/aws-iam"
1219

1320
export interface S3BucketProps {
1421
readonly bucketName: string
1522
readonly versioned: boolean
23+
readonly deploymentRole: IPrincipal
1624
}
1725

1826
export class S3Bucket extends Construct {
@@ -40,6 +48,53 @@ export class S3Bucket extends Construct {
4048
objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED
4149
})
4250

51+
// Adding full deployment roles to this bucket
52+
const deploymentPolicy = new PolicyStatement({
53+
effect: Effect.ALLOW,
54+
principals: [props.deploymentRole],
55+
actions: [
56+
"s3:Abort*",
57+
"s3:GetBucket*",
58+
"s3:GetObject*",
59+
"s3:List*",
60+
"s3:PutObject",
61+
"s3:PutObjectLegalHold",
62+
"s3:PutObjectRetention",
63+
"s3:PutObjectTagging",
64+
"s3:PutObjectVersionTagging"
65+
],
66+
resources: [
67+
bucket.bucketArn,
68+
bucket.arnForObjects("*")
69+
]
70+
})
71+
72+
const accountRootPrincipal = new AccountRootPrincipal()
73+
const kmsPolicy = new PolicyDocument({
74+
statements: [
75+
new PolicyStatement({
76+
effect: Effect.ALLOW,
77+
principals: [accountRootPrincipal],
78+
actions: ["kms:*"],
79+
resources: ["*"]
80+
}),
81+
new PolicyStatement({
82+
effect: Effect.ALLOW,
83+
principals: [props.deploymentRole],
84+
actions: [
85+
"kms:Encrypt",
86+
"kms:GenerateDataKey*"
87+
],
88+
resources:["*"]
89+
})
90+
]
91+
})
92+
93+
bucket.addToResourcePolicy(deploymentPolicy)
94+
95+
const contentBucketKmsKey = (kmsKey.node.defaultChild as CfnKey)
96+
contentBucketKmsKey.keyPolicy = kmsPolicy.toJSON()
97+
4398
const cfnBucket = bucket.node.defaultChild as CfnBucket
4499
cfnBucket.cfnOptions.metadata = {
45100
...cfnBucket.cfnOptions.metadata,

packages/cdk/resources/Storage.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import {Construct} from "constructs"
22
import {S3Bucket} from "../constructs/S3Bucket"
3+
import {IPrincipal} from "aws-cdk-lib/aws-iam"
34

45
export interface StorageProps {
5-
readonly stackName: string
6+
readonly stackName: string,
7+
readonly deploymentRole: IPrincipal
68
}
79

810
export class Storage extends Construct {
@@ -14,7 +16,9 @@ export class Storage extends Construct {
1416
// Create S3 bucket for knowledge base documents with encryption
1517
this.kbDocsBucket = new S3Bucket(this, "DocsBucket", {
1618
bucketName: `${props.stackName}-Docs`,
17-
versioned: true
19+
versioned: true,
20+
deploymentRole: props.deploymentRole
1821
})
22+
1923
}
2024
}

packages/cdk/stacks/EpsAssistMeStack.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export class EpsAssistMeStack extends Stack {
3333

3434
// imports
3535
const mainSlackBotLambdaExecutionRoleArn = Fn.importValue("epsam:lambda:SlackBot:ExecutionRole:Arn")
36+
const deploymentRoleImport = Fn.importValue("ci-resources:CloudFormationDeployRole")
3637
// regression testing needs direct lambda invoke — bypasses slack webhooks entirely
3738
const regressionTestRoleArn = Fn.importValue("ci-resources:AssistMeRegressionTestRole")
3839

@@ -50,6 +51,7 @@ export class EpsAssistMeStack extends Stack {
5051
const slackSigningSecret: string = this.node.tryGetContext("slackSigningSecret")
5152

5253
const cdkExecRole = Role.fromRoleArn(this, "CdkExecRole", cdkExecRoleArn)
54+
const deploymentRole = Role.fromRoleArn(this, "deploymentRole", deploymentRoleImport)
5355

5456
if (!slackBotToken || !slackSigningSecret) {
5557
throw new Error("Missing required context variables. Please provide slackBotToken and slackSigningSecret")
@@ -78,7 +80,8 @@ export class EpsAssistMeStack extends Stack {
7880

7981
// Create Storage construct first as it has no dependencies
8082
const storage = new Storage(this, "Storage", {
81-
stackName: props.stackName
83+
stackName: props.stackName,
84+
deploymentRole: deploymentRole
8285
})
8386

8487
// Create Bedrock execution role without dependencies

0 commit comments

Comments
 (0)