Skip to content

Commit 12d979c

Browse files
committed
Extract storage resources from stack and update nag suppressions
1 parent d67b93b commit 12d979c

File tree

3 files changed

+90
-67
lines changed

3 files changed

+90
-67
lines changed

packages/cdk/nagSuppressions.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export const nagSuppressions = (stack: Stack) => {
9191
// Suppress S3 warnings on EpsAssistDocsBucket
9292
safeAddNagSuppression(
9393
stack,
94-
"/EpsAssistMeStack/EpsAssistDocsBucket/Resource",
94+
"/EpsAssistMeStack/Storage/EpsAssistDocsBucket/Resource",
9595
[
9696
{
9797
id: "AwsSolutions-S1",
@@ -135,7 +135,7 @@ export const nagSuppressions = (stack: Stack) => {
135135
// Suppress warnings on access logs bucket
136136
safeAddNagSuppression(
137137
stack,
138-
"/EpsAssistMeStack/EpsAssistAccessLogsBucket/Resource",
138+
"/EpsAssistMeStack/Storage/EpsAssistAccessLogsBucket/Resource",
139139
[
140140
{
141141
id: "AwsSolutions-S10",
@@ -159,7 +159,7 @@ export const nagSuppressions = (stack: Stack) => {
159159
// Suppress SSL warning on actual access log bucket policy resource
160160
safeAddNagSuppression(
161161
stack,
162-
"/EpsAssistMeStack/EpsAssistAccessLogsBucket/Policy/Resource",
162+
"/EpsAssistMeStack/Storage/EpsAssistAccessLogsBucket/Policy/Resource",
163163
[
164164
{
165165
id: "AwsSolutions-S10",
@@ -177,7 +177,7 @@ export const nagSuppressions = (stack: Stack) => {
177177
id: "AwsSolutions-IAM5",
178178
reason: "Bedrock Knowledge Base requires these permissions to access S3 documents and OpenSearch collection.",
179179
appliesTo: [
180-
"Resource::<EpsAssistDocsBucketD6886E55.Arn>/*",
180+
"Resource::<StorageEpsAssistDocsBucketD6886E55.Arn>/*",
181181
"Action::aoss:*",
182182
"Resource::*",
183183
"Resource::<OsCollection.Arn>/*",

packages/cdk/resources/Storage.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {Construct} from "constructs"
2+
import {RemovalPolicy} from "aws-cdk-lib"
3+
import {
4+
Bucket,
5+
BucketEncryption,
6+
BlockPublicAccess,
7+
ObjectOwnership
8+
} from "aws-cdk-lib/aws-s3"
9+
import {Key} from "aws-cdk-lib/aws-kms"
10+
import * as iam from "aws-cdk-lib/aws-iam"
11+
12+
export interface StorageProps {
13+
bedrockExecutionRole: iam.Role
14+
}
15+
16+
export class Storage extends Construct {
17+
public readonly kbDocsBucket: Bucket
18+
public readonly accessLogBucket: Bucket
19+
public readonly kbDocsKey: Key
20+
21+
constructor(scope: Construct, id: string, props: StorageProps) {
22+
super(scope, id)
23+
24+
// Define the S3 bucket for access logs
25+
this.accessLogBucket = new Bucket(this, "EpsAssistAccessLogsBucket", {
26+
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
27+
encryption: BucketEncryption.KMS,
28+
removalPolicy: RemovalPolicy.DESTROY,
29+
autoDeleteObjects: true,
30+
enforceSSL: true,
31+
versioned: false,
32+
objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED
33+
})
34+
35+
// Create a customer-managed KMS key
36+
this.kbDocsKey = new Key(this, "KbDocsKey", {
37+
enableKeyRotation: true,
38+
description: "KMS key for encrypting knowledge base documents"
39+
})
40+
41+
// Use the KMS key in your S3 bucket
42+
this.kbDocsBucket = new Bucket(this, "EpsAssistDocsBucket", {
43+
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
44+
encryption: BucketEncryption.KMS,
45+
encryptionKey: this.kbDocsKey,
46+
removalPolicy: RemovalPolicy.DESTROY,
47+
autoDeleteObjects: true,
48+
enforceSSL: true,
49+
versioned: true,
50+
objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
51+
serverAccessLogsBucket: this.accessLogBucket,
52+
serverAccessLogsPrefix: "s3-access-logs/"
53+
})
54+
55+
// Grant Bedrock permission to decrypt
56+
this.kbDocsKey.addToResourcePolicy(new iam.PolicyStatement({
57+
effect: iam.Effect.ALLOW,
58+
principals: [new iam.ArnPrincipal(props.bedrockExecutionRole.roleArn)],
59+
actions: ["kms:Decrypt", "kms:DescribeKey"],
60+
resources: ["*"]
61+
}))
62+
}
63+
}

packages/cdk/stacks/EpsAssistMeStack.ts

Lines changed: 23 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,8 @@ import {
22
App,
33
Stack,
44
StackProps,
5-
RemovalPolicy,
65
CfnOutput
76
} from "aws-cdk-lib"
8-
import {
9-
Bucket,
10-
BucketEncryption,
11-
BlockPublicAccess,
12-
ObjectOwnership
13-
} from "aws-cdk-lib/aws-s3"
14-
import {Key} from "aws-cdk-lib/aws-kms"
157
import {
168
CfnGuardrail,
179
CfnGuardrailVersion,
@@ -28,6 +20,7 @@ import * as secretsmanager from "aws-cdk-lib/aws-secretsmanager"
2820
import {nagSuppressions} from "../nagSuppressions"
2921
import {Apis} from "../resources/Apis"
3022
import {Functions} from "../resources/Functions"
23+
import {Storage} from "../resources/Storage"
3124

3225
const EMBEDDING_MODEL = "amazon.titan-embed-text-v2:0"
3326
const COLLECTION_NAME = "eps-assist-vector-db"
@@ -90,51 +83,6 @@ export class EpsAssistMeStack extends Stack {
9083
tier: ssm.ParameterTier.STANDARD
9184
})
9285

93-
// Define the S3 bucket for access logs
94-
const accessLogBucket = new Bucket(this, "EpsAssistAccessLogsBucket", {
95-
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
96-
encryption: BucketEncryption.KMS,
97-
removalPolicy: RemovalPolicy.DESTROY,
98-
autoDeleteObjects: true,
99-
enforceSSL: true,
100-
versioned: false,
101-
objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED
102-
})
103-
104-
// Create a customer-managed KMS key
105-
const kbDocsKey = new Key(this, "KbDocsKey", {
106-
enableKeyRotation: true,
107-
description: "KMS key for encrypting knowledge base documents"
108-
})
109-
110-
// Use the KMS key in your S3 bucket
111-
const kbDocsBucket = new Bucket(this, "EpsAssistDocsBucket", {
112-
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
113-
encryption: BucketEncryption.KMS,
114-
encryptionKey: kbDocsKey,
115-
removalPolicy: RemovalPolicy.DESTROY,
116-
autoDeleteObjects: true,
117-
enforceSSL: true,
118-
versioned: true,
119-
objectOwnership: ObjectOwnership.BUCKET_OWNER_ENFORCED,
120-
serverAccessLogsBucket: accessLogBucket,
121-
serverAccessLogsPrefix: "s3-access-logs/"
122-
})
123-
124-
// Create an IAM policy for S3 access
125-
const s3AccessListPolicy = new PolicyStatement({
126-
actions: ["s3:ListBucket"],
127-
resources: [kbDocsBucket.bucketArn]
128-
})
129-
s3AccessListPolicy.addCondition("StringEquals", {"aws:ResourceAccount": account})
130-
131-
// Create an IAM policy for S3 access
132-
const s3AccessGetPolicy = new PolicyStatement({
133-
actions: ["s3:GetObject", "s3:Delete*"],
134-
resources: [`${kbDocsBucket.bucketArn}/*`]
135-
})
136-
s3AccessGetPolicy.addCondition("StringEquals", {"aws:ResourceAccount": account})
137-
13886
// Create an IAM policy to invoke Bedrock models and access titan v1 embedding model
13987
const bedrockExecutionRolePolicy = new PolicyStatement()
14088
bedrockExecutionRolePolicy.addActions("bedrock:InvokeModel")
@@ -164,17 +112,29 @@ export class EpsAssistMeStack extends Stack {
164112
})
165113
bedrockExecutionRole.addToPolicy(bedrockExecutionRolePolicy)
166114
bedrockExecutionRole.addToPolicy(bedrockOSSPolicyForKnowledgeBase)
167-
bedrockExecutionRole.addToPolicy(s3AccessListPolicy)
168-
bedrockExecutionRole.addToPolicy(s3AccessGetPolicy)
169115
bedrockExecutionRole.addToPolicy(bedrockKBDeleteRolePolicy)
170116

171-
// Grant Bedrock permission to decrypt
172-
kbDocsKey.addToResourcePolicy(new iam.PolicyStatement({
173-
effect: iam.Effect.ALLOW,
174-
principals: [new iam.ArnPrincipal(bedrockExecutionRole.roleArn)],
175-
actions: ["kms:Decrypt", "kms:DescribeKey"],
176-
resources: ["*"]
177-
}))
117+
// Create Storage construct
118+
const storage = new Storage(this, "Storage", {
119+
bedrockExecutionRole
120+
})
121+
122+
// Create an IAM policy for S3 access
123+
const s3AccessListPolicy = new PolicyStatement({
124+
actions: ["s3:ListBucket"],
125+
resources: [storage.kbDocsBucket.bucketArn]
126+
})
127+
s3AccessListPolicy.addCondition("StringEquals", {"aws:ResourceAccount": account})
128+
129+
// Create an IAM policy for S3 access
130+
const s3AccessGetPolicy = new PolicyStatement({
131+
actions: ["s3:GetObject", "s3:Delete*"],
132+
resources: [`${storage.kbDocsBucket.bucketArn}/*`]
133+
})
134+
s3AccessGetPolicy.addCondition("StringEquals", {"aws:ResourceAccount": account})
135+
136+
bedrockExecutionRole.addToPolicy(s3AccessListPolicy)
137+
bedrockExecutionRole.addToPolicy(s3AccessGetPolicy)
178138

179139
// Create bedrock Guardrails for the slack bot
180140
const guardrail = new CfnGuardrail(this, "EpsGuardrail", {
@@ -400,7 +360,7 @@ export class EpsAssistMeStack extends Stack {
400360
dataSourceConfiguration: {
401361
type: "S3",
402362
s3Configuration: {
403-
bucketArn: kbDocsBucket.bucketArn
363+
bucketArn: storage.kbDocsBucket.bucketArn
404364
}
405365
}
406366
})

0 commit comments

Comments
 (0)