diff --git a/browser_custom.tf b/browser_custom.tf index 78130d3..7e23aba 100644 --- a/browser_custom.tf +++ b/browser_custom.tf @@ -5,9 +5,9 @@ locals { # Browser name is now validated directly in the variable definition # No need to sanitize here as the validation will prevent invalid names browser_name = var.browser_name - + # Data Plane Permissions - + # Permissions to manage a specific browser session browser_session_perms = [ "bedrock-agentcore:GetBrowserSession", @@ -15,16 +15,16 @@ locals { "bedrock-agentcore:StartBrowserSession", "bedrock-agentcore:StopBrowserSession" ] - + # Permissions to connect to a browser live view or automation stream browser_stream_perms = [ "bedrock-agentcore:UpdateBrowserStream", "bedrock-agentcore:ConnectBrowserAutomationStream", "bedrock-agentcore:ConnectBrowserLiveViewStream" ] - + # Control Plane Permissions - + # Grants control plane operations to manage the browser (CRUD) browser_admin_perms = [ "bedrock-agentcore:CreateBrowser", @@ -32,121 +32,121 @@ locals { "bedrock-agentcore:GetBrowser", "bedrock-agentcore:ListBrowsers" ] - + # Permissions for reading browser information browser_read_perms = [ "bedrock-agentcore:GetBrowser", "bedrock-agentcore:GetBrowserSession" ] - + # Permissions for listing browser resources browser_list_perms = [ "bedrock-agentcore:ListBrowsers", "bedrock-agentcore:ListBrowserSessions" ] - + # Permissions for using browser functionality browser_use_perms = [ "bedrock-agentcore:StartBrowserSession", "bedrock-agentcore:UpdateBrowserStream", "bedrock-agentcore:StopBrowserSession" ] - + # Combined permissions for full access browser_full_access_perms = distinct(concat( local.browser_session_perms, local.browser_stream_perms, local.browser_admin_perms )) - + # Policy documents - + # Browser full access policy document browser_full_access_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCoreBrowserFullAccess" - Effect = "Allow" - Action = local.browser_full_access_perms + Sid = "BedrockAgentCoreBrowserFullAccess" + Effect = "Allow" + Action = local.browser_full_access_perms Resource = "arn:aws:bedrock-agentcore:*:*:browser/*" } ] } - + # Browser session policy document browser_session_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCoreBrowserSession" - Effect = "Allow" - Action = local.browser_session_perms + Sid = "BedrockAgentCoreBrowserSession" + Effect = "Allow" + Action = local.browser_session_perms Resource = "arn:aws:bedrock-agentcore:*:*:browser/*" } ] } - + # Browser stream policy document browser_stream_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCoreBrowserStream" - Effect = "Allow" - Action = local.browser_stream_perms + Sid = "BedrockAgentCoreBrowserStream" + Effect = "Allow" + Action = local.browser_stream_perms Resource = "arn:aws:bedrock-agentcore:*:*:browser/*" } ] } - + # Browser admin policy document browser_admin_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCoreBrowserAdmin" - Effect = "Allow" - Action = local.browser_admin_perms + Sid = "BedrockAgentCoreBrowserAdmin" + Effect = "Allow" + Action = local.browser_admin_perms Resource = "arn:aws:bedrock-agentcore:*:*:browser/*" } ] } - + # Browser read policy document browser_read_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCoreBrowserRead" - Effect = "Allow" - Action = local.browser_read_perms + Sid = "BedrockAgentCoreBrowserRead" + Effect = "Allow" + Action = local.browser_read_perms Resource = "arn:aws:bedrock-agentcore:*:*:browser/*" } ] } - + # Browser list policy document browser_list_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCoreBrowserList" - Effect = "Allow" - Action = local.browser_list_perms + Sid = "BedrockAgentCoreBrowserList" + Effect = "Allow" + Action = local.browser_list_perms Resource = "arn:aws:bedrock-agentcore:*:*:browser/*" } ] } - + # Browser use policy document browser_use_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCoreBrowserUse" - Effect = "Allow" - Action = local.browser_use_perms + Sid = "BedrockAgentCoreBrowserUse" + Effect = "Allow" + Action = local.browser_use_perms Resource = "arn:aws:bedrock-agentcore:*:*:browser/*" } ] @@ -158,10 +158,10 @@ resource "awscc_bedrockagentcore_browser_custom" "agent_browser" { name = "${random_string.solution_prefix.result}_${local.browser_name}" description = var.browser_description execution_role_arn = var.browser_role_arn != null ? var.browser_role_arn : aws_iam_role.browser_role[0].arn - + network_configuration = { network_mode = var.browser_network_mode - vpc_config = var.browser_network_mode == "VPC" ? { + vpc_config = var.browser_network_mode == "VPC" ? { security_groups = var.browser_network_configuration.security_groups subnets = var.browser_network_configuration.subnets } : null @@ -176,7 +176,7 @@ resource "awscc_bedrockagentcore_browser_custom" "agent_browser" { } : null tags = var.browser_tags - + # Explicit dependency to avoid race conditions with IAM role creation depends_on = [ aws_iam_role.browser_role, diff --git a/code_interpreter.tf b/code_interpreter.tf index aece6d2..931e66f 100644 --- a/code_interpreter.tf +++ b/code_interpreter.tf @@ -4,9 +4,9 @@ locals { create_code_interpreter = var.create_code_interpreter # Sanitize code interpreter name to ensure it follows the regex pattern ^[a-zA-Z][a-zA-Z0-9_]{0,47}$ sanitized_code_interpreter_name = replace(var.code_interpreter_name, "-", "_") - + # Data Plane Permissions - + # Permissions to manage a specific code interpreter session code_interpreter_session_perms = [ "bedrock-agentcore:GetCodeInterpreterSession", @@ -14,12 +14,12 @@ locals { "bedrock-agentcore:StartCodeInterpreterSession", "bedrock-agentcore:StopCodeInterpreterSession" ] - + # Permissions to invoke a code interpreter code_interpreter_invoke_perms = ["bedrock-agentcore:InvokeCodeInterpreter"] - + # Control Plane Permissions - + # Grants control plane operations to manage the code interpreter (CRUD) code_interpreter_admin_perms = [ "bedrock-agentcore:CreateCodeInterpreter", @@ -27,121 +27,121 @@ locals { "bedrock-agentcore:GetCodeInterpreter", "bedrock-agentcore:ListCodeInterpreters" ] - + # Permissions for reading code interpreter information code_interpreter_read_perms = [ "bedrock-agentcore:GetCodeInterpreter", "bedrock-agentcore:GetCodeInterpreterSession" ] - + # Permissions for listing code interpreter resources code_interpreter_list_perms = [ "bedrock-agentcore:ListCodeInterpreters", "bedrock-agentcore:ListCodeInterpreterSessions" ] - + # Permissions for using code interpreter functionality code_interpreter_use_perms = [ "bedrock-agentcore:StartCodeInterpreterSession", "bedrock-agentcore:InvokeCodeInterpreter", "bedrock-agentcore:StopCodeInterpreterSession" ] - + # Combined permissions for full access code_interpreter_full_access_perms = distinct(concat( local.code_interpreter_session_perms, local.code_interpreter_invoke_perms, local.code_interpreter_admin_perms )) - + # Policy documents - + # Code interpreter full access policy document code_interpreter_full_access_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCodeInterpreterFullAccess" - Effect = "Allow" - Action = local.code_interpreter_full_access_perms + Sid = "BedrockAgentCodeInterpreterFullAccess" + Effect = "Allow" + Action = local.code_interpreter_full_access_perms Resource = "arn:aws:bedrock-agentcore:*:*:code-interpreter/*" } ] } - + # Code interpreter session policy document code_interpreter_session_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCodeInterpreterSession" - Effect = "Allow" - Action = local.code_interpreter_session_perms + Sid = "BedrockAgentCodeInterpreterSession" + Effect = "Allow" + Action = local.code_interpreter_session_perms Resource = "arn:aws:bedrock-agentcore:*:*:code-interpreter/*" } ] } - + # Code interpreter invoke policy document code_interpreter_invoke_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCodeInterpreterInvoke" - Effect = "Allow" - Action = local.code_interpreter_invoke_perms + Sid = "BedrockAgentCodeInterpreterInvoke" + Effect = "Allow" + Action = local.code_interpreter_invoke_perms Resource = "arn:aws:bedrock-agentcore:*:*:code-interpreter/*" } ] } - + # Code interpreter admin policy document code_interpreter_admin_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCodeInterpreterAdmin" - Effect = "Allow" - Action = local.code_interpreter_admin_perms + Sid = "BedrockAgentCodeInterpreterAdmin" + Effect = "Allow" + Action = local.code_interpreter_admin_perms Resource = "arn:aws:bedrock-agentcore:*:*:code-interpreter/*" } ] } - + # Code interpreter read policy document code_interpreter_read_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCodeInterpreterRead" - Effect = "Allow" - Action = local.code_interpreter_read_perms + Sid = "BedrockAgentCodeInterpreterRead" + Effect = "Allow" + Action = local.code_interpreter_read_perms Resource = "arn:aws:bedrock-agentcore:*:*:code-interpreter/*" } ] } - + # Code interpreter list policy document code_interpreter_list_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCodeInterpreterList" - Effect = "Allow" - Action = local.code_interpreter_list_perms + Sid = "BedrockAgentCodeInterpreterList" + Effect = "Allow" + Action = local.code_interpreter_list_perms Resource = "arn:aws:bedrock-agentcore:*:*:code-interpreter/*" } ] } - + # Code interpreter use policy document code_interpreter_use_policy_doc = { Version = "2012-10-17" Statement = [ { - Sid = "BedrockAgentCodeInterpreterUse" - Effect = "Allow" - Action = local.code_interpreter_use_perms + Sid = "BedrockAgentCodeInterpreterUse" + Effect = "Allow" + Action = local.code_interpreter_use_perms Resource = "arn:aws:bedrock-agentcore:*:*:code-interpreter/*" } ] @@ -153,17 +153,17 @@ resource "awscc_bedrockagentcore_code_interpreter_custom" "agent_code_interprete name = "${random_string.solution_prefix.result}_${local.sanitized_code_interpreter_name}" description = var.code_interpreter_description execution_role_arn = var.code_interpreter_role_arn != null ? var.code_interpreter_role_arn : aws_iam_role.code_interpreter_role[0].arn - + network_configuration = { network_mode = var.code_interpreter_network_mode - vpc_config = var.code_interpreter_network_mode == "VPC" ? { + vpc_config = var.code_interpreter_network_mode == "VPC" ? { security_groups = var.code_interpreter_network_configuration.security_groups subnets = var.code_interpreter_network_configuration.subnets } : null } tags = var.code_interpreter_tags - + # Explicit dependency to avoid race conditions with IAM role creation depends_on = [ aws_iam_role.code_interpreter_role, @@ -238,17 +238,17 @@ resource "aws_iam_role_policy" "code_interpreter_role_policy" { "arn:aws:bedrock:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:*" ] } - ], - # Add VPC permissions if applicable - var.code_interpreter_network_mode == "VPC" ? [{ - Sid = "VPCAccess" - Effect = "Allow" - Action = [ - "ec2:CreateNetworkInterface", - "ec2:DescribeNetworkInterfaces", - "ec2:DeleteNetworkInterface" - ] - Resource = "*" + ], + # Add VPC permissions if applicable + var.code_interpreter_network_mode == "VPC" ? [{ + Sid = "VPCAccess" + Effect = "Allow" + Action = [ + "ec2:CreateNetworkInterface", + "ec2:DescribeNetworkInterfaces", + "ec2:DeleteNetworkInterface" + ] + Resource = "*" }] : []) }) } diff --git a/cognito.tf b/cognito.tf index 1916a78..3b006d3 100644 --- a/cognito.tf +++ b/cognito.tf @@ -18,7 +18,7 @@ locals { } resource "random_password" "password" { - count = local.create_user_pool && var.user_pool_create_admin ? 1 : 0 + count = local.create_user_pool && var.user_pool_create_admin ? 1 : 0 length = 16 special = true override_special = "!#$%&*()-_=+[]{}<>:?" diff --git a/gateway.tf b/gateway.tf index b351dae..5be34d4 100644 --- a/gateway.tf +++ b/gateway.tf @@ -152,7 +152,7 @@ resource "aws_iam_role_policy" "gateway_role_policy" { ] Resource = [ "arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default", - "arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default/workload-identity/${var.gateway_name}-*" + "arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default/workload-identity/${random_string.solution_prefix.result}-${var.gateway_name}-*" ] }, { @@ -182,7 +182,7 @@ resource "aws_iam_role_policy" "gateway_role_policy" { ] Resource = [ "arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default", - "arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default/workload-identity/${var.gateway_name}-*" + "arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default/workload-identity/${random_string.solution_prefix.result}-${var.gateway_name}-*" ] }, { @@ -191,7 +191,15 @@ resource "aws_iam_role_policy" "gateway_role_policy" { Action = [ "bedrock-agentcore:GetResourceApiKey" ] - Resource = var.apikey_credential_provider_arn != null ? [var.apikey_credential_provider_arn] : [] + Resource = concat( + var.apikey_credential_provider_arn != null ? [var.apikey_credential_provider_arn] : [], + var.apikey_secret_arn != null ? [var.apikey_secret_arn] : [], + [ + "arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default", + "arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:workload-identity-directory/default/workload-identity/${random_string.solution_prefix.result}-${var.gateway_name}-*", + "arn:aws:bedrock-agentcore:${data.aws_region.current.region}:${data.aws_caller_identity.current.account_id}:token-vault/default" + ] + ) }, { Sid = "GetSecretValueApiKey" diff --git a/main.tf b/main.tf index a87ad5c..db6294e 100644 --- a/main.tf +++ b/main.tf @@ -32,7 +32,7 @@ data "aws_iam_policy_document" "service_linked_role" { condition { test = "StringEquals" variable = "iam:AWSServiceName" - values = [ + values = [ "runtime-identity.bedrock-agentcore.amazonaws.com" ] } @@ -44,7 +44,7 @@ resource "awscc_bedrockagentcore_runtime" "agent_runtime" { agent_runtime_name = "${random_string.solution_prefix.result}_${local.sanitized_runtime_name}" description = var.runtime_description role_arn = var.runtime_role_arn != null ? var.runtime_role_arn : aws_iam_role.runtime_role[0].arn - + # Explicit dependency to avoid race conditions with IAM role creation # Include the time_sleep resource to ensure IAM role propagation depends_on = [ diff --git a/memory.tf b/memory.tf index ccff13f..2624754 100644 --- a/memory.tf +++ b/memory.tf @@ -6,41 +6,41 @@ locals { # Data Plane Permissions - + # Short-Term Memory (STM) permissions - stm_write_perms = ["bedrock-agentcore:CreateEvent"] - stm_read_perms = [ + stm_write_perms = ["bedrock-agentcore:CreateEvent"] + stm_read_perms = [ "bedrock-agentcore:GetEvent", "bedrock-agentcore:ListEvents", "bedrock-agentcore:ListActors", "bedrock-agentcore:ListSessions", ] - stm_delete_perms = ["bedrock-agentcore:DeleteEvent"] - + stm_delete_perms = ["bedrock-agentcore:DeleteEvent"] + # Long-Term Memory (LTM) permissions # Note: There is no "bedrock-agentcore:CreateMemoryRecord" as you cannot write directly to LTM # This is done asynchronously once extraction strategies have been configured - ltm_read_perms = [ + ltm_read_perms = [ "bedrock-agentcore:GetMemoryRecord", "bedrock-agentcore:RetrieveMemoryRecords", # Read via semantic query "bedrock-agentcore:ListMemoryRecords", "bedrock-agentcore:ListActors", "bedrock-agentcore:ListSessions", ] - ltm_delete_perms = ["bedrock-agentcore:DeleteMemoryRecord"] - + ltm_delete_perms = ["bedrock-agentcore:DeleteMemoryRecord"] + # Combined permissions for both STM and LTM memory_read_perms = distinct(concat(local.stm_read_perms, local.ltm_read_perms)) memory_delete_perms = distinct(concat(local.stm_delete_perms, local.ltm_delete_perms)) - + # Control Plane Permissions - memory_admin_perms = [ + memory_admin_perms = [ "bedrock-agentcore:CreateMemory", "bedrock-agentcore:GetMemory", "bedrock-agentcore:DeleteMemory", "bedrock-agentcore:UpdateMemory", ] - + # Full access permissions (combines all permissions) memory_full_access_perms = distinct(concat( local.stm_write_perms, @@ -54,12 +54,12 @@ locals { create_memory = var.create_memory # Sanitize memory name to ensure it follows the regex pattern ^[a-zA-Z][a-zA-Z0-9_]{0,47}$ sanitized_memory_name = replace(var.memory_name, "-", "_") - + # Determine if KMS is being used for memory encryption kms_provided = var.memory_encryption_key_arn != null - + # Determine if we need to create a KMS policy - create_kms_policy = local.create_memory && local.kms_provided + create_kms_policy = local.create_memory && local.kms_provided } # Determine if we need to create an IAM role for the memory @@ -68,23 +68,23 @@ locals { # Custom strategies require a role for Bedrock model access has_custom_strategies = length(var.memory_strategies) > 0 && contains( flatten([ - for strategy in var.memory_strategies : + for strategy in var.memory_strategies : strategy.custom_memory_strategy != null ? ["has_custom"] : [] ]), "has_custom" ) - + # Check if any strategies are self-managed strategies that need S3/SNS access has_self_managed_strategies = length(var.memory_strategies) > 0 && contains( flatten([ - for strategy in var.memory_strategies : - strategy.custom_memory_strategy != null && - strategy.custom_memory_strategy.configuration != null && + for strategy in var.memory_strategies : + strategy.custom_memory_strategy != null && + strategy.custom_memory_strategy.configuration != null && strategy.custom_memory_strategy.configuration.self_managed_configuration != null ? ["has_self_managed"] : [] ]), "has_self_managed" ) - + # Only create a role if we have custom strategies that need model access create_memory_role = local.create_memory && var.memory_execution_role_arn == null && (local.has_custom_strategies || local.create_kms_policy) } @@ -127,22 +127,22 @@ resource "aws_iam_role_policy_attachment" "memory_execution_policy" { locals { # Get all unique bucket names from self-managed strategies s3_bucket_names = distinct(compact([ - for strategy in var.memory_strategies : - try(strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration.payload_delivery_bucket_name, null) - if strategy.custom_memory_strategy != null && - strategy.custom_memory_strategy.configuration != null && - strategy.custom_memory_strategy.configuration.self_managed_configuration != null && - strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration != null + for strategy in var.memory_strategies : + try(strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration.payload_delivery_bucket_name, null) + if strategy.custom_memory_strategy != null && + strategy.custom_memory_strategy.configuration != null && + strategy.custom_memory_strategy.configuration.self_managed_configuration != null && + strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration != null ])) - + # Get all unique SNS topic ARNs from self-managed strategies sns_topic_arns = distinct(compact([ - for strategy in var.memory_strategies : - try(strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration.topic_arn, null) - if strategy.custom_memory_strategy != null && - strategy.custom_memory_strategy.configuration != null && - strategy.custom_memory_strategy.configuration.self_managed_configuration != null && - strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration != null + for strategy in var.memory_strategies : + try(strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration.topic_arn, null) + if strategy.custom_memory_strategy != null && + strategy.custom_memory_strategy.configuration != null && + strategy.custom_memory_strategy.configuration.self_managed_configuration != null && + strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration != null ])) } @@ -234,8 +234,8 @@ resource "aws_iam_role_policy_attachment" "memory_kms_policy" { # Add a time delay to ensure IAM role propagation resource "time_sleep" "memory_iam_role_propagation" { - count = local.create_memory_role ? 1 : 0 - depends_on = [ + count = local.create_memory_role ? 1 : 0 + depends_on = [ aws_iam_role.memory_role, aws_iam_role_policy_attachment.memory_execution_policy, aws_iam_role_policy_attachment.memory_self_managed_policy, @@ -255,7 +255,7 @@ locals { Resource = "*" }] } - + # Memory Read permissions policy document (both STM and LTM) memory_read_policy_doc = { Version = "2012-10-17" @@ -265,7 +265,7 @@ locals { Resource = "*" }] } - + # STM Read permissions policy document memory_stm_read_policy_doc = { Version = "2012-10-17" @@ -275,7 +275,7 @@ locals { Resource = "*" }] } - + # LTM Read permissions policy document memory_ltm_read_policy_doc = { Version = "2012-10-17" @@ -285,7 +285,7 @@ locals { Resource = "*" }] } - + # Memory Delete permissions policy document (both STM and LTM) memory_delete_policy_doc = { Version = "2012-10-17" @@ -295,7 +295,7 @@ locals { Resource = "*" }] } - + # STM Delete permissions policy document memory_stm_delete_policy_doc = { Version = "2012-10-17" @@ -305,7 +305,7 @@ locals { Resource = "*" }] } - + # LTM Delete permissions policy document memory_ltm_delete_policy_doc = { Version = "2012-10-17" @@ -315,7 +315,7 @@ locals { Resource = "*" }] } - + # Memory Admin permissions policy document memory_admin_policy_doc = { Version = "2012-10-17" @@ -325,7 +325,7 @@ locals { Resource = "*" }] } - + # Memory Full Access permissions policy document memory_full_access_policy_doc = { Version = "2012-10-17" @@ -338,18 +338,18 @@ locals { } resource "awscc_bedrockagentcore_memory" "agent_memory" { - count = local.create_memory ? 1 : 0 - name = "${random_string.solution_prefix.result}_${local.sanitized_memory_name}" - description = var.memory_description - event_expiry_duration = var.memory_event_expiry_duration - encryption_key_arn = var.memory_encryption_key_arn + count = local.create_memory ? 1 : 0 + name = "${random_string.solution_prefix.result}_${local.sanitized_memory_name}" + description = var.memory_description + event_expiry_duration = var.memory_event_expiry_duration + encryption_key_arn = var.memory_encryption_key_arn memory_execution_role_arn = var.memory_execution_role_arn != null ? var.memory_execution_role_arn : (local.create_memory_role ? try(aws_iam_role.memory_role[0].arn, null) : null) - + # Explicit dependency to avoid race conditions with IAM role creation depends_on = [ time_sleep.memory_iam_role_propagation ] - + # Direct assignment of memory strategies memory_strategies = [ for strategy in var.memory_strategies : { @@ -359,39 +359,39 @@ resource "awscc_bedrockagentcore_memory" "agent_memory" { description = strategy.semantic_memory_strategy.description namespaces = strategy.semantic_memory_strategy.namespaces } : null - + # Summary memory strategy summary_memory_strategy = strategy.summary_memory_strategy != null ? { name = strategy.summary_memory_strategy.name description = strategy.summary_memory_strategy.description namespaces = strategy.summary_memory_strategy.namespaces } : null - + # User preference memory strategy user_preference_memory_strategy = strategy.user_preference_memory_strategy != null ? { name = strategy.user_preference_memory_strategy.name description = strategy.user_preference_memory_strategy.description namespaces = strategy.user_preference_memory_strategy.namespaces } : null - + # Custom memory strategy custom_memory_strategy = strategy.custom_memory_strategy != null ? { name = strategy.custom_memory_strategy.name description = strategy.custom_memory_strategy.description namespaces = strategy.custom_memory_strategy.namespaces - + # Custom strategy configuration configuration = strategy.custom_memory_strategy.configuration != null ? { # Self-managed configuration self_managed_configuration = strategy.custom_memory_strategy.configuration.self_managed_configuration != null ? { historical_context_window_size = strategy.custom_memory_strategy.configuration.self_managed_configuration.historical_context_window_size - + # Invocation configuration invocation_configuration = strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration != null ? { payload_delivery_bucket_name = strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration.payload_delivery_bucket_name - topic_arn = strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration.topic_arn + topic_arn = strategy.custom_memory_strategy.configuration.self_managed_configuration.invocation_configuration.topic_arn } : null - + # Trigger conditions trigger_conditions = strategy.custom_memory_strategy.configuration.self_managed_configuration.trigger_conditions != null ? [ for trigger in strategy.custom_memory_strategy.configuration.self_managed_configuration.trigger_conditions : { @@ -399,12 +399,12 @@ resource "awscc_bedrockagentcore_memory" "agent_memory" { message_based_trigger = trigger.message_based_trigger != null ? { message_count = trigger.message_based_trigger.message_count } : null - + # Time-based trigger time_based_trigger = trigger.time_based_trigger != null ? { idle_session_timeout = trigger.time_based_trigger.idle_session_timeout } : null - + # Token-based trigger token_based_trigger = trigger.token_based_trigger != null ? { token_count = trigger.token_based_trigger.token_count @@ -412,49 +412,49 @@ resource "awscc_bedrockagentcore_memory" "agent_memory" { } ] : null } : null - + # Semantic override semantic_override = strategy.custom_memory_strategy.configuration.semantic_override != null ? { # Consolidation consolidation = strategy.custom_memory_strategy.configuration.semantic_override.consolidation != null ? { append_to_prompt = strategy.custom_memory_strategy.configuration.semantic_override.consolidation.append_to_prompt - model_id = strategy.custom_memory_strategy.configuration.semantic_override.consolidation.model_id + model_id = strategy.custom_memory_strategy.configuration.semantic_override.consolidation.model_id } : null - + # Extraction extraction = strategy.custom_memory_strategy.configuration.semantic_override.extraction != null ? { append_to_prompt = strategy.custom_memory_strategy.configuration.semantic_override.extraction.append_to_prompt - model_id = strategy.custom_memory_strategy.configuration.semantic_override.extraction.model_id + model_id = strategy.custom_memory_strategy.configuration.semantic_override.extraction.model_id } : null } : null - + # Summary override summary_override = strategy.custom_memory_strategy.configuration.summary_override != null ? { # Consolidation consolidation = strategy.custom_memory_strategy.configuration.summary_override.consolidation != null ? { append_to_prompt = strategy.custom_memory_strategy.configuration.summary_override.consolidation.append_to_prompt - model_id = strategy.custom_memory_strategy.configuration.summary_override.consolidation.model_id + model_id = strategy.custom_memory_strategy.configuration.summary_override.consolidation.model_id } : null } : null - + # User preference override user_preference_override = strategy.custom_memory_strategy.configuration.user_preference_override != null ? { # Consolidation consolidation = strategy.custom_memory_strategy.configuration.user_preference_override.consolidation != null ? { append_to_prompt = strategy.custom_memory_strategy.configuration.user_preference_override.consolidation.append_to_prompt - model_id = strategy.custom_memory_strategy.configuration.user_preference_override.consolidation.model_id + model_id = strategy.custom_memory_strategy.configuration.user_preference_override.consolidation.model_id } : null - + # Extraction extraction = strategy.custom_memory_strategy.configuration.user_preference_override.extraction != null ? { append_to_prompt = strategy.custom_memory_strategy.configuration.user_preference_override.extraction.append_to_prompt - model_id = strategy.custom_memory_strategy.configuration.user_preference_override.extraction.model_id + model_id = strategy.custom_memory_strategy.configuration.user_preference_override.extraction.model_id } : null } : null } : null } : null } ] - + tags = var.memory_tags } diff --git a/variables.tf b/variables.tf index 6538e22..5a2fb4f 100644 --- a/variables.tf +++ b/variables.tf @@ -154,31 +154,31 @@ variable "memory_strategies" { description = "List of memory strategies attached to this memory." type = list(object({ semantic_memory_strategy = optional(object({ - name = optional(string) + name = optional(string) description = optional(string) - namespaces = optional(list(string)) + namespaces = optional(list(string)) })) summary_memory_strategy = optional(object({ - name = optional(string) + name = optional(string) description = optional(string) - namespaces = optional(list(string)) + namespaces = optional(list(string)) })) user_preference_memory_strategy = optional(object({ - name = optional(string) + name = optional(string) description = optional(string) - namespaces = optional(list(string)) + namespaces = optional(list(string)) })) custom_memory_strategy = optional(object({ - name = optional(string) + name = optional(string) description = optional(string) - namespaces = optional(list(string)) + namespaces = optional(list(string)) configuration = optional(object({ self_managed_configuration = optional(object({ historical_context_window_size = optional(number, 4) # Default to 4 messages invocation_configuration = object({ # Both fields are required when a self-managed configuration is used payload_delivery_bucket_name = string - topic_arn = string + topic_arn = string }) trigger_conditions = optional(list(object({ message_based_trigger = optional(object({ @@ -195,27 +195,27 @@ variable "memory_strategies" { semantic_override = optional(object({ consolidation = optional(object({ append_to_prompt = optional(string) - model_id = optional(string) + model_id = optional(string) })) extraction = optional(object({ append_to_prompt = optional(string) - model_id = optional(string) + model_id = optional(string) })) })) summary_override = optional(object({ consolidation = optional(object({ append_to_prompt = optional(string) - model_id = optional(string) + model_id = optional(string) })) })) user_preference_override = optional(object({ consolidation = optional(object({ append_to_prompt = optional(string) - model_id = optional(string) + model_id = optional(string) })) extraction = optional(object({ append_to_prompt = optional(string) - model_id = optional(string) + model_id = optional(string) })) })) })) @@ -279,13 +279,13 @@ variable "gateway_protocol_type" { } variable "gateway_exception_level" { - description = "Exception level for the gateway. Valid values: PARTIAL, FULL." + description = "Exception level for the gateway. Valid values: DEBUG, INFO, WARN, ERROR." type = string default = null validation { - condition = var.gateway_exception_level == null || contains(["PARTIAL", "FULL"], var.gateway_exception_level) - error_message = "The gateway_exception_level must be either PARTIAL or FULL." + condition = var.gateway_exception_level == null || contains(["DEBUG", "INFO", "WARN", "ERROR"], var.gateway_exception_level) + error_message = "The gateway_exception_level must be in [DEBUG, INFO, WARN, FULL]." } } @@ -410,7 +410,7 @@ variable "browser_name" { description = "The name of the agent core browser. Valid characters are a-z, A-Z, 0-9, _ (underscore). The name must start with a letter and can be up to 48 characters long." type = string default = "TerraformBedrockAgentCoreBrowser" - + validation { condition = can(regex("^[a-zA-Z][a-zA-Z0-9_]{0,47}$", var.browser_name)) error_message = "The browser_name must start with a letter and can only include letters, numbers, and underscores, with a maximum length of 48 characters." @@ -447,7 +447,7 @@ variable "browser_network_configuration" { subnets = optional(list(string)) }) default = null - + validation { condition = var.browser_network_configuration == null || (length(coalesce(var.browser_network_configuration.security_groups, [])) > 0 && length(coalesce(var.browser_network_configuration.subnets, [])) > 0) error_message = "When providing browser_network_configuration, you must include at least one security group and one subnet." @@ -467,14 +467,14 @@ variable "browser_recording_config" { prefix = string }) default = null - + validation { - condition = var.browser_recording_config == null || can(regex("^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$", var.browser_recording_config.bucket)) + condition = var.browser_recording_config == null || can(regex("^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$", var.browser_recording_config.bucket)) error_message = "S3 bucket name must follow naming conventions: lowercase alphanumeric characters, dots and hyphens, 3-63 characters long, starting and ending with alphanumeric character." } - + validation { - condition = var.browser_recording_config == null || var.browser_recording_config.prefix != null + condition = var.browser_recording_config == null || var.browser_recording_config.prefix != null error_message = "When providing a recording configuration, the S3 prefix cannot be null." } } @@ -483,21 +483,21 @@ variable "browser_tags" { description = "A map of tag keys and values for the agent core browser. Each tag key and value must be between 1 and 256 characters and can only include alphanumeric characters, spaces, and the following special characters: _ . : / = + @ -" type = map(string) default = null - + validation { condition = var.browser_tags == null || alltrue([ - for k, v in var.browser_tags : - length(k) >= 1 && length(k) <= 256 && - length(v) >= 1 && length(v) <= 256 + for k, v in var.browser_tags : + length(k) >= 1 && length(k) <= 256 && + length(v) >= 1 && length(v) <= 256 ]) error_message = "Each tag key and value must be between 1 and 256 characters in length." } - + validation { condition = var.browser_tags == null || alltrue([ - for k, v in var.browser_tags : - can(regex("^[a-zA-Z0-9\\s._:/=+@-]*$", k)) && - can(regex("^[a-zA-Z0-9\\s._:/=+@-]*$", v)) + for k, v in var.browser_tags : + can(regex("^[a-zA-Z0-9\\s._:/=+@-]*$", k)) && + can(regex("^[a-zA-Z0-9\\s._:/=+@-]*$", v)) ]) error_message = "Tag keys and values can only include alphanumeric characters, spaces, and the following special characters: _ . : / = + @ -" } @@ -515,12 +515,12 @@ variable "code_interpreter_name" { description = "The name of the agent core code interpreter. Valid characters are a-z, A-Z, 0-9, _ (underscore). The name must start with a letter and can be up to 48 characters long." type = string default = "TerraformBedrockAgentCoreCodeInterpreter" - + validation { condition = length(var.code_interpreter_name) >= 1 && length(var.code_interpreter_name) <= 48 error_message = "The code_interpreter_name must be between 1 and 48 characters in length." } - + validation { condition = can(regex("^[a-zA-Z][a-zA-Z0-9_]{0,47}$", var.code_interpreter_name)) error_message = "The code_interpreter_name must start with a letter and can only include letters, numbers, and underscores." @@ -531,12 +531,12 @@ variable "code_interpreter_description" { description = "Description of the agent core code interpreter. Valid characters are a-z, A-Z, 0-9, _ (underscore), - (hyphen) and spaces. The description can have up to 200 characters." type = string default = null - + validation { condition = var.code_interpreter_description == null || length(var.code_interpreter_description) <= 200 error_message = "The code_interpreter_description must be 200 characters or less." } - + validation { condition = var.code_interpreter_description == null || can(regex("^[a-zA-Z0-9_\\- ]*$", var.code_interpreter_description)) error_message = "The code_interpreter_description can only include letters, numbers, underscores, hyphens, and spaces." @@ -573,21 +573,21 @@ variable "code_interpreter_tags" { description = "A map of tag keys and values for the agent core code interpreter. Each tag key and value must be between 1 and 256 characters and can only include alphanumeric characters, spaces, and the following special characters: _ . : / = + @ -" type = map(string) default = null - + validation { condition = var.code_interpreter_tags == null || alltrue([ - for k, v in var.code_interpreter_tags : - length(k) >= 1 && length(k) <= 256 && - length(v) >= 1 && length(v) <= 256 + for k, v in var.code_interpreter_tags : + length(k) >= 1 && length(k) <= 256 && + length(v) >= 1 && length(v) <= 256 ]) error_message = "Each tag key and value must be between 1 and 256 characters in length." } - + validation { condition = var.code_interpreter_tags == null || alltrue([ - for k, v in var.code_interpreter_tags : - can(regex("^[a-zA-Z0-9\\s._:/=+@-]*$", k)) && - can(regex("^[a-zA-Z0-9\\s._:/=+@-]*$", v)) + for k, v in var.code_interpreter_tags : + can(regex("^[a-zA-Z0-9\\s._:/=+@-]*$", k)) && + can(regex("^[a-zA-Z0-9\\s._:/=+@-]*$", v)) ]) error_message = "Tag keys and values can only include alphanumeric characters, spaces, and the following special characters: _ . : / = + @ -" }