serverless-bedrock-agentcore-plugin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/LICENSE +21 -0
- package/README.md +476 -0
- package/package.json +96 -0
- package/src/compilers/browser.js +110 -0
- package/src/compilers/codeInterpreter.js +64 -0
- package/src/compilers/gateway.js +98 -0
- package/src/compilers/gatewayTarget.js +285 -0
- package/src/compilers/index.js +15 -0
- package/src/compilers/memory.js +168 -0
- package/src/compilers/runtime.js +234 -0
- package/src/compilers/runtimeEndpoint.js +37 -0
- package/src/compilers/workloadIdentity.js +36 -0
- package/src/docker/builder.js +236 -0
- package/src/iam/policies.js +591 -0
- package/src/index.js +1354 -0
- package/src/utils/index.js +9 -0
- package/src/utils/naming.js +79 -0
- package/src/utils/tags.js +56 -0
- package/src/validators/schema.js +250 -0
|
@@ -0,0 +1,591 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { getResourceName } = require('../utils/naming');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Generate IAM role for AgentCore Runtime
|
|
7
|
+
*
|
|
8
|
+
* @param {string} name - The agent name
|
|
9
|
+
* @param {Object} config - The runtime configuration
|
|
10
|
+
* @param {Object} context - The compilation context
|
|
11
|
+
* @returns {Object} CloudFormation IAM Role resource
|
|
12
|
+
*/
|
|
13
|
+
function generateRuntimeRole(name, config, context) {
|
|
14
|
+
const { serviceName, stage } = context;
|
|
15
|
+
const roleName = getResourceName(serviceName, `${name}-runtime-role`, stage);
|
|
16
|
+
|
|
17
|
+
const assumeRolePolicy = {
|
|
18
|
+
Version: '2012-10-17',
|
|
19
|
+
Statement: [
|
|
20
|
+
{
|
|
21
|
+
Effect: 'Allow',
|
|
22
|
+
Principal: {
|
|
23
|
+
Service: 'bedrock-agentcore.amazonaws.com',
|
|
24
|
+
},
|
|
25
|
+
Action: 'sts:AssumeRole',
|
|
26
|
+
Condition: {
|
|
27
|
+
StringEquals: {
|
|
28
|
+
'aws:SourceAccount': { Ref: 'AWS::AccountId' },
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Base permissions for runtime
|
|
36
|
+
const policies = [
|
|
37
|
+
{
|
|
38
|
+
PolicyName: `${roleName}-base-policy`,
|
|
39
|
+
PolicyDocument: {
|
|
40
|
+
Version: '2012-10-17',
|
|
41
|
+
Statement: [
|
|
42
|
+
// CloudWatch Logs permissions
|
|
43
|
+
{
|
|
44
|
+
Effect: 'Allow',
|
|
45
|
+
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
|
|
46
|
+
Resource: {
|
|
47
|
+
'Fn::Sub':
|
|
48
|
+
'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/bedrock-agentcore/*',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
// ECR permissions if using container image
|
|
52
|
+
...(config.artifact?.containerImage
|
|
53
|
+
? [
|
|
54
|
+
{
|
|
55
|
+
Effect: 'Allow',
|
|
56
|
+
Action: ['ecr:GetAuthorizationToken'],
|
|
57
|
+
Resource: '*',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
Effect: 'Allow',
|
|
61
|
+
Action: [
|
|
62
|
+
'ecr:BatchCheckLayerAvailability',
|
|
63
|
+
'ecr:GetDownloadUrlForLayer',
|
|
64
|
+
'ecr:BatchGetImage',
|
|
65
|
+
],
|
|
66
|
+
Resource: {
|
|
67
|
+
'Fn::Sub':
|
|
68
|
+
'arn:${AWS::Partition}:ecr:${AWS::Region}:${AWS::AccountId}:repository/*',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
]
|
|
72
|
+
: []),
|
|
73
|
+
// S3 permissions if using S3 artifact
|
|
74
|
+
...(config.artifact?.s3
|
|
75
|
+
? [
|
|
76
|
+
{
|
|
77
|
+
Effect: 'Allow',
|
|
78
|
+
Action: ['s3:GetObject', 's3:GetObjectVersion'],
|
|
79
|
+
Resource: {
|
|
80
|
+
'Fn::Sub': `arn:\${AWS::Partition}:s3:::${config.artifact.s3.bucket}/${config.artifact.s3.key}`,
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
]
|
|
84
|
+
: []),
|
|
85
|
+
// Bedrock model invocation permissions (all regions for cross-region inference)
|
|
86
|
+
{
|
|
87
|
+
Effect: 'Allow',
|
|
88
|
+
Action: ['bedrock:InvokeModel', 'bedrock:InvokeModelWithResponseStream'],
|
|
89
|
+
Resource: {
|
|
90
|
+
'Fn::Sub': 'arn:${AWS::Partition}:bedrock:*::foundation-model/*',
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
// Bedrock cross-region inference profile permissions
|
|
94
|
+
{
|
|
95
|
+
Effect: 'Allow',
|
|
96
|
+
Action: [
|
|
97
|
+
'bedrock:InvokeModel',
|
|
98
|
+
'bedrock:InvokeModelWithResponseStream',
|
|
99
|
+
'bedrock:GetInferenceProfile',
|
|
100
|
+
],
|
|
101
|
+
Resource: [
|
|
102
|
+
'arn:aws:bedrock:*:*:inference-profile/us.*',
|
|
103
|
+
'arn:aws:bedrock:*:*:inference-profile/eu.*',
|
|
104
|
+
'arn:aws:bedrock:*:*:inference-profile/global.*',
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
// Add VPC permissions if VPC mode
|
|
113
|
+
if (config.network?.networkMode === 'VPC') {
|
|
114
|
+
policies[0].PolicyDocument.Statement.push({
|
|
115
|
+
Effect: 'Allow',
|
|
116
|
+
Action: [
|
|
117
|
+
'ec2:CreateNetworkInterface',
|
|
118
|
+
'ec2:DescribeNetworkInterfaces',
|
|
119
|
+
'ec2:DeleteNetworkInterface',
|
|
120
|
+
'ec2:AssignPrivateIpAddresses',
|
|
121
|
+
'ec2:UnassignPrivateIpAddresses',
|
|
122
|
+
],
|
|
123
|
+
Resource: '*',
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
Type: 'AWS::IAM::Role',
|
|
129
|
+
Properties: {
|
|
130
|
+
RoleName: roleName,
|
|
131
|
+
AssumeRolePolicyDocument: assumeRolePolicy,
|
|
132
|
+
Policies: policies,
|
|
133
|
+
Tags: [
|
|
134
|
+
{ Key: 'serverless:service', Value: serviceName },
|
|
135
|
+
{ Key: 'serverless:stage', Value: stage },
|
|
136
|
+
{ Key: 'agentcore:resource', Value: name },
|
|
137
|
+
{ Key: 'agentcore:type', Value: 'runtime-role' },
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Generate IAM role for AgentCore Memory
|
|
145
|
+
*
|
|
146
|
+
* @param {string} name - The agent name
|
|
147
|
+
* @param {Object} config - The memory configuration
|
|
148
|
+
* @param {Object} context - The compilation context
|
|
149
|
+
* @returns {Object} CloudFormation IAM Role resource
|
|
150
|
+
*/
|
|
151
|
+
function generateMemoryRole(name, config, context) {
|
|
152
|
+
const { serviceName, stage } = context;
|
|
153
|
+
const roleName = getResourceName(serviceName, `${name}-memory-role`, stage);
|
|
154
|
+
|
|
155
|
+
const assumeRolePolicy = {
|
|
156
|
+
Version: '2012-10-17',
|
|
157
|
+
Statement: [
|
|
158
|
+
{
|
|
159
|
+
Effect: 'Allow',
|
|
160
|
+
Principal: {
|
|
161
|
+
Service: 'bedrock-agentcore.amazonaws.com',
|
|
162
|
+
},
|
|
163
|
+
Action: 'sts:AssumeRole',
|
|
164
|
+
Condition: {
|
|
165
|
+
StringEquals: {
|
|
166
|
+
'aws:SourceAccount': { Ref: 'AWS::AccountId' },
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const policies = [
|
|
174
|
+
{
|
|
175
|
+
PolicyName: `${roleName}-base-policy`,
|
|
176
|
+
PolicyDocument: {
|
|
177
|
+
Version: '2012-10-17',
|
|
178
|
+
Statement: [
|
|
179
|
+
// CloudWatch Logs permissions
|
|
180
|
+
{
|
|
181
|
+
Effect: 'Allow',
|
|
182
|
+
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
|
|
183
|
+
Resource: {
|
|
184
|
+
'Fn::Sub':
|
|
185
|
+
'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/bedrock-agentcore/*',
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
// Bedrock model invocation for memory strategies (all regions for cross-region inference)
|
|
189
|
+
{
|
|
190
|
+
Effect: 'Allow',
|
|
191
|
+
Action: ['bedrock:InvokeModel', 'bedrock:InvokeModelWithResponseStream'],
|
|
192
|
+
Resource: {
|
|
193
|
+
'Fn::Sub': 'arn:${AWS::Partition}:bedrock:*::foundation-model/*',
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
// Bedrock cross-region inference profile permissions
|
|
197
|
+
{
|
|
198
|
+
Effect: 'Allow',
|
|
199
|
+
Action: [
|
|
200
|
+
'bedrock:InvokeModel',
|
|
201
|
+
'bedrock:InvokeModelWithResponseStream',
|
|
202
|
+
'bedrock:GetInferenceProfile',
|
|
203
|
+
],
|
|
204
|
+
Resource: [
|
|
205
|
+
'arn:aws:bedrock:*:*:inference-profile/us.*',
|
|
206
|
+
'arn:aws:bedrock:*:*:inference-profile/eu.*',
|
|
207
|
+
'arn:aws:bedrock:*:*:inference-profile/global.*',
|
|
208
|
+
],
|
|
209
|
+
},
|
|
210
|
+
// KMS permissions if encryption key is specified
|
|
211
|
+
...(config.encryptionKeyArn
|
|
212
|
+
? [
|
|
213
|
+
{
|
|
214
|
+
Effect: 'Allow',
|
|
215
|
+
Action: ['kms:Decrypt', 'kms:Encrypt', 'kms:GenerateDataKey', 'kms:DescribeKey'],
|
|
216
|
+
Resource: config.encryptionKeyArn,
|
|
217
|
+
},
|
|
218
|
+
]
|
|
219
|
+
: []),
|
|
220
|
+
],
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
];
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
Type: 'AWS::IAM::Role',
|
|
227
|
+
Properties: {
|
|
228
|
+
RoleName: roleName,
|
|
229
|
+
AssumeRolePolicyDocument: assumeRolePolicy,
|
|
230
|
+
Policies: policies,
|
|
231
|
+
Tags: [
|
|
232
|
+
{ Key: 'serverless:service', Value: serviceName },
|
|
233
|
+
{ Key: 'serverless:stage', Value: stage },
|
|
234
|
+
{ Key: 'agentcore:resource', Value: name },
|
|
235
|
+
{ Key: 'agentcore:type', Value: 'memory-role' },
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Generate IAM role for AgentCore Gateway
|
|
243
|
+
*
|
|
244
|
+
* @param {string} name - The agent name
|
|
245
|
+
* @param {Object} config - The gateway configuration
|
|
246
|
+
* @param {Object} context - The compilation context
|
|
247
|
+
* @returns {Object} CloudFormation IAM Role resource
|
|
248
|
+
*/
|
|
249
|
+
function generateGatewayRole(name, config, context) {
|
|
250
|
+
const { serviceName, stage } = context;
|
|
251
|
+
const roleName = getResourceName(serviceName, `${name}-gateway-role`, stage);
|
|
252
|
+
|
|
253
|
+
const assumeRolePolicy = {
|
|
254
|
+
Version: '2012-10-17',
|
|
255
|
+
Statement: [
|
|
256
|
+
{
|
|
257
|
+
Effect: 'Allow',
|
|
258
|
+
Principal: {
|
|
259
|
+
Service: 'bedrock-agentcore.amazonaws.com',
|
|
260
|
+
},
|
|
261
|
+
Action: 'sts:AssumeRole',
|
|
262
|
+
Condition: {
|
|
263
|
+
StringEquals: {
|
|
264
|
+
'aws:SourceAccount': { Ref: 'AWS::AccountId' },
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
],
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// Build Lambda invocation permissions if there are Lambda targets
|
|
272
|
+
const lambdaTargets = (config.targets || []).filter(
|
|
273
|
+
(t) => t.type === 'lambda' || (!t.type && (t.functionArn || t.functionName))
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
const policies = [
|
|
277
|
+
{
|
|
278
|
+
PolicyName: `${roleName}-base-policy`,
|
|
279
|
+
PolicyDocument: {
|
|
280
|
+
Version: '2012-10-17',
|
|
281
|
+
Statement: [
|
|
282
|
+
// CloudWatch Logs permissions
|
|
283
|
+
{
|
|
284
|
+
Effect: 'Allow',
|
|
285
|
+
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
|
|
286
|
+
Resource: {
|
|
287
|
+
'Fn::Sub':
|
|
288
|
+
'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/bedrock-agentcore/*',
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
// Lambda invocation permissions for Lambda targets
|
|
292
|
+
...(lambdaTargets.length > 0
|
|
293
|
+
? [
|
|
294
|
+
{
|
|
295
|
+
Effect: 'Allow',
|
|
296
|
+
Action: ['lambda:InvokeFunction'],
|
|
297
|
+
Resource: lambdaTargets.map((t) => {
|
|
298
|
+
if (t.functionArn) {
|
|
299
|
+
return t.functionArn;
|
|
300
|
+
}
|
|
301
|
+
// Reference the function from the stack
|
|
302
|
+
const functionLogicalId =
|
|
303
|
+
t.functionName
|
|
304
|
+
.split(/[-_]/)
|
|
305
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase())
|
|
306
|
+
.join('') + 'LambdaFunction';
|
|
307
|
+
|
|
308
|
+
return { 'Fn::GetAtt': [functionLogicalId, 'Arn'] };
|
|
309
|
+
}),
|
|
310
|
+
},
|
|
311
|
+
]
|
|
312
|
+
: []),
|
|
313
|
+
// S3 permissions for OpenAPI/Smithy specs
|
|
314
|
+
...getS3PermissionsForTargets(config.targets || []),
|
|
315
|
+
// Secrets Manager permissions for OAuth/API Key credentials
|
|
316
|
+
...getSecretsManagerPermissions(config.targets || []),
|
|
317
|
+
// KMS permissions if encryption key is specified
|
|
318
|
+
...(config.kmsKeyArn
|
|
319
|
+
? [
|
|
320
|
+
{
|
|
321
|
+
Effect: 'Allow',
|
|
322
|
+
Action: ['kms:Decrypt', 'kms:Encrypt', 'kms:GenerateDataKey', 'kms:DescribeKey'],
|
|
323
|
+
Resource: config.kmsKeyArn,
|
|
324
|
+
},
|
|
325
|
+
]
|
|
326
|
+
: []),
|
|
327
|
+
],
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
];
|
|
331
|
+
|
|
332
|
+
return {
|
|
333
|
+
Type: 'AWS::IAM::Role',
|
|
334
|
+
Properties: {
|
|
335
|
+
RoleName: roleName,
|
|
336
|
+
AssumeRolePolicyDocument: assumeRolePolicy,
|
|
337
|
+
Policies: policies,
|
|
338
|
+
Tags: [
|
|
339
|
+
{ Key: 'serverless:service', Value: serviceName },
|
|
340
|
+
{ Key: 'serverless:stage', Value: stage },
|
|
341
|
+
{ Key: 'agentcore:resource', Value: name },
|
|
342
|
+
{ Key: 'agentcore:type', Value: 'gateway-role' },
|
|
343
|
+
],
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Get S3 permissions for targets with S3 configurations
|
|
350
|
+
*
|
|
351
|
+
* @param {Array} targets - Array of target configurations
|
|
352
|
+
* @returns {Array} Array of IAM policy statements
|
|
353
|
+
*/
|
|
354
|
+
function getS3PermissionsForTargets(targets) {
|
|
355
|
+
const s3Targets = targets.filter((t) => t.s3);
|
|
356
|
+
|
|
357
|
+
if (s3Targets.length === 0) {
|
|
358
|
+
return [];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return [
|
|
362
|
+
{
|
|
363
|
+
Effect: 'Allow',
|
|
364
|
+
Action: ['s3:GetObject', 's3:GetObjectVersion'],
|
|
365
|
+
Resource: s3Targets.map((t) => ({
|
|
366
|
+
'Fn::Sub': `arn:\${AWS::Partition}:s3:::${t.s3.bucket}/${t.s3.key}`,
|
|
367
|
+
})),
|
|
368
|
+
},
|
|
369
|
+
];
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Get Secrets Manager permissions for OAuth/API Key credentials
|
|
374
|
+
*
|
|
375
|
+
* @param {Array} targets - Array of target configurations
|
|
376
|
+
* @returns {Array} Array of IAM policy statements
|
|
377
|
+
*/
|
|
378
|
+
function getSecretsManagerPermissions(targets) {
|
|
379
|
+
const secretArns = targets
|
|
380
|
+
.filter((t) => t.credentialProvider)
|
|
381
|
+
.map((t) => {
|
|
382
|
+
const cp = t.credentialProvider;
|
|
383
|
+
if (cp.oauthConfig?.secretArn) {
|
|
384
|
+
return cp.oauthConfig.secretArn;
|
|
385
|
+
}
|
|
386
|
+
if (cp.apiKeyConfig?.secretArn) {
|
|
387
|
+
return cp.apiKeyConfig.secretArn;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
return null;
|
|
391
|
+
})
|
|
392
|
+
.filter(Boolean);
|
|
393
|
+
|
|
394
|
+
if (secretArns.length === 0) {
|
|
395
|
+
return [];
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return [
|
|
399
|
+
{
|
|
400
|
+
Effect: 'Allow',
|
|
401
|
+
Action: ['secretsmanager:GetSecretValue'],
|
|
402
|
+
Resource: secretArns,
|
|
403
|
+
},
|
|
404
|
+
];
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Generate IAM role for AgentCore BrowserCustom
|
|
409
|
+
*
|
|
410
|
+
* @param {string} name - The browser name
|
|
411
|
+
* @param {Object} config - The browser configuration
|
|
412
|
+
* @param {Object} context - The compilation context
|
|
413
|
+
* @returns {Object} CloudFormation IAM Role resource
|
|
414
|
+
*/
|
|
415
|
+
function generateBrowserRole(name, config, context) {
|
|
416
|
+
const { serviceName, stage } = context;
|
|
417
|
+
const roleName = getResourceName(serviceName, `${name}-browser-role`, stage);
|
|
418
|
+
|
|
419
|
+
const assumeRolePolicy = {
|
|
420
|
+
Version: '2012-10-17',
|
|
421
|
+
Statement: [
|
|
422
|
+
{
|
|
423
|
+
Effect: 'Allow',
|
|
424
|
+
Principal: {
|
|
425
|
+
Service: 'bedrock-agentcore.amazonaws.com',
|
|
426
|
+
},
|
|
427
|
+
Action: 'sts:AssumeRole',
|
|
428
|
+
Condition: {
|
|
429
|
+
StringEquals: {
|
|
430
|
+
'aws:SourceAccount': { Ref: 'AWS::AccountId' },
|
|
431
|
+
},
|
|
432
|
+
},
|
|
433
|
+
},
|
|
434
|
+
],
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
const policies = [
|
|
438
|
+
{
|
|
439
|
+
PolicyName: `${roleName}-policy`,
|
|
440
|
+
PolicyDocument: {
|
|
441
|
+
Version: '2012-10-17',
|
|
442
|
+
Statement: [
|
|
443
|
+
// CloudWatch Logs permissions
|
|
444
|
+
{
|
|
445
|
+
Effect: 'Allow',
|
|
446
|
+
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
|
|
447
|
+
Resource: {
|
|
448
|
+
'Fn::Sub':
|
|
449
|
+
'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/bedrock-agentcore/*',
|
|
450
|
+
},
|
|
451
|
+
},
|
|
452
|
+
// S3 permissions for recordings (if enabled)
|
|
453
|
+
...(config.recording?.s3Location
|
|
454
|
+
? [
|
|
455
|
+
{
|
|
456
|
+
Effect: 'Allow',
|
|
457
|
+
Action: ['s3:PutObject', 's3:GetObject'],
|
|
458
|
+
Resource: {
|
|
459
|
+
'Fn::Sub': `arn:\${AWS::Partition}:s3:::${config.recording.s3Location.bucket}/${config.recording.s3Location.prefix || ''}*`,
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
]
|
|
463
|
+
: []),
|
|
464
|
+
// VPC permissions (if VPC mode)
|
|
465
|
+
...(config.network?.networkMode === 'VPC'
|
|
466
|
+
? [
|
|
467
|
+
{
|
|
468
|
+
Effect: 'Allow',
|
|
469
|
+
Action: [
|
|
470
|
+
'ec2:CreateNetworkInterface',
|
|
471
|
+
'ec2:DescribeNetworkInterfaces',
|
|
472
|
+
'ec2:DeleteNetworkInterface',
|
|
473
|
+
'ec2:AssignPrivateIpAddresses',
|
|
474
|
+
'ec2:UnassignPrivateIpAddresses',
|
|
475
|
+
],
|
|
476
|
+
Resource: '*',
|
|
477
|
+
},
|
|
478
|
+
]
|
|
479
|
+
: []),
|
|
480
|
+
],
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
];
|
|
484
|
+
|
|
485
|
+
return {
|
|
486
|
+
Type: 'AWS::IAM::Role',
|
|
487
|
+
Properties: {
|
|
488
|
+
RoleName: roleName,
|
|
489
|
+
AssumeRolePolicyDocument: assumeRolePolicy,
|
|
490
|
+
Policies: policies,
|
|
491
|
+
Tags: [
|
|
492
|
+
{ Key: 'serverless:service', Value: serviceName },
|
|
493
|
+
{ Key: 'serverless:stage', Value: stage },
|
|
494
|
+
{ Key: 'agentcore:resource', Value: name },
|
|
495
|
+
{ Key: 'agentcore:type', Value: 'browser-role' },
|
|
496
|
+
],
|
|
497
|
+
},
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Generate IAM role for AgentCore CodeInterpreterCustom
|
|
503
|
+
*
|
|
504
|
+
* @param {string} name - The code interpreter name
|
|
505
|
+
* @param {Object} config - The code interpreter configuration
|
|
506
|
+
* @param {Object} context - The compilation context
|
|
507
|
+
* @returns {Object} CloudFormation IAM Role resource
|
|
508
|
+
*/
|
|
509
|
+
function generateCodeInterpreterRole(name, config, context) {
|
|
510
|
+
const { serviceName, stage } = context;
|
|
511
|
+
const roleName = getResourceName(serviceName, `${name}-ci-role`, stage);
|
|
512
|
+
|
|
513
|
+
const assumeRolePolicy = {
|
|
514
|
+
Version: '2012-10-17',
|
|
515
|
+
Statement: [
|
|
516
|
+
{
|
|
517
|
+
Effect: 'Allow',
|
|
518
|
+
Principal: {
|
|
519
|
+
Service: 'bedrock-agentcore.amazonaws.com',
|
|
520
|
+
},
|
|
521
|
+
Action: 'sts:AssumeRole',
|
|
522
|
+
Condition: {
|
|
523
|
+
StringEquals: {
|
|
524
|
+
'aws:SourceAccount': { Ref: 'AWS::AccountId' },
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
],
|
|
529
|
+
};
|
|
530
|
+
|
|
531
|
+
const policies = [
|
|
532
|
+
{
|
|
533
|
+
PolicyName: `${roleName}-policy`,
|
|
534
|
+
PolicyDocument: {
|
|
535
|
+
Version: '2012-10-17',
|
|
536
|
+
Statement: [
|
|
537
|
+
// CloudWatch Logs permissions
|
|
538
|
+
{
|
|
539
|
+
Effect: 'Allow',
|
|
540
|
+
Action: ['logs:CreateLogGroup', 'logs:CreateLogStream', 'logs:PutLogEvents'],
|
|
541
|
+
Resource: {
|
|
542
|
+
'Fn::Sub':
|
|
543
|
+
'arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/bedrock-agentcore/*',
|
|
544
|
+
},
|
|
545
|
+
},
|
|
546
|
+
// VPC permissions (if VPC mode)
|
|
547
|
+
...(config.network?.networkMode === 'VPC'
|
|
548
|
+
? [
|
|
549
|
+
{
|
|
550
|
+
Effect: 'Allow',
|
|
551
|
+
Action: [
|
|
552
|
+
'ec2:CreateNetworkInterface',
|
|
553
|
+
'ec2:DescribeNetworkInterfaces',
|
|
554
|
+
'ec2:DeleteNetworkInterface',
|
|
555
|
+
'ec2:AssignPrivateIpAddresses',
|
|
556
|
+
'ec2:UnassignPrivateIpAddresses',
|
|
557
|
+
],
|
|
558
|
+
Resource: '*',
|
|
559
|
+
},
|
|
560
|
+
]
|
|
561
|
+
: []),
|
|
562
|
+
],
|
|
563
|
+
},
|
|
564
|
+
},
|
|
565
|
+
];
|
|
566
|
+
|
|
567
|
+
return {
|
|
568
|
+
Type: 'AWS::IAM::Role',
|
|
569
|
+
Properties: {
|
|
570
|
+
RoleName: roleName,
|
|
571
|
+
AssumeRolePolicyDocument: assumeRolePolicy,
|
|
572
|
+
Policies: policies,
|
|
573
|
+
Tags: [
|
|
574
|
+
{ Key: 'serverless:service', Value: serviceName },
|
|
575
|
+
{ Key: 'serverless:stage', Value: stage },
|
|
576
|
+
{ Key: 'agentcore:resource', Value: name },
|
|
577
|
+
{ Key: 'agentcore:type', Value: 'codeinterpreter-role' },
|
|
578
|
+
],
|
|
579
|
+
},
|
|
580
|
+
};
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
module.exports = {
|
|
584
|
+
generateRuntimeRole,
|
|
585
|
+
generateMemoryRole,
|
|
586
|
+
generateGatewayRole,
|
|
587
|
+
generateBrowserRole,
|
|
588
|
+
generateCodeInterpreterRole,
|
|
589
|
+
getS3PermissionsForTargets,
|
|
590
|
+
getSecretsManagerPermissions,
|
|
591
|
+
};
|