@aws/nx-plugin 0.60.2 → 0.61.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.
@@ -20,44 +20,48 @@ CMD ["python", "bin/opentelemetry-instrument", "python", "-m", "proj_test_projec
20
20
 
21
21
  exports[`py#strands-agent generator > should match snapshot for BedrockAgentCoreRuntime generated constructs files > agent-construct.ts 1`] = `
22
22
  "import { Lazy, Names } from 'aws-cdk-lib';
23
- import { DockerImageAsset, Platform } from 'aws-cdk-lib/aws-ecr-assets';
23
+ import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
24
24
  import { Construct } from 'constructs';
25
25
  import { execSync } from 'child_process';
26
26
  import * as path from 'path';
27
27
  import * as url from 'url';
28
28
  import {
29
- AgentCoreRuntime,
30
- AgentCoreRuntimeProps,
31
- } from '../../../core/agent-core/runtime.js';
29
+ AgentRuntimeArtifact,
30
+ ProtocolType,
31
+ Runtime,
32
+ RuntimeProps,
33
+ } from '@aws-cdk/aws-bedrock-agentcore-alpha';
32
34
 
33
35
  export type SnapshotBedrockAgentProps = Omit<
34
- AgentCoreRuntimeProps,
35
- 'runtimeName' | 'serverProtocol' | 'containerUri'
36
+ RuntimeProps,
37
+ 'runtimeName' | 'protocolConfiguration' | 'agentRuntimeArtifact'
36
38
  >;
37
39
 
38
40
  export class SnapshotBedrockAgent extends Construct {
39
- public readonly dockerImage: DockerImageAsset;
40
- public readonly agentCoreRuntime: AgentCoreRuntime;
41
+ public readonly dockerImage: AgentRuntimeArtifact;
42
+ public readonly agentCoreRuntime: Runtime;
41
43
 
42
44
  constructor(scope: Construct, id: string, props?: SnapshotBedrockAgentProps) {
43
45
  super(scope, id);
44
46
 
45
- this.dockerImage = new DockerImageAsset(this, 'DockerImage', {
46
- platform: Platform.LINUX_ARM64,
47
- directory: path.dirname(url.fileURLToPath(new URL(import.meta.url))),
48
- extraHash: execSync(
49
- \`docker inspect proj-snapshot-bedrock-agent:latest --format '{{.Id}}'\`,
50
- { encoding: 'utf-8' },
51
- ).trim(),
52
- });
47
+ this.dockerImage = AgentRuntimeArtifact.fromAsset(
48
+ path.dirname(url.fileURLToPath(new URL(import.meta.url))),
49
+ {
50
+ platform: Platform.LINUX_ARM64,
51
+ extraHash: execSync(
52
+ \`docker inspect proj-snapshot-bedrock-agent:latest --format '{{.Id}}'\`,
53
+ { encoding: 'utf-8' },
54
+ ).trim(),
55
+ },
56
+ );
53
57
 
54
- this.agentCoreRuntime = new AgentCoreRuntime(this, 'SnapshotBedrockAgent', {
58
+ this.agentCoreRuntime = new Runtime(this, 'SnapshotBedrockAgent', {
55
59
  runtimeName: Lazy.string({
56
60
  produce: () =>
57
61
  Names.uniqueResourceName(this.agentCoreRuntime, { maxLength: 40 }),
58
62
  }),
59
- serverProtocol: 'HTTP',
60
- containerUri: this.dockerImage.imageUri,
63
+ protocolConfiguration: ProtocolType.HTTP,
64
+ agentRuntimeArtifact: this.dockerImage,
61
65
  ...props,
62
66
  });
63
67
  }
@@ -65,169 +69,6 @@ export class SnapshotBedrockAgent extends Construct {
65
69
  "
66
70
  `;
67
71
 
68
- exports[`py#strands-agent generator > should match snapshot for BedrockAgentCoreRuntime generated constructs files > agent-core-runtime.ts 1`] = `
69
- "import {
70
- Role,
71
- ServicePrincipal,
72
- PolicyStatement,
73
- Effect,
74
- PolicyDocument,
75
- IGrantable,
76
- Grant,
77
- IPrincipal,
78
- } from 'aws-cdk-lib/aws-iam';
79
- import { Construct } from 'constructs';
80
- import { Stack } from 'aws-cdk-lib';
81
- import { CfnRuntime } from 'aws-cdk-lib/aws-bedrockagentcore';
82
-
83
- /**
84
- * Options for the AgentCoreRuntime construct
85
- */
86
- export interface AgentCoreRuntimeProps {
87
- runtimeName: string;
88
- description?: string;
89
- containerUri: string;
90
- serverProtocol: 'MCP' | 'HTTP';
91
- environment?: Record<string, string>;
92
- authorizerConfiguration?: CfnRuntime.AuthorizerConfigurationProperty;
93
- }
94
-
95
- /**
96
- * A construct for creating a Bedrock AgentCore Runtime
97
- */
98
- export class AgentCoreRuntime extends Construct implements IGrantable {
99
- public readonly role: Role;
100
- public readonly arn: string;
101
-
102
- public readonly grantPrincipal: IPrincipal;
103
-
104
- constructor(scope: Construct, id: string, props: AgentCoreRuntimeProps) {
105
- super(scope, id);
106
-
107
- const region = Stack.of(this).region;
108
- const accountId = Stack.of(this).account;
109
-
110
- this.role = new Role(this, 'AgentCoreRole', {
111
- assumedBy: new ServicePrincipal('bedrock-agentcore.amazonaws.com'),
112
- inlinePolicies: {
113
- AgentCorePolicy: new PolicyDocument({
114
- statements: [
115
- new PolicyStatement({
116
- sid: 'ECRImageAccess',
117
- effect: Effect.ALLOW,
118
- actions: ['ecr:BatchGetImage', 'ecr:GetDownloadUrlForLayer'],
119
- resources: [\`arn:aws:ecr:\${region}:\${accountId}:repository/*\`],
120
- }),
121
- new PolicyStatement({
122
- effect: Effect.ALLOW,
123
- actions: ['logs:DescribeLogStreams', 'logs:CreateLogGroup'],
124
- resources: [
125
- \`arn:aws:logs:\${region}:\${accountId}:log-group:/aws/bedrock-agentcore/runtimes/*\`,
126
- ],
127
- }),
128
- new PolicyStatement({
129
- effect: Effect.ALLOW,
130
- actions: ['logs:DescribeLogGroups'],
131
- resources: [\`arn:aws:logs:\${region}:\${accountId}:log-group:*\`],
132
- }),
133
- new PolicyStatement({
134
- effect: Effect.ALLOW,
135
- actions: ['logs:CreateLogStream', 'logs:PutLogEvents'],
136
- resources: [
137
- \`arn:aws:logs:\${region}:\${accountId}:log-group:/aws/bedrock-agentcore/runtimes/*:log-stream:*\`,
138
- ],
139
- }),
140
- new PolicyStatement({
141
- sid: 'ECRTokenAccess',
142
- effect: Effect.ALLOW,
143
- actions: ['ecr:GetAuthorizationToken'],
144
- resources: ['*'],
145
- }),
146
- new PolicyStatement({
147
- effect: Effect.ALLOW,
148
- actions: [
149
- 'xray:PutTraceSegments',
150
- 'xray:PutTelemetryRecords',
151
- 'xray:GetSamplingRules',
152
- 'xray:GetSamplingTargets',
153
- ],
154
- resources: ['*'],
155
- }),
156
- new PolicyStatement({
157
- effect: Effect.ALLOW,
158
- actions: ['cloudwatch:PutMetricData'],
159
- resources: ['*'],
160
- conditions: {
161
- StringEquals: {
162
- 'cloudwatch:namespace': 'bedrock-agentcore',
163
- },
164
- },
165
- }),
166
- new PolicyStatement({
167
- sid: 'GetAgentAccessToken',
168
- effect: Effect.ALLOW,
169
- actions: [
170
- 'bedrock-agentcore:GetWorkloadAccessToken',
171
- 'bedrock-agentcore:GetWorkloadAccessTokenForJWT',
172
- 'bedrock-agentcore:GetWorkloadAccessTokenForUserId',
173
- ],
174
- resources: [
175
- \`arn:aws:bedrock-agentcore:\${region}:\${accountId}:workload-identity-directory/default\`,
176
- \`arn:aws:bedrock-agentcore:\${region}:\${accountId}:workload-identity-directory/default/workload-identity/*\`,
177
- ],
178
- }),
179
- new PolicyStatement({
180
- sid: 'BedrockModelInvocation',
181
- effect: Effect.ALLOW,
182
- actions: [
183
- 'bedrock:InvokeModel',
184
- 'bedrock:InvokeModelWithResponseStream',
185
- ],
186
- resources: [
187
- 'arn:aws:bedrock:*::foundation-model/*',
188
- \`arn:aws:bedrock:\${region}:\${accountId}:*\`,
189
- ],
190
- }),
191
- ],
192
- }),
193
- },
194
- });
195
- this.grantPrincipal = this.role.grantPrincipal;
196
-
197
- const agentRuntime = new CfnRuntime(this, 'MCPServerRuntime', {
198
- agentRuntimeName: props.runtimeName,
199
- agentRuntimeArtifact: {
200
- containerConfiguration: {
201
- containerUri: props.containerUri,
202
- },
203
- },
204
- description: props.description,
205
- environmentVariables: props.environment,
206
- networkConfiguration: {
207
- networkMode: 'PUBLIC',
208
- },
209
- protocolConfiguration: props.serverProtocol,
210
- roleArn: this.role.roleArn,
211
- authorizerConfiguration: props.authorizerConfiguration,
212
- });
213
-
214
- this.arn = agentRuntime.attrAgentRuntimeArn;
215
- }
216
-
217
- /**
218
- * Grant permissions to invoke the agent runtime (if using IAM auth - not required for JWT auth)
219
- */
220
- public grantInvoke = (grantee: IGrantable) => {
221
- Grant.addToPrincipal({
222
- grantee,
223
- actions: ['bedrock-agentcore:InvokeAgentRuntime'],
224
- resourceArns: [this.arn, \`\${this.arn}/*\`],
225
- });
226
- };
227
- }
228
- "
229
- `;
230
-
231
72
  exports[`py#strands-agent generator > should match snapshot for BedrockAgentCoreRuntime generated constructs files > agents-index.ts 1`] = `
232
73
  "export * from './snapshot-bedrock-agent/snapshot-bedrock-agent.js';
233
74
  "
@@ -273,9 +114,11 @@ module "agent_core_runtime" {
273
114
  agent_runtime_name = "TerraformSnapshotAgent"
274
115
  docker_image_tag = "proj-terraform-snapshot-agent:latest"
275
116
  server_protocol = "HTTP"
276
- # customJWTAuthorizer = {
277
- # discoveryUrl = "https://xxx/.well-known/openid-configuration",
278
- # allowedClients = [ "xxx" ]
117
+ # authorizer_configuration = {
118
+ # custom_jwt_authorizer = {
119
+ # discovery_url = "https://xxx/.well-known/openid-configuration"
120
+ # allowed_clients = [ "xxx" ]
121
+ # }
279
122
  # }
280
123
 
281
124
  env = var.env
@@ -302,16 +145,12 @@ exports[`py#strands-agent generator > should match snapshot for Terraform genera
302
145
  required_providers {
303
146
  aws = {
304
147
  source = "hashicorp/aws"
305
- version = ">= 6.0"
148
+ version = ">= 6.23"
306
149
  }
307
150
  null = {
308
151
  source = "hashicorp/null"
309
152
  version = ">= 3.0"
310
153
  }
311
- local = {
312
- source = "hashicorp/local"
313
- version = ">= 2.0"
314
- }
315
154
  random = {
316
155
  source = "hashicorp/random"
317
156
  version = ">= 3.0"
@@ -330,20 +169,23 @@ variable "agent_runtime_name" {
330
169
  }
331
170
 
332
171
  variable "server_protocol" {
333
- description = "Whether this is an Agent (HTTP) or MCP Server (MCP)"
172
+ description = "Server protocol for the agent runtime (HTTP, MCP, or A2A)"
334
173
  type = string
174
+ default = "HTTP"
335
175
  validation {
336
- condition = contains(["MCP", "HTTP"], var.server_protocol)
337
- error_message = "Protocol type must be either 'MCP' or 'HTTP'."
176
+ condition = contains(["MCP", "HTTP", "A2A"], var.server_protocol)
177
+ error_message = "Protocol type must be either 'MCP', 'HTTP', or 'A2A'."
338
178
  }
339
179
  }
340
180
 
341
- variable "customJWTAuthorizer" {
342
- description = "Custom JWTAuthorizer Configuration"
181
+ variable "authorizer_configuration" {
182
+ description = "Authorization configuration for authenticating incoming requests"
343
183
  type = object({
344
- discoveryUrl = optional(string)
345
- allowedAudience = optional(list(string))
346
- allowedClients = optional(list(string))
184
+ custom_jwt_authorizer = optional(object({
185
+ discovery_url = string
186
+ allowed_audience = optional(list(string))
187
+ allowed_clients = optional(list(string))
188
+ }))
347
189
  })
348
190
  default = null
349
191
  }
@@ -381,7 +223,7 @@ data "aws_region" "current" {}
381
223
 
382
224
  locals {
383
225
  aws_account_id = data.aws_caller_identity.current.account_id
384
- aws_region = data.aws_region.current.name
226
+ aws_region = data.aws_region.current.id
385
227
  }
386
228
 
387
229
  # Random ID for bucket suffix to ensure uniqueness
@@ -392,7 +234,7 @@ resource "random_id" "unique_suffix" {
392
234
  # ECR Repository
393
235
  resource "aws_ecr_repository" "agent_core_repository" {
394
236
  #checkov:skip=CKV_AWS_136:AES256 encryption is sufficient for ECR repositories
395
- name = "\${lower(var.agent_runtime_name)}_repository_\${random_id.unique_suffix.hex}"
237
+ name = "\${lower(var.agent_runtime_name)}_repository_\${random_id.unique_suffix.hex}"
396
238
 
397
239
  #checkov:skip=CKV_AWS_51:Image tag is reused for latest deployments
398
240
  image_tag_mutability = "MUTABLE"
@@ -461,7 +303,7 @@ resource "aws_iam_role" "agent_core_runtime_role" {
461
303
  tags = var.tags
462
304
  }
463
305
 
464
- # IAM Policy for Query Agent with restricted Athena permissions
306
+ # IAM Policy for Agent Core Runtime
465
307
  resource "aws_iam_policy" "agent_core_runtime_policy" {
466
308
  name = "\${var.agent_runtime_name}-QueryAgentPolicy-\${random_id.unique_suffix.hex}"
467
309
  description = "Restricted policy for Agent"
@@ -477,7 +319,7 @@ resource "aws_iam_policy" "agent_core_runtime_policy" {
477
319
  "ecr:GetDownloadUrlForLayer"
478
320
  ]
479
321
  Resource = [
480
- "arn:aws:ecr:\${local.aws_region}:\${local.aws_account_id}:repository/*"
322
+ aws_ecr_repository.agent_core_repository.arn
481
323
  ]
482
324
  },
483
325
  {
@@ -551,17 +393,6 @@ resource "aws_iam_policy" "agent_core_runtime_policy" {
551
393
  "arn:aws:bedrock-agentcore:\${local.aws_region}:\${local.aws_account_id}:workload-identity-directory/default",
552
394
  "arn:aws:bedrock-agentcore:\${local.aws_region}:\${local.aws_account_id}:workload-identity-directory/default/workload-identity/*"
553
395
  ]
554
- },
555
- { "Sid" : "BedrockModelInvocation",
556
- "Effect" : "Allow",
557
- "Action" : [
558
- "bedrock:InvokeModel",
559
- "bedrock:InvokeModelWithResponseStream"
560
- ],
561
- "Resource" : [
562
- "arn:aws:bedrock:*::foundation-model/*",
563
- "arn:aws:bedrock:\${local.aws_region}:\${local.aws_account_id}:*"
564
- ]
565
396
  }
566
397
  ], var.additional_iam_policy_statements)
567
398
  })
@@ -575,6 +406,7 @@ resource "aws_iam_role_policy_attachment" "agent_core_policy" {
575
406
  policy_arn = aws_iam_policy.agent_core_runtime_policy.arn
576
407
  }
577
408
 
409
+ # Data source to get Docker image digest
578
410
  data "external" "docker_digest" {
579
411
  program = ["sh", "-c", "echo '{\\"digest\\":\\"'$(docker inspect \${var.docker_image_tag} --format '{{.Id}}')'\\"}' "]
580
412
  }
@@ -582,9 +414,7 @@ data "external" "docker_digest" {
582
414
  # Null resource for Docker publish
583
415
  resource "null_resource" "docker_publish" {
584
416
  triggers = {
585
- # Trigger rebuild when the image changes
586
417
  docker_digest = data.external.docker_digest.result.digest
587
-
588
418
  repository_url = aws_ecr_repository.agent_core_repository.repository_url
589
419
  docker_image_tag = var.docker_image_tag
590
420
  }
@@ -605,206 +435,45 @@ resource "null_resource" "docker_publish" {
605
435
  depends_on = [aws_ecr_repository_policy.agent_core_ecr_policy]
606
436
  }
607
437
 
608
- # Null resource for agent core deployment with proper lifecycle management
609
- resource "null_resource" "agent_core_runtime_deployment" {
610
- triggers = {
611
- container_uri = "\${aws_ecr_repository.agent_core_repository.repository_url}:latest"
612
- role_arn = aws_iam_role.agent_core_runtime_role.arn
613
- config_hash = md5(join("", [jsonencode(var.customJWTAuthorizer), var.server_protocol]))
614
- env_hash = md5(jsonencode(var.env))
615
- }
438
+ # Bedrock AgentCore Agent Runtime
439
+ resource "aws_bedrockagentcore_agent_runtime" "agent_runtime" {
440
+ agent_runtime_name = "\${var.agent_runtime_name}_\${random_id.unique_suffix.hex}"
441
+ description = "Agent Runtime for \${var.agent_runtime_name}"
442
+ role_arn = aws_iam_role.agent_core_runtime_role.arn
616
443
 
617
- provisioner "local-exec" {
618
- command = <<-EOT
619
- uv run --with boto3 python -c '
620
- import boto3
621
- import json
622
- import sys
623
-
624
- # Create the client
625
- client = boto3.client("bedrock-agentcore-control", region_name="\${local.aws_region}")
626
-
627
- # Environment variables for QueryAgentConfig
628
- environment_variables = json.loads("""\${jsonencode(var.env)}""")
629
- agent_name = "\${var.agent_runtime_name}_\${random_id.unique_suffix.hex}"
630
- authorization_config = json.loads("""{"customJWTAuthorizer": \${jsonencode(var.customJWTAuthorizer != null ? {
631
- for k, v in var.customJWTAuthorizer : k => v if v != null
632
- } : {})}}""")
633
-
634
- try:
635
- # First, check if an agent runtime with this name already exists
636
- existing_agent_runtime_id = None
637
- try:
638
- list_response = client.list_agent_runtimes()
639
- for runtime in list_response.get("agentRuntimes", []):
640
- if runtime.get("agentRuntimeName") == agent_name:
641
- existing_agent_runtime_id = runtime.get("agentRuntimeId")
642
- print(f"Found existing agent runtime with ID: {existing_agent_runtime_id}")
643
- break
644
- except Exception as e:
645
- print(f"Error listing agent runtimes: {e}")
646
-
647
- if existing_agent_runtime_id:
648
- # Update the existing agent runtime
649
- try:
650
- update_response = client.update_agent_runtime(
651
- agentRuntimeId=existing_agent_runtime_id,
652
- agentRuntimeArtifact={
653
- "containerConfiguration": {
654
- "containerUri": "\${aws_ecr_repository.agent_core_repository.repository_url}:latest"
655
- }
656
- },
657
- environmentVariables=environment_variables,
658
- networkConfiguration={"networkMode": "PUBLIC"},
659
- protocolConfiguration={"serverProtocol": "\${var.server_protocol}"},
660
- \${var.customJWTAuthorizer == null ? "" : "authorizerConfiguration=authorization_config,"}
661
- roleArn="\${aws_iam_role.agent_core_runtime_role.arn}"
662
- )
663
- agent_runtime_id = existing_agent_runtime_id
664
- print(f"Agent runtime updated successfully: {agent_runtime_id}")
665
- except Exception as e:
666
- print(f"Error updating agent runtime: {e}")
667
- # If update fails, try to create a new one
668
- existing_agent_runtime_id = None
669
-
670
- if not existing_agent_runtime_id:
671
- # Agent runtime doesn"t exist or update failed, create it
672
- response = client.create_agent_runtime(
673
- agentRuntimeName=agent_name,
674
- agentRuntimeArtifact={
675
- "containerConfiguration": {
676
- "containerUri": "\${aws_ecr_repository.agent_core_repository.repository_url}:latest"
677
- }
678
- },
679
- environmentVariables=environment_variables,
680
- networkConfiguration={"networkMode": "PUBLIC"},
681
- protocolConfiguration={"serverProtocol": "\${var.server_protocol}"},
682
- \${var.customJWTAuthorizer == null ? "" : "authorizerConfiguration=authorization_config,"}
683
- roleArn="\${aws_iam_role.agent_core_runtime_role.arn}"
684
- )
685
-
686
- agent_runtime_id = response.get("agentRuntimeId", "")
687
- print(f"Agent runtime created successfully with ID: {agent_runtime_id}")
688
-
689
- except Exception as e:
690
- print(f"Error managing agent runtime: {str(e)}")
691
- sys.exit(1)
692
- '
693
- EOT
444
+ agent_runtime_artifact {
445
+ container_configuration {
446
+ container_uri = "\${aws_ecr_repository.agent_core_repository.repository_url}:latest"
447
+ }
694
448
  }
695
449
 
696
- depends_on = [
697
- null_resource.docker_publish,
698
- aws_iam_role_policy_attachment.agent_core_policy
699
- ]
700
- }
701
-
450
+ environment_variables = length(var.env) > 0 ? var.env : null
702
451
 
703
- # Null resource for cleanup/destroy
704
- resource "null_resource" "agent_core_cleanup" {
705
- triggers = {
706
- aws_region = local.aws_region
707
- agent_name = var.agent_runtime_name
708
- unique_suffix = random_id.unique_suffix.hex
452
+ dynamic "authorizer_configuration" {
453
+ for_each = var.authorizer_configuration != null && var.authorizer_configuration.custom_jwt_authorizer != null ? [var.authorizer_configuration.custom_jwt_authorizer] : []
454
+ content {
455
+ custom_jwt_authorizer {
456
+ discovery_url = authorizer_configuration.value.discovery_url
457
+ allowed_audience = authorizer_configuration.value.allowed_audience
458
+ allowed_clients = authorizer_configuration.value.allowed_clients
459
+ }
460
+ }
709
461
  }
710
462
 
711
- provisioner "local-exec" {
712
- when = destroy
713
- command = <<-EOT
714
- uv run --with boto3 python -c "
715
- import boto3
716
- import json
717
- import os
718
-
719
- # Create the client
720
- client = boto3.client('bedrock-agentcore-control', region_name='\${self.triggers.aws_region}')
721
-
722
- agent_name = '\${self.triggers.agent_name}_\${self.triggers.unique_suffix}'
723
-
724
- try:
725
- # Find the agent runtime by name
726
- agent_runtime_id = None
727
- try:
728
- list_response = client.list_agent_runtimes()
729
- for runtime in list_response.get('agentRuntimes', []):
730
- if runtime.get('agentRuntimeName') == agent_name:
731
- agent_runtime_id = runtime.get('agentRuntimeId')
732
- print(f'Found agent runtime to delete: {agent_name} (ID: {agent_runtime_id})')
733
- break
734
- except Exception as e:
735
- print(f'Error listing agent runtimes: {e}')
736
-
737
- if not agent_runtime_id:
738
- print(f'No agent runtime found with name: {agent_name}')
739
- exit(0)
740
-
741
- # Delete the agent runtime using the found ID
742
- response = client.delete_agent_runtime(
743
- agentRuntimeId=agent_runtime_id
744
- )
745
- print(f'Agent runtime {agent_name} (ID: {agent_runtime_id}) deleted successfully:', json.dumps(response, indent=2, default=str))
463
+ network_configuration {
464
+ network_mode = "PUBLIC"
465
+ }
746
466
 
747
- except client.exceptions.ResourceNotFoundException:
748
- print(f'Agent runtime {agent_name} not found, may have been already deleted')
749
- except Exception as e:
750
- print(f'Error deleting agent runtime {agent_name}:', str(e))
751
- # Don't exit with error code during destroy to avoid blocking cleanup
752
- "
753
- EOT
467
+ protocol_configuration {
468
+ server_protocol = var.server_protocol
754
469
  }
755
470
 
756
- depends_on = [null_resource.agent_core_runtime_deployment]
757
- }
471
+ tags = var.tags
758
472
 
759
- # Data source to find the agent runtime by name and get its ID
760
- data "external" "agent_runtime_lookup" {
761
- program = ["uv", "run", "--with", "boto3", "python", "-c", <<-EOT
762
- import boto3
763
- import json
764
- import sys
765
-
766
- # Create the client
767
- client = boto3.client("bedrock-agentcore-control", region_name="\${local.aws_region}")
768
-
769
- agent_name = "\${var.agent_runtime_name}_\${random_id.unique_suffix.hex}"
770
-
771
- try:
772
- # Find the agent runtime by name
773
- list_response = client.list_agent_runtimes()
774
- for runtime in list_response.get("agentRuntimes", []):
775
- if runtime.get("agentRuntimeName") == agent_name:
776
- agent_runtime_id = runtime.get("agentRuntimeId")
777
- runtime_arn = f"arn:aws:bedrock-agentcore:\${local.aws_region}:\${local.aws_account_id}:runtime/{agent_runtime_id}"
778
-
779
- result = {
780
- "agent_runtime_id": agent_runtime_id,
781
- "agent_runtime_arn": runtime_arn,
782
- "agent_name": agent_name
783
- }
784
- print(json.dumps(result))
785
- sys.exit(0)
786
-
787
- # If not found, return empty values
788
- result = {
789
- "agent_runtime_id": "",
790
- "agent_runtime_arn": "",
791
- "agent_name": agent_name
792
- }
793
- print(json.dumps(result))
794
-
795
- except Exception as e:
796
- print(f"Error looking up agent runtime: {str(e)}", file=sys.stderr)
797
- # Return empty values on error to avoid breaking Terraform
798
- result = {
799
- "agent_runtime_id": "",
800
- "agent_runtime_arn": "",
801
- "agent_name": agent_name
802
- }
803
- print(json.dumps(result))
804
- EOT
473
+ depends_on = [
474
+ null_resource.docker_publish,
475
+ aws_iam_role_policy.agent_core_runtime_policy
805
476
  ]
806
-
807
- depends_on = [null_resource.agent_core_runtime_deployment]
808
477
  }
809
478
 
810
479
  # Outputs
@@ -820,17 +489,22 @@ output "agent_core_runtime_role_name" {
820
489
 
821
490
  output "agent_runtime_name" {
822
491
  description = "Name of the deployed agent runtime"
823
- value = "\${var.agent_runtime_name}-\${random_id.unique_suffix.hex}"
492
+ value = aws_bedrockagentcore_agent_runtime.agent_runtime.agent_runtime_name
824
493
  }
825
494
 
826
495
  output "agent_core_runtime_arn" {
827
496
  description = "ARN of the Bedrock Agent Core runtime"
828
- value = data.external.agent_runtime_lookup.result.agent_runtime_arn
497
+ value = aws_bedrockagentcore_agent_runtime.agent_runtime.agent_runtime_arn
829
498
  }
830
499
 
831
500
  output "agent_runtime_id" {
832
501
  description = "ID of the Bedrock Agent Core runtime"
833
- value = data.external.agent_runtime_lookup.result.agent_runtime_id
502
+ value = aws_bedrockagentcore_agent_runtime.agent_runtime.agent_runtime_id
503
+ }
504
+
505
+ output "agent_runtime_version" {
506
+ description = "Version of the Bedrock Agent Core runtime"
507
+ value = aws_bedrockagentcore_agent_runtime.agent_runtime.agent_runtime_version
834
508
  }
835
509
  "
836
510
  `;
@@ -181,13 +181,12 @@ import {
181
181
  Cors,
182
182
  LambdaIntegration,
183
183
  } from 'aws-cdk-lib/aws-apigateway';
184
- import { Duration, Stack } from 'aws-cdk-lib';
184
+ import { Duration } from 'aws-cdk-lib';
185
185
  import {
186
186
  PolicyDocument,
187
187
  PolicyStatement,
188
188
  Effect,
189
189
  AnyPrincipal,
190
- AccountPrincipal,
191
190
  IGrantable,
192
191
  Grant,
193
192
  } from 'aws-cdk-lib/aws-iam';
@@ -276,15 +275,6 @@ export class TestApi<
276
275
  },
277
276
  policy: new PolicyDocument({
278
277
  statements: [
279
- // Here we grant any AWS credentials from the account that the project is deployed in to call the api.
280
- // Machine to machine fine-grained access can be defined here using more specific principals (eg roles or
281
- // users) and resources (eg which api paths may be invoked by which principal) if required.
282
- new PolicyStatement({
283
- effect: Effect.ALLOW,
284
- principals: [new AccountPrincipal(Stack.of(scope).account)],
285
- actions: ['execute-api:Invoke'],
286
- resources: ['execute-api:/*'],
287
- }),
288
278
  // Open up OPTIONS to allow browsers to make unauthenticated preflight requests
289
279
  new PolicyStatement({
290
280
  effect: Effect.ALLOW,
@@ -305,6 +295,18 @@ export class TestApi<
305
295
  * @param grantee - The IAM principal to grant permissions to
306
296
  */
307
297
  public grantInvokeAccess(grantee: IGrantable) {
298
+ // Here we grant grantee permission to call the api.
299
+ // Machine to machine fine-grained access can be defined here using more specific principals (eg roles or
300
+ // users) and resources (eg which api paths may be invoked by which principal) if required.
301
+ this.api.addToResourcePolicy(
302
+ new PolicyStatement({
303
+ effect: Effect.ALLOW,
304
+ principals: [grantee.grantPrincipal],
305
+ actions: ['execute-api:Invoke'],
306
+ resources: ['execute-api:/*'],
307
+ }),
308
+ );
309
+
308
310
  Grant.addToPrincipal({
309
311
  grantee,
310
312
  actions: ['execute-api:Invoke'],