diff --git a/.header.md b/.header.md index 33ce403..c164080 100644 --- a/.header.md +++ b/.header.md @@ -263,7 +263,7 @@ Amazon Bedrock's Guardrails feature enables you to implement robust governance a With Guardrails, you can define and enforce granular, customizable policies to precisely govern the behavior of your generative AI applications. You can configure the following policies in a guardrail to avoid undesirable and harmful content and remove sensitive information for privacy protection. -Content filters – Adjust filter strengths to block input prompts or model responses containing harmful content. +Content filters – Adjust filter strengths to block input prompts or model responses containing harmful content. Supports both text and image content filtering. Use `input_modalities` and `output_modalities` (list of strings) to specify content types: `["TEXT"]` for text-only, `["IMAGE"]` for image-only, or `["TEXT", "IMAGE"]` to apply the same filter to both text and image content. Denied topics – Define a set of topics that are undesirable in the context of your application. These topics will be blocked if detected in user queries or model responses. @@ -282,14 +282,32 @@ module "bedrock" { blocked_output = "I can provide general info about services, but can't fully address your request here. For personalized help or detailed questions, please contact our customer service team directly. For security reasons, avoid sharing sensitive information through this channel. If you have a general product question, feel free to ask without including personal details." filters_config = [ { - input_strength = "MEDIUM" - output_strength = "MEDIUM" - type = "HATE" + input_strength = "MEDIUM" + output_strength = "MEDIUM" + type = "HATE" + input_modalities = ["TEXT"] + output_modalities = ["TEXT"] }, { - input_strength = "HIGH" - output_strength = "HIGH" - type = "VIOLENCE" + input_strength = "HIGH" + output_strength = "HIGH" + type = "VIOLENCE" + input_modalities = ["TEXT", "IMAGE"] + output_modalities = ["TEXT", "IMAGE"] + }, + { + input_strength = "HIGH" + output_strength = "HIGH" + type = "HATE" + input_modalities = ["IMAGE"] + output_modalities = ["IMAGE"] + }, + { + input_strength = "MEDIUM" + output_strength = "MEDIUM" + type = "SEXUAL" + input_modalities = ["IMAGE"] + output_modalities = ["IMAGE"] } ] pii_entities_config = [ diff --git a/README.md b/README.md index a8ede1d..fe7ab70 100644 --- a/README.md +++ b/README.md @@ -264,7 +264,7 @@ Amazon Bedrock's Guardrails feature enables you to implement robust governance a With Guardrails, you can define and enforce granular, customizable policies to precisely govern the behavior of your generative AI applications. You can configure the following policies in a guardrail to avoid undesirable and harmful content and remove sensitive information for privacy protection. -Content filters – Adjust filter strengths to block input prompts or model responses containing harmful content. +Content filters – Adjust filter strengths to block input prompts or model responses containing harmful content. Supports both text and image content filtering. Use `input_modalities` and `output_modalities` (list of strings) to specify content types: `["TEXT"]` for text-only, `["IMAGE"]` for image-only, or `["TEXT", "IMAGE"]` to apply the same filter to both text and image content. Denied topics – Define a set of topics that are undesirable in the context of your application. These topics will be blocked if detected in user queries or model responses. @@ -283,14 +283,32 @@ module "bedrock" { blocked_output = "I can provide general info about services, but can't fully address your request here. For personalized help or detailed questions, please contact our customer service team directly. For security reasons, avoid sharing sensitive information through this channel. If you have a general product question, feel free to ask without including personal details." filters_config = [ { - input_strength = "MEDIUM" - output_strength = "MEDIUM" - type = "HATE" + input_strength = "MEDIUM" + output_strength = "MEDIUM" + type = "HATE" + input_modalities = ["TEXT"] + output_modalities = ["TEXT"] }, { - input_strength = "HIGH" - output_strength = "HIGH" - type = "VIOLENCE" + input_strength = "HIGH" + output_strength = "HIGH" + type = "VIOLENCE" + input_modalities = ["TEXT", "IMAGE"] + output_modalities = ["TEXT", "IMAGE"] + }, + { + input_strength = "HIGH" + output_strength = "HIGH" + type = "HATE" + input_modalities = ["IMAGE"] + output_modalities = ["IMAGE"] + }, + { + input_strength = "MEDIUM" + output_strength = "MEDIUM" + type = "SEXUAL" + input_modalities = ["IMAGE"] + output_modalities = ["IMAGE"] } ] pii_entities_config = [ @@ -720,6 +738,7 @@ See the additional input variables for deploying BDA projects and blueprints [he | [app\_inference\_profile\_name](#input\_app\_inference\_profile\_name) | The name of your application inference profile. | `string` | `"AppInferenceProfile"` | no | | [app\_inference\_profile\_tags](#input\_app\_inference\_profile\_tags) | A map of tag keys and values for application inference profile. | `list(map(string))` | `null` | no | | [auth\_type](#input\_auth\_type) | The supported authentication type. | `string` | `null` | no | +| [automated\_reasoning\_policy\_config](#input\_automated\_reasoning\_policy\_config) | Optional configuration for integrating Automated Reasoning policies with the guardrail. |
object({
confidence_threshold = optional(number)
policies = optional(list(string))
})
| `null` | no | | [base\_prompt\_template](#input\_base\_prompt\_template) | Defines the prompt template with which to replace the default prompt template. | `string` | `null` | no | | [bda\_custom\_output\_config](#input\_bda\_custom\_output\_config) | A list of the BDA custom output configuartion blueprint(s). |
list(object({
blueprint_arn = optional(string)
blueprint_stage = optional(string)
blueprint_version = optional(string)
}))
| `null` | no | | [bda\_kms\_encryption\_context](#input\_bda\_kms\_encryption\_context) | The KMS encryption context for the Bedrock data automation project. | `map(string)` | `null` | no | @@ -753,7 +772,7 @@ See the additional input variables for deploying BDA projects and blueprints [he | [content\_filters\_tier\_config](#input\_content\_filters\_tier\_config) | Guardrail tier config for content policy. |
object({
tier_name = optional(string)
})
| `null` | no | | [context\_enrichment\_model\_arn](#input\_context\_enrichment\_model\_arn) | The model's ARN for context enrichment. | `string` | `null` | no | | [context\_enrichment\_type](#input\_context\_enrichment\_type) | Enrichment type to be used for the vector database. | `string` | `null` | no | -| [contextual\_grounding\_policy\_filters](#input\_contextual\_grounding\_policy\_filters) | The contextual grounding policy filters for the guardrail. | `list(map(string))` | `null` | no | +| [contextual\_grounding\_policy\_filters](#input\_contextual\_grounding\_policy\_filters) | The contextual grounding policy filters for the guardrail. |
list(object({
action = optional(string)
enabled = optional(bool)
threshold = optional(number)
type = optional(string)
}))
| `null` | no | | [crawl\_filter\_type](#input\_crawl\_filter\_type) | The crawl filter type. | `string` | `null` | no | | [crawler\_scope](#input\_crawler\_scope) | The scope that a web crawl job will be restricted to. | `string` | `null` | no | | [create\_ag](#input\_create\_ag) | Whether or not to create an action group. | `bool` | `false` | no | @@ -823,7 +842,7 @@ See the additional input variables for deploying BDA projects and blueprints [he | [enrichment\_strategy\_method](#input\_enrichment\_strategy\_method) | Enrichment Strategy method. | `string` | `null` | no | | [exclusion\_filters](#input\_exclusion\_filters) | A set of regular expression filter patterns for a type of object. | `list(string)` | `[]` | no | | [existing\_kb](#input\_existing\_kb) | The ID of the existing knowledge base. | `string` | `null` | no | -| [filters\_config](#input\_filters\_config) | List of content filter configs in content policy. | `list(map(string))` | `null` | no | +| [filters\_config](#input\_filters\_config) | List of content filter configs in content policy. Supports both text and image filters. Use 'input\_modalities' and 'output\_modalities' (list of strings) to specify content types: ['TEXT'] for text-only, ['IMAGE'] for image-only, or ['TEXT', 'IMAGE'] to apply the same filter to both text and image content in a single filter configuration. Filter types include: HATE, INSULTS, MISCONDUCT, PROMPT\_ATTACK, SEXUAL, VIOLENCE. |
list(object({
input_action = optional(string)
input_enabled = optional(bool)
input_modalities = optional(list(string))
input_strength = optional(string)
output_action = optional(string)
output_enabled = optional(bool)
output_modalities = optional(list(string))
output_strength = optional(string)
type = optional(string)
}))
| `null` | no | | [flow\_alias\_description](#input\_flow\_alias\_description) | A description of the flow alias. | `string` | `null` | no | | [flow\_alias\_name](#input\_flow\_alias\_name) | The name of your flow alias. | `string` | `"BedrockFlowAlias"` | no | | [flow\_arn](#input\_flow\_arn) | ARN representation of the flow. | `string` | `null` | no | @@ -872,7 +891,7 @@ See the additional input variables for deploying BDA projects and blueprints [he | [kms\_key\_arn](#input\_kms\_key\_arn) | KMS encryption key to use for the agent. | `string` | `null` | no | | [lambda\_action\_group\_executor](#input\_lambda\_action\_group\_executor) | ARN of Lambda. | `string` | `null` | no | | [level\_configurations\_list](#input\_level\_configurations\_list) | Token settings for each layer. | `list(object({ max_tokens = number }))` | `null` | no | -| [managed\_word\_lists\_config](#input\_managed\_word\_lists\_config) | A config for the list of managed words. | `list(map(string))` | `null` | no | +| [managed\_word\_lists\_config](#input\_managed\_word\_lists\_config) | A config for the list of managed words in word policy. |
list(object({
input_action = optional(string)
input_enabled = optional(bool)
output_action = optional(string)
output_enabled = optional(bool)
type = optional(string)
}))
| `null` | no | | [max\_length](#input\_max\_length) | The maximum number of tokens to generate in the response. | `number` | `0` | no | | [max\_pages](#input\_max\_pages) | Maximum number of pages the crawler can crawl. | `number` | `null` | no | | [memory\_configuration](#input\_memory\_configuration) | Configuration for agent memory storage |
object({
enabled_memory_types = optional(list(string))
session_summary_configuration = optional(object({
max_recent_sessions = optional(number)
}))
storage_days = optional(number)
})
| `null` | no | @@ -891,7 +910,7 @@ See the additional input variables for deploying BDA projects and blueprints [he | [parsing\_strategy](#input\_parsing\_strategy) | The parsing strategy for the data source. | `string` | `null` | no | | [pattern\_object\_filter\_list](#input\_pattern\_object\_filter\_list) | List of pattern object information. |
list(object({
exclusion_filters = optional(list(string))
inclusion_filters = optional(list(string))
object_type = optional(string)

}))
| `[]` | no | | [permissions\_boundary\_arn](#input\_permissions\_boundary\_arn) | The ARN of the IAM permission boundary for the role. | `string` | `null` | no | -| [pii\_entities\_config](#input\_pii\_entities\_config) | List of entities. | `list(map(string))` | `null` | no | +| [pii\_entities\_config](#input\_pii\_entities\_config) | List of PII entities configuration for sensitive information policy. |
list(object({
action = optional(string)
input_action = optional(string)
input_enabled = optional(bool)
output_action = optional(string)
output_enabled = optional(bool)
type = optional(string)
}))
| `null` | no | | [primary\_key\_field](#input\_primary\_key\_field) | The name of the field in which Bedrock stores the ID for each entry. | `string` | `null` | no | | [prompt\_creation\_mode](#input\_prompt\_creation\_mode) | Specifies whether to override the default prompt template. | `string` | `null` | no | | [prompt\_description](#input\_prompt\_description) | Description for a prompt resource. | `string` | `null` | no | @@ -902,13 +921,13 @@ See the additional input variables for deploying BDA projects and blueprints [he | [prompt\_type](#input\_prompt\_type) | The step in the agent sequence that this prompt configuration applies to. | `string` | `null` | no | | [prompt\_version\_description](#input\_prompt\_version\_description) | Description for a prompt version resource. | `string` | `null` | no | | [prompt\_version\_tags](#input\_prompt\_version\_tags) | A map of tag keys and values for a prompt version resource. | `map(string)` | `null` | no | -| [provisioned\_auth\_configuration](#input\_provisioned\_auth\_configuration) | Configurations for provisioned Redshift query engine |
object({
database_user = optional(string)
type = optional(string) # Auth type explicitly defined
username_password_secret_arn = optional(string)
})
| `null` | no | +| [provisioned\_auth\_configuration](#input\_provisioned\_auth\_configuration) | Configurations for provisioned Redshift query engine |
object({
database_user = optional(string)
type = optional(string) # Auth type explicitly defined
username_password_secret_arn = optional(string)
})
| `null` | no | | [provisioned\_config\_cluster\_identifier](#input\_provisioned\_config\_cluster\_identifier) | The cluster identifier for the provisioned Redshift query engine. | `string` | `null` | no | -| [query\_generation\_configuration](#input\_query\_generation\_configuration) | Configurations for generating Redshift engine queries. |
object({
generation_context = optional(object({
curated_queries = optional(list(object({
natural_language = optional(string) # Question for the query
sql = optional(string) # SQL answer for the query
})))
tables = optional(list(object({
columns = optional(list(object({
description = optional(string) # Column description
inclusion = optional(string) # Include or exclude status
name = optional(string) # Column name
})))
description = optional(string) # Table description
inclusion = optional(string) # Include or exclude status
name = optional(string) # Table name (three-part notation)
})))
}))
execution_timeout_seconds = optional(number) # Max query execution timeout
})
| `null` | no | +| [query\_generation\_configuration](#input\_query\_generation\_configuration) | Configurations for generating Redshift engine queries. |
object({
generation_context = optional(object({
curated_queries = optional(list(object({
natural_language = optional(string) # Question for the query
sql = optional(string) # SQL answer for the query
})))
tables = optional(list(object({
columns = optional(list(object({
description = optional(string) # Column description
inclusion = optional(string) # Include or exclude status
name = optional(string) # Column name
})))
description = optional(string) # Table description
inclusion = optional(string) # Include or exclude status
name = optional(string) # Table name (three-part notation)
})))
}))
execution_timeout_seconds = optional(number) # Max query execution timeout
})
| `null` | no | | [rate\_limit](#input\_rate\_limit) | Rate of web URLs retrieved per minute. | `number` | `null` | no | | [redshift\_query\_engine\_type](#input\_redshift\_query\_engine\_type) | Redshift query engine type for the knowledge base. Defaults to SERVERLESS | `string` | `"SERVERLESS"` | no | -| [redshift\_storage\_configuration](#input\_redshift\_storage\_configuration) | List of configurations for available Redshift query engine storage types. |
list(object({
aws_data_catalog_configuration = optional(object({
table_names = optional(list(string)) # List of table names in AWS Data Catalog
}))
redshift_configuration = optional(object({
database_name = optional(string)
}))
type = optional(string)
}))
| `null` | no | -| [regexes\_config](#input\_regexes\_config) | List of regex. | `list(map(string))` | `null` | no | +| [redshift\_storage\_configuration](#input\_redshift\_storage\_configuration) | List of configurations for available Redshift query engine storage types. |
list(object({
aws_data_catalog_configuration = optional(object({
table_names = optional(list(string)) # List of table names in AWS Data Catalog
}))
redshift_configuration = optional(object({
database_name = optional(string)
}))
type = optional(string)
}))
| `null` | no | +| [regexes\_config](#input\_regexes\_config) | List of regex patterns for sensitive information policy. |
list(object({
action = optional(string)
description = optional(string)
input_action = optional(string)
input_enabled = optional(bool)
name = optional(string)
output_action = optional(string)
output_enabled = optional(bool)
pattern = optional(string)
}))
| `null` | no | | [relay\_conversation\_history](#input\_relay\_conversation\_history) | Relay conversation history setting will share conversation history to collaborator if enabled. | `string` | `"TO_COLLABORATOR"` | no | | [resource\_arn](#input\_resource\_arn) | The ARN of the vector store. | `string` | `null` | no | | [s3\_data\_source\_bucket\_name](#input\_s3\_data\_source\_bucket\_name) | The name of the S3 bucket where the data source is stored. | `string` | `null` | no | @@ -922,7 +941,7 @@ See the additional input variables for deploying BDA projects and blueprints [he | [seed\_urls](#input\_seed\_urls) | A list of web urls. | `list(object({ url = string }))` | `[]` | no | | [semantic\_buffer\_size](#input\_semantic\_buffer\_size) | The buffer size. | `number` | `null` | no | | [semantic\_max\_tokens](#input\_semantic\_max\_tokens) | The maximum number of tokens that a chunk can contain. | `number` | `null` | no | -| [serverless\_auth\_configuration](#input\_serverless\_auth\_configuration) | Configuration for the Redshift serverless query engine. |
object({
type = optional(string) # Auth type explicitly defined
username_password_secret_arn = optional(string)
})
| `null` | no | +| [serverless\_auth\_configuration](#input\_serverless\_auth\_configuration) | Configuration for the Redshift serverless query engine. |
object({
type = optional(string) # Auth type explicitly defined
username_password_secret_arn = optional(string)
})
| `null` | no | | [share\_point\_credentials\_secret\_arn](#input\_share\_point\_credentials\_secret\_arn) | The ARN of an AWS Secrets Manager secret that stores your authentication credentials for your SharePoint site/sites. | `string` | `null` | no | | [share\_point\_domain](#input\_share\_point\_domain) | The domain of your SharePoint instance or site URL/URLs. | `string` | `null` | no | | [share\_point\_site\_urls](#input\_share\_point\_site\_urls) | A list of one or more SharePoint site URLs. | `list(string)` | `[]` | no | @@ -946,7 +965,7 @@ See the additional input variables for deploying BDA projects and blueprints [he | [text\_index\_name](#input\_text\_index\_name) | Name of a MongoDB Atlas text index. | `string` | `null` | no | | [top\_k](#input\_top\_k) | Sample from the k most likely next tokens. | `number` | `50` | no | | [top\_p](#input\_top\_p) | Cumulative probability cutoff for token selection. | `number` | `0.5` | no | -| [topics\_config](#input\_topics\_config) | List of topic configs in topic policy |
list(object({
name = string
examples = list(string)
type = string
definition = string
}))
| `null` | no | +| [topics\_config](#input\_topics\_config) | List of topic configs in topic policy. |
list(object({
definition = optional(string)
examples = optional(list(string))
input_action = optional(string)
input_enabled = optional(bool)
name = optional(string)
output_action = optional(string)
output_enabled = optional(bool)
type = optional(string)
}))
| `null` | no | | [topics\_tier\_config](#input\_topics\_tier\_config) | Guardrail tier config for topic policy. |
object({
tier_name = optional(string)
})
| `null` | no | | [transformations\_list](#input\_transformations\_list) | A list of Lambda functions that process documents. |
list(object({
step_to_apply = optional(string)
transformation_function = optional(object({
transformation_lambda_configuration = optional(object({
lambda_arn = optional(string)
}))
}))
}))
| `null` | no | | [use\_app\_inference\_profile](#input\_use\_app\_inference\_profile) | Whether or not to attach to the app\_inference\_profile\_model\_source. | `bool` | `false` | no | @@ -954,11 +973,11 @@ See the additional input variables for deploying BDA projects and blueprints [he | [use\_existing\_s3\_data\_source](#input\_use\_existing\_s3\_data\_source) | Whether or not to use an existing S3 data source. | `bool` | `false` | no | | [user\_agent](#input\_user\_agent) | The suffix that will be included in the user agent header for web crawling. | `string` | `null` | no | | [user\_token\_configurations](#input\_user\_token\_configurations) | List of user token configurations for Kendra. |
list(object({

json_token_type_configurations = optional(object({
group_attribute_field = string
user_name_attribute_field = string
}))

jwt_token_type_configuration = optional(object({
claim_regex = optional(string)
key_location = optional(string)
group_attribute_field = optional(string)
user_name_attribute_field = optional(string)
issuer = optional(string)
secret_manager_arn = optional(string)
url = optional(string)
}))

}))
| `null` | no | -| [variants\_list](#input\_variants\_list) | List of prompt variants. |
list(object({
name = optional(string)
template_type = optional(string)
model_id = optional(string)
additional_model_request_fields = optional(string)
metadata = optional(list(object({
key = optional(string)
value = optional(string)
})))
gen_ai_resource = optional(object({
agent = optional(object({
agent_identifier = optional(string)
}))
}))

inference_configuration = optional(object({
text = optional(object({
max_tokens = optional(number)
stop_sequences = optional(list(string))
temperature = optional(number)
top_p = optional(number)
top_k = optional(number)
}))
}))

template_configuration = optional(object({
chat = optional(object({
input_variables = optional(list(object({
name = optional(string)
})))
messages = optional(list(object({
content = optional(list(object({
cache_point = optional(object({
type = optional(string)
}))
text = optional(string)
})))
role = optional(string)
})))
system = optional(list(object({
cache_point = optional(object({
type = optional(string)
}))
text = optional(string)
})))
tool_configuration = optional(object({
tool_choice = optional(object({
any = optional(string)
auto = optional(string)
tool = optional(object({
name = optional(string)
}))
}))
tools = optional(list(object({
cache_point = optional(object({
type = optional(string)
}))
tool_spec = optional(object({
description = optional(string)
input_schema = optional(object({
json = optional(string)
}))
name = optional(string)
}))
})))
}))
})),

text = optional(object({
input_variables = optional(list(object({ name = optional(string) })))
text = optional(string)
cache_point = optional(object({
type = optional(string)
}))
text_s3_location = optional(object({
bucket = optional(string)
key = optional(string)
version = optional(string)
}))
}))
}))
}))
| `null` | no | +| [variants\_list](#input\_variants\_list) | List of prompt variants. |
list(object({
name = optional(string)
template_type = optional(string)
model_id = optional(string)
additional_model_request_fields = optional(string)
metadata = optional(list(object({
key = optional(string)
value = optional(string)
})))
gen_ai_resource = optional(object({
agent = optional(object({
agent_identifier = optional(string)
}))
}))

inference_configuration = optional(object({
text = optional(object({
max_tokens = optional(number)
stop_sequences = optional(list(string))
temperature = optional(number)
top_p = optional(number)
top_k = optional(number)
}))
}))

template_configuration = optional(object({
chat = optional(object({
input_variables = optional(list(object({
name = optional(string)
})))
messages = optional(list(object({
content = optional(list(object({
cache_point = optional(object({
type = optional(string)
}))
text = optional(string)
})))
role = optional(string)
})))
system = optional(list(object({
cache_point = optional(object({
type = optional(string)
}))
text = optional(string)
})))
tool_configuration = optional(object({
tool_choice = optional(object({
any = optional(string)
auto = optional(string)
tool = optional(object({
name = optional(string)
}))
}))
tools = optional(list(object({
cache_point = optional(object({
type = optional(string)
}))
tool_spec = optional(object({
description = optional(string)
input_schema = optional(object({
json = optional(string)
}))
name = optional(string)
}))
})))
}))
})),

text = optional(object({
input_variables = optional(list(object({ name = optional(string) })))
text = optional(string)
cache_point = optional(object({
type = optional(string)
}))
text_s3_location = optional(object({
bucket = optional(string)
key = optional(string)
version = optional(string)
}))
}))
}))
}))
| `null` | no | | [vector\_dimension](#input\_vector\_dimension) | The dimension of vectors in the OpenSearch index. Use 1024 for Titan Text Embeddings V2, 1536 for V1 | `number` | `1024` | no | | [vector\_field](#input\_vector\_field) | The name of the field where the vector embeddings are stored | `string` | `"bedrock-knowledge-base-default-vector"` | no | | [vector\_index\_name](#input\_vector\_index\_name) | The name of the vector index. | `string` | `"bedrock-knowledge-base-default-index"` | no | -| [words\_config](#input\_words\_config) | List of custom word configs. | `list(map(string))` | `null` | no | +| [words\_config](#input\_words\_config) | List of custom word configs in word policy. |
list(object({
input_action = optional(string)
input_enabled = optional(bool)
output_action = optional(string)
output_enabled = optional(bool)
text = optional(string)
}))
| `null` | no | ## Outputs diff --git a/bda.tf b/bda.tf index 4ad12d3..a437664 100644 --- a/bda.tf +++ b/bda.tf @@ -1,29 +1,29 @@ resource "awscc_bedrock_data_automation_project" "bda_project" { - count = var.create_bda ? 1 : 0 - project_name = "${random_string.solution_prefix.result}-${var.bda_project_name}" - project_description = var.bda_project_description - kms_encryption_context = var.bda_kms_encryption_context - kms_key_id = var.bda_kms_key_id - tags = var.bda_tags - standard_output_configuration = var.bda_standard_output_configuration - custom_output_configuration = { - blueprints = var.bda_custom_output_config - } - override_configuration = { - document = { - splitter = { - state = var.bda_override_config_state - } - } + count = var.create_bda ? 1 : 0 + project_name = "${random_string.solution_prefix.result}-${var.bda_project_name}" + project_description = var.bda_project_description + kms_encryption_context = var.bda_kms_encryption_context + kms_key_id = var.bda_kms_key_id + tags = var.bda_tags + standard_output_configuration = var.bda_standard_output_configuration + custom_output_configuration = { + blueprints = var.bda_custom_output_config + } + override_configuration = { + document = { + splitter = { + state = var.bda_override_config_state + } } + } } resource "awscc_bedrock_blueprint" "bda_blueprint" { - count = var.create_blueprint ? 1 : 0 - blueprint_name = "${random_string.solution_prefix.result}-${var.blueprint_name}" - schema = var.blueprint_schema - type = var.blueprint_type - kms_encryption_context = var.blueprint_kms_encryption_context - kms_key_id = var.blueprint_kms_key_id - tags = var.blueprint_tags + count = var.create_blueprint ? 1 : 0 + blueprint_name = "${random_string.solution_prefix.result}-${var.blueprint_name}" + schema = var.blueprint_schema + type = var.blueprint_type + kms_encryption_context = var.blueprint_kms_encryption_context + kms_key_id = var.blueprint_kms_key_id + tags = var.blueprint_tags } \ No newline at end of file diff --git a/data-source.tf b/data-source.tf index bdbc655..a05511d 100644 --- a/data-source.tf +++ b/data-source.tf @@ -5,17 +5,17 @@ locals { chunking_configuration = var.chunking_strategy == null ? null : { chunking_strategy = var.chunking_strategy fixed_size_chunking_configuration = var.chunking_strategy_max_tokens == null ? null : { - max_tokens = var.chunking_strategy_max_tokens + max_tokens = var.chunking_strategy_max_tokens overlap_percentage = var.chunking_strategy_overlap_percentage } hierarchical_chunking_configuration = var.heirarchical_overlap_tokens == null && var.level_configurations_list == null ? null : { level_configurations = var.level_configurations_list - overlap_tokens = var.heirarchical_overlap_tokens + overlap_tokens = var.heirarchical_overlap_tokens } semantic_chunking_configuration = var.breakpoint_percentile_threshold == null && var.semantic_buffer_size == null && var.semantic_max_tokens == null ? null : { breakpoint_percentile_threshold = var.breakpoint_percentile_threshold - buffer_size = var.semantic_buffer_size - max_tokens = var.semantic_max_tokens + buffer_size = var.semantic_buffer_size + max_tokens = var.semantic_max_tokens } } context_enrichment_configuration = var.create_context_enrichment_config == false ? null : { @@ -49,7 +49,7 @@ locals { parsing_strategy = var.parsing_strategy } } - + server_side_encryption_configuration = var.create_server_side_encryption_config == false ? null : { kms_key_arn = var.data_source_kms_key_arn } @@ -92,12 +92,12 @@ resource "awscc_bedrock_data_source" "knowledge_base_ds" { data_source_configuration = { type = "S3" s3_configuration = { - bucket_arn = var.kb_s3_data_source == null ? awscc_s3_bucket.s3_data_source[0].arn : var.kb_s3_data_source # Create an S3 bucket or reference existing + bucket_arn = var.kb_s3_data_source == null ? awscc_s3_bucket.s3_data_source[0].arn : var.kb_s3_data_source # Create an S3 bucket or reference existing bucket_owner_account_id = var.bucket_owner_account_id - inclusion_prefixes = var.s3_inclusion_prefixes + inclusion_prefixes = var.s3_inclusion_prefixes } } - vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration + vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration server_side_encryption_configuration = local.server_side_encryption_configuration } @@ -163,7 +163,7 @@ resource "awscc_bedrock_data_source" "knowledge_base_web_crawler" { } } } - vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration + vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration server_side_encryption_configuration = local.server_side_encryption_configuration } @@ -176,23 +176,23 @@ resource "awscc_bedrock_data_source" "knowledge_base_confluence" { data_source_configuration = { type = "CONFLUENCE" confluence_configuration = { - crawler_configuration = { - filter_configuration = { - pattern_object_filter = { - filters = var.pattern_object_filter_list - } - type = var.crawl_filter_type - } - } - source_configuration = { - auth_type = var.auth_type - credentials_secret_arn = var.confluence_credentials_secret_arn - host_type = var.host_type - host_url = var.host_url + crawler_configuration = { + filter_configuration = { + pattern_object_filter = { + filters = var.pattern_object_filter_list + } + type = var.crawl_filter_type } + } + source_configuration = { + auth_type = var.auth_type + credentials_secret_arn = var.confluence_credentials_secret_arn + host_type = var.host_type + host_url = var.host_url + } } } - vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration + vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration server_side_encryption_configuration = local.server_side_encryption_configuration } @@ -204,26 +204,26 @@ resource "awscc_bedrock_data_source" "knowledge_base_sharepoint" { description = var.data_source_description data_source_configuration = { type = "SHAREPOINT" - share_point_configuration = { - crawler_configuration = { - filter_configuration = { - pattern_object_filter ={ - filters = var.pattern_object_filter_list - } - type = var.crawl_filter_type - } - } - source_configuration = { - auth_type = var.auth_type - credentials_secret_arn = var.share_point_credentials_secret_arn - domain = var.share_point_domain - host_type = var.host_type - site_urls = var.share_point_site_urls - tenant_id = var.tenant_id + share_point_configuration = { + crawler_configuration = { + filter_configuration = { + pattern_object_filter = { + filters = var.pattern_object_filter_list + } + type = var.crawl_filter_type } + } + source_configuration = { + auth_type = var.auth_type + credentials_secret_arn = var.share_point_credentials_secret_arn + domain = var.share_point_domain + host_type = var.host_type + site_urls = var.share_point_site_urls + tenant_id = var.tenant_id + } } } - vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration + vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration server_side_encryption_configuration = local.server_side_encryption_configuration } @@ -236,21 +236,21 @@ resource "awscc_bedrock_data_source" "knowledge_base_salesforce" { data_source_configuration = { type = "SALESFORCE" salesforce_configuration = { - crawler_configuration = { - filter_configuration = { - pattern_object_filter = { - filters = var.pattern_object_filter_list - } - type = var.crawl_filter_type - } - } - source_configuration = { - auth_type = var.auth_type - credentials_secret_arn = var.salesforce_credentials_secret_arn - host_url = var.host_url + crawler_configuration = { + filter_configuration = { + pattern_object_filter = { + filters = var.pattern_object_filter_list + } + type = var.crawl_filter_type } + } + source_configuration = { + auth_type = var.auth_type + credentials_secret_arn = var.salesforce_credentials_secret_arn + host_url = var.host_url + } } } - vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration + vector_ingestion_configuration = var.create_vector_ingestion_configuration == false ? null : local.vector_ingestion_configuration server_side_encryption_configuration = local.server_side_encryption_configuration } diff --git a/data.tf b/data.tf index b4a8c06..075ae6a 100644 --- a/data.tf +++ b/data.tf @@ -3,10 +3,10 @@ data "aws_partition" "current" {} data "aws_region" "current" {} locals { - region = data.aws_region.current.region - account_id = data.aws_caller_identity.current.account_id - partition = data.aws_partition.current.partition - create_kb = var.create_default_kb || var.create_rds_config || var.create_mongo_config || var.create_pinecone_config || var.create_opensearch_config || var.create_opensearch_managed_config || var.create_kb || var.create_kendra_config + region = data.aws_region.current.region + account_id = data.aws_caller_identity.current.account_id + partition = data.aws_partition.current.partition + create_kb = var.create_default_kb || var.create_rds_config || var.create_mongo_config || var.create_pinecone_config || var.create_opensearch_config || var.create_opensearch_managed_config || var.create_kb || var.create_kendra_config foundation_model = var.create_agent ? var.foundation_model : (var.create_supervisor ? var.supervisor_model : null) } @@ -47,18 +47,18 @@ data "aws_iam_policy_document" "agent_permissions" { "arn:aws:bedrock:*:*:application-inference-profile/*", ] : [], var.create_app_inference_profile ? [ - var.app_inference_profile_model_source, - awscc_bedrock_application_inference_profile.application_inference_profile[0].inference_profile_arn, - "arn:${local.partition}:bedrock:*:*:application-inference-profile/*", + var.app_inference_profile_model_source, + awscc_bedrock_application_inference_profile.application_inference_profile[0].inference_profile_arn, + "arn:${local.partition}:bedrock:*:*:application-inference-profile/*", ] : [], - var.create_app_inference_profile ? - awscc_bedrock_application_inference_profile.application_inference_profile[0].models[*].model_arn : [], - !var.create_app_inference_profile && !var.use_app_inference_profile ? + var.create_app_inference_profile ? + awscc_bedrock_application_inference_profile.application_inference_profile[0].models[*].model_arn : [], + !var.create_app_inference_profile && !var.use_app_inference_profile ? [ - "arn:${local.partition}:bedrock:${local.region}::foundation-model/${local.foundation_model}", - "arn:${local.partition}:bedrock:*::foundation-model/${local.foundation_model}", - "arn:${local.partition}:bedrock:${local.region}:${local.account_id}:inference-profile/*.${local.foundation_model}", - ]: [] + "arn:${local.partition}:bedrock:${local.region}::foundation-model/${local.foundation_model}", + "arn:${local.partition}:bedrock:*::foundation-model/${local.foundation_model}", + "arn:${local.partition}:bedrock:${local.region}:${local.account_id}:inference-profile/*.${local.foundation_model}", + ] : [] )) } } @@ -67,12 +67,12 @@ data "aws_iam_policy_document" "agent_alias_permissions" { count = var.create_agent_alias || var.create_supervisor ? 1 : 0 statement { actions = [ - "bedrock:GetAgentAlias", + "bedrock:GetAgentAlias", "bedrock:InvokeAgent" ] resources = [ "arn:${local.partition}:bedrock:${local.region}:${local.account_id}:agent/*", - "arn:${local.partition}:bedrock:${local.region}:${local.account_id}:agent-alias/*" + "arn:${local.partition}:bedrock:${local.region}:${local.account_id}:agent-alias/*" ] } } @@ -124,6 +124,6 @@ data "aws_iam_policy_document" "app_inference_profile_permission" { } data "aws_bedrock_foundation_model" "model_identifier" { - count = var.create_custom_model ? 1 : 0 + count = var.create_custom_model ? 1 : 0 model_id = var.custom_model_id } diff --git a/examples/agent-collaborator/main.tf b/examples/agent-collaborator/main.tf index 21d2e17..c277557 100644 --- a/examples/agent-collaborator/main.tf +++ b/examples/agent-collaborator/main.tf @@ -5,35 +5,35 @@ ##################################################################################### module "agent_supervisor" { - source = "../.." - create_agent = false - create_supervisor = true - supervisor_model = "anthropic.claude-3-5-sonnet-20241022-v2:0" - supervisor_instruction = "You are a supervisor who can provide detailed information about cars to an agent." + source = "../.." + create_agent = false + create_supervisor = true + supervisor_model = "anthropic.claude-3-5-sonnet-20241022-v2:0" + supervisor_instruction = "You are a supervisor who can provide detailed information about cars to an agent." } module "agent_collaborator1" { - source = "../.." - create_agent_alias = true - foundation_model = "anthropic.claude-v2" - instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." - supervisor_id = module.agent_supervisor.supervisor_id - create_collaborator = true - collaborator_name = "AgentA" - collaboration_instruction = "Handle customer inquiries" + source = "../.." + create_agent_alias = true + foundation_model = "anthropic.claude-v2" + instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." + supervisor_id = module.agent_supervisor.supervisor_id + create_collaborator = true + collaborator_name = "AgentA" + collaboration_instruction = "Handle customer inquiries" depends_on = [module.agent_supervisor] } module "agent_collaborator2" { - source = "../.." - create_agent_alias = true - foundation_model = "anthropic.claude-v2" - instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." - supervisor_id = module.agent_supervisor.supervisor_id - create_collaborator = true - collaborator_name = "AgentB" - collaboration_instruction = "Process backend tasks" + source = "../.." + create_agent_alias = true + foundation_model = "anthropic.claude-v2" + instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." + supervisor_id = module.agent_supervisor.supervisor_id + create_collaborator = true + collaborator_name = "AgentB" + collaboration_instruction = "Process backend tasks" depends_on = [module.agent_supervisor, module.agent_collaborator1] } \ No newline at end of file diff --git a/examples/agent-only/main.tf b/examples/agent-only/main.tf index c7a16fd..561d188 100644 --- a/examples/agent-only/main.tf +++ b/examples/agent-only/main.tf @@ -5,8 +5,8 @@ ##################################################################################### module "bedrock" { - source = "../.." # local example + source = "../.." # local example create_agent_alias = true - foundation_model = "anthropic.claude-v2" - instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." + foundation_model = "anthropic.claude-v2" + instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." } \ No newline at end of file diff --git a/examples/agent-with-guardrails/main.tf b/examples/agent-with-guardrails/main.tf index c8f8efb..88299ca 100644 --- a/examples/agent-with-guardrails/main.tf +++ b/examples/agent-with-guardrails/main.tf @@ -5,52 +5,70 @@ ##################################################################################### module "bedrock" { - source = "../.." # local example + source = "../.." # local example create_guardrail = true filters_config = [ - { - input_strength = "MEDIUM" - output_strength = "MEDIUM" - type = "HATE" - }, - { - input_strength = "HIGH" - output_strength = "HIGH" - type = "VIOLENCE" - } + { + input_strength = "MEDIUM" + output_strength = "MEDIUM" + type = "HATE" + input_modalities = ["TEXT"] + output_modalities = ["TEXT"] + }, + { + input_strength = "HIGH" + output_strength = "HIGH" + type = "VIOLENCE" + input_modalities = ["TEXT", "IMAGE"] + output_modalities = ["TEXT", "IMAGE"] + }, + { + input_strength = "HIGH" + output_strength = "HIGH" + type = "MISCONDUCT" + input_modalities = ["IMAGE"] + output_modalities = ["IMAGE"] + }, + { + input_strength = "MEDIUM" + output_strength = "MEDIUM" + type = "SEXUAL" + input_modalities = ["IMAGE"] + output_modalities = ["IMAGE"] + } ] pii_entities_config = [ - { - action = "BLOCK" - type = "NAME" - }, - { - action = "BLOCK" - type = "DRIVER_ID" - }, - { - action = "ANONYMIZE" - type = "USERNAME" - }, + { + action = "BLOCK" + type = "NAME" + }, + { + action = "BLOCK" + type = "DRIVER_ID" + }, + { + action = "ANONYMIZE" + type = "USERNAME" + }, ] regexes_config = [{ - action = "BLOCK" - description = "example regex" - name = "regex_example" - pattern = "^\\d{3}-\\d{2}-\\d{4}$" + action = "BLOCK" + description = "example regex" + name = "regex_example" + pattern = "^\\d{3}-\\d{2}-\\d{4}$" }] managed_word_lists_config = [{ - type = "PROFANITY" + type = "PROFANITY" }] words_config = [{ text = "HATE" }] topics_config = [{ - name = "investment_topic" - examples = ["Where should I invest my money ?"] - type = "DENY" - definition = "Investment advice refers to inquiries, guidance, or recommendations regarding the management or allocation of funds or assets with the goal of generating returns ." + name = "investment_topic" + examples = ["Where should I invest my money ?"] + type = "DENY" + definition = "Investment advice refers to inquiries, guidance, or recommendations regarding the management or allocation of funds or assets with the goal of generating returns ." }] foundation_model = "anthropic.claude-v2" - instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." + instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." } \ No newline at end of file diff --git a/examples/agent-with-inference-profile/main.tf b/examples/agent-with-inference-profile/main.tf index d3a1f48..34db7be 100644 --- a/examples/agent-with-inference-profile/main.tf +++ b/examples/agent-with-inference-profile/main.tf @@ -11,22 +11,22 @@ data "aws_caller_identity" "current" {} data "aws_region" "current" {} locals { - region = data.aws_region.current.name + region = data.aws_region.current.name account_id = data.aws_caller_identity.current.account_id } module "agent_supervisor" { source = "../.." - - create_agent = false + + create_agent = false create_supervisor = true - supervisor_name = "SupervisorTF" + supervisor_name = "SupervisorTF" - create_app_inference_profile = true - app_inference_profile_name = "Claude37SonnetProfile" - app_inference_profile_description = "Inference profile for Claude 3.7 Sonnet" + create_app_inference_profile = true + app_inference_profile_name = "Claude37SonnetProfile" + app_inference_profile_description = "Inference profile for Claude 3.7 Sonnet" app_inference_profile_model_source = "arn:aws:bedrock:${local.region}:${local.account_id}:inference-profile/us.anthropic.claude-3-7-sonnet-20250219-v1:0" - + supervisor_instruction = "You are a supervisor who can provide detailed information about cars and trucks to an agent. You can also provide feedback to the agent." - + } diff --git a/examples/agent-with-knowledge-base/main.tf b/examples/agent-with-knowledge-base/main.tf index 67b10c7..1be4a2a 100644 --- a/examples/agent-with-knowledge-base/main.tf +++ b/examples/agent-with-knowledge-base/main.tf @@ -5,9 +5,9 @@ ##################################################################################### module "bedrock" { - source = "../.." # local example - create_default_kb = true + source = "../.." # local example + create_default_kb = true create_s3_data_source = true - foundation_model = "anthropic.claude-v2" - instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." + foundation_model = "anthropic.claude-v2" + instruction = "You are an automotive assisant who can provide detailed information about cars to a customer." } \ No newline at end of file diff --git a/examples/agent-with-knowledge-base/providers.tf b/examples/agent-with-knowledge-base/providers.tf index 9dc1906..b8f353f 100644 --- a/examples/agent-with-knowledge-base/providers.tf +++ b/examples/agent-with-knowledge-base/providers.tf @@ -39,6 +39,6 @@ provider "awscc" { } provider "opensearch" { - url = module.bedrock.default_collection.collection_endpoint + url = module.bedrock.default_collection.collection_endpoint healthcheck = false } \ No newline at end of file diff --git a/examples/application-inference-profile/main.tf b/examples/application-inference-profile/main.tf index 260c583..a02a9a2 100644 --- a/examples/application-inference-profile/main.tf +++ b/examples/application-inference-profile/main.tf @@ -11,10 +11,10 @@ data "aws_caller_identity" "current" {} data "aws_region" "current" {} module "bedrock" { - source = "../.." # local example + source = "../.." # local example create_agent = false # Application Inference Profile - create_app_inference_profile = true + create_app_inference_profile = true app_inference_profile_model_source = "arn:aws:bedrock:${data.aws_region.current.name}::foundation-model/anthropic.claude-3-sonnet-20240229-v1:0" } \ No newline at end of file diff --git a/examples/bda/main.tf b/examples/bda/main.tf index 21f3238..aa09b96 100644 --- a/examples/bda/main.tf +++ b/examples/bda/main.tf @@ -28,8 +28,8 @@ module "bda" { } } bda_custom_output_config = [{ - blueprint_arn = module.blueprint.bda_blueprint.blueprint_arn - blueprint_stage = module.blueprint.bda_blueprint.blueprint_stage + blueprint_arn = module.blueprint.bda_blueprint.blueprint_arn + blueprint_stage = module.blueprint.bda_blueprint.blueprint_stage }] } diff --git a/examples/kendra-kb/main.tf b/examples/kendra-kb/main.tf index 4688a17..d434e0d 100644 --- a/examples/kendra-kb/main.tf +++ b/examples/kendra-kb/main.tf @@ -5,8 +5,8 @@ ##################################################################################### module "bedrock" { - source = "../.." # local example - create_kendra_config = true + source = "../.." # local example + create_kendra_config = true create_kendra_s3_data_source = true - create_agent = false + create_agent = false } \ No newline at end of file diff --git a/examples/kendra-kb/providers.tf b/examples/kendra-kb/providers.tf index f3dbd41..51119a5 100644 --- a/examples/kendra-kb/providers.tf +++ b/examples/kendra-kb/providers.tf @@ -39,6 +39,6 @@ provider "awscc" { } provider "opensearch" { - url = "n/a" + url = "n/a" healthcheck = false } \ No newline at end of file diff --git a/examples/knowledge-base-only/main.tf b/examples/knowledge-base-only/main.tf index 7cb5fa3..5e60025 100644 --- a/examples/knowledge-base-only/main.tf +++ b/examples/knowledge-base-only/main.tf @@ -5,8 +5,8 @@ ##################################################################################### module "bedrock" { - source = "../.." # local example - create_default_kb = true - create_agent = false + source = "../.." # local example + create_default_kb = true + create_agent = false create_s3_data_source = true } \ No newline at end of file diff --git a/examples/knowledge-base-only/providers.tf b/examples/knowledge-base-only/providers.tf index fc5b1a9..b8f353f 100644 --- a/examples/knowledge-base-only/providers.tf +++ b/examples/knowledge-base-only/providers.tf @@ -39,6 +39,6 @@ provider "awscc" { } provider "opensearch" { - url = module.bedrock.default_collection.collection_endpoint + url = module.bedrock.default_collection.collection_endpoint healthcheck = false } \ No newline at end of file diff --git a/examples/prompt-management/main.tf b/examples/prompt-management/main.tf index ff236bc..298d006 100644 --- a/examples/prompt-management/main.tf +++ b/examples/prompt-management/main.tf @@ -5,14 +5,14 @@ ##################################################################################### module "bedrock" { - source = "../.." # local example + source = "../.." # local example create_agent = false # Prompt Management - prompt_name = "prompt" - default_variant = "variant-example" - create_prompt = true - create_prompt_version = true + prompt_name = "prompt" + default_variant = "variant-example" + create_prompt = true + create_prompt_version = true prompt_version_description = "Example prompt version" variants_list = [ { @@ -41,5 +41,5 @@ module "bedrock" { } ] - + } \ No newline at end of file diff --git a/iam.tf b/iam.tf index 4b0fe20..20b54de 100644 --- a/iam.tf +++ b/iam.tf @@ -1,18 +1,18 @@ # – IAM – locals { - create_kb_role = var.kb_role_arn == null && local.create_kb - kendra_index_id = var.create_kendra_config == true ? (var.kendra_index_id != null ? var.kendra_index_id : awscc_kendra_index.genai_kendra_index[0].id) : null + create_kb_role = var.kb_role_arn == null && local.create_kb + kendra_index_id = var.create_kendra_config == true ? (var.kendra_index_id != null ? var.kendra_index_id : awscc_kendra_index.genai_kendra_index[0].id) : null kendra_data_source_bucket_arn = var.create_kendra_s3_data_source ? (var.kb_s3_data_source != null ? var.kb_s3_data_source : awscc_s3_bucket.s3_data_source[0].arn) : null - action_group_names = concat(var.action_group_lambda_names_list, [var.lambda_action_group_executor]) - agent_role_name = var.agent_resource_role_arn != null ? split("/", var.agent_resource_role_arn)[1] : ((var.create_agent || var.create_supervisor) ? aws_iam_role.agent_role[0].name : null) - kb_embedding_model_arn = replace(replace(var.kb_embedding_model_arn, "arn:aws", "arn:${local.partition}"), "us-east-1", local.region) + action_group_names = concat(var.action_group_lambda_names_list, [var.lambda_action_group_executor]) + agent_role_name = var.agent_resource_role_arn != null ? split("/", var.agent_resource_role_arn)[1] : ((var.create_agent || var.create_supervisor) ? aws_iam_role.agent_role[0].name : null) + kb_embedding_model_arn = replace(replace(var.kb_embedding_model_arn, "arn:aws", "arn:${local.partition}"), "us-east-1", local.region) } resource "aws_iam_role" "agent_role" { - count = var.agent_resource_role_arn == null && (var.create_agent || var.create_supervisor) ? 1 : 0 - assume_role_policy = data.aws_iam_policy_document.agent_trust[0].json - name_prefix = var.name_prefix - permissions_boundary = var.permissions_boundary_arn + count = var.agent_resource_role_arn == null && (var.create_agent || var.create_supervisor) ? 1 : 0 + assume_role_policy = data.aws_iam_policy_document.agent_trust[0].json + name_prefix = var.name_prefix + permissions_boundary = var.permissions_boundary_arn } resource "aws_iam_role_policy" "agent_policy" { @@ -56,7 +56,7 @@ resource "aws_iam_role" "bedrock_knowledge_base_role" { } ] }) - permissions_boundary = var.permissions_boundary_arn + permissions_boundary = var.permissions_boundary_arn } # Attach a policy to allow necessary permissions for the Bedrock Knowledge Base @@ -207,19 +207,19 @@ resource "aws_iam_role_policy" "bedrock_kb_oss" { resource "aws_iam_policy" "bedrock_kb_opensearch_managed" { count = var.kb_role_arn != null || var.create_opensearch_managed_config == false ? 0 : 1 name = "AmazonBedrockOpenSearchManagedPolicyForKnowledgeBase_${var.kb_name}" - + policy = jsonencode({ Version = "2012-10-17" Statement = [ { - Action = [ + Action = [ "es:ESHttpGet", "es:ESHttpPost", "es:ESHttpPut", "es:ESHttpDelete", "es:DescribeDomain" ] - Effect = "Allow" + Effect = "Allow" Resource = [ var.domain_arn, "${var.domain_arn}/*" @@ -249,7 +249,7 @@ resource "aws_iam_role_policy" "guardrail_policy" { } resource "aws_iam_role_policy" "guardrail_policy_supervisor_agent" { - count = var.create_collaborator && var.create_supervisor_guardrail ? 1 : 0 + count = var.create_collaborator && var.create_supervisor_guardrail ? 1 : 0 policy = jsonencode({ Version = "2012-10-17" Statement = [ @@ -310,41 +310,41 @@ resource "aws_iam_role" "application_inference_profile_role" { } ] }) - permissions_boundary = var.permissions_boundary_arn + permissions_boundary = var.permissions_boundary_arn } resource "aws_iam_role_policy" "app_inference_profile_role_policy" { - count = var.create_app_inference_profile || var.use_app_inference_profile ? 1 : 0 + count = var.create_app_inference_profile || var.use_app_inference_profile ? 1 : 0 policy = jsonencode({ - "Version": "2012-10-17", - "Statement": [ - { - "Effect": "Allow", - "Action": [ - "bedrock:InvokeModel*", - "bedrock:CreateInferenceProfile" - ], - "Resource": [ - "arn:${local.partition}:bedrock:*::foundation-model/*", - "arn:${local.partition}:bedrock:*:*:inference-profile/*", - "arn:${local.partition}:bedrock:*:*:application-inference-profile/*" - ] - }, - { - "Effect": "Allow", - "Action": [ - "bedrock:GetInferenceProfile", - "bedrock:ListInferenceProfiles", - "bedrock:DeleteInferenceProfile", - "bedrock:TagResource", - "bedrock:UntagResource", - "bedrock:ListTagsForResource" - ], - "Resource": [ - "arn:${local.partition}:bedrock:*:*:inference-profile/*", - "arn:${local.partition}:bedrock:*:*:application-inference-profile/*" - ] - } + "Version" : "2012-10-17", + "Statement" : [ + { + "Effect" : "Allow", + "Action" : [ + "bedrock:InvokeModel*", + "bedrock:CreateInferenceProfile" + ], + "Resource" : [ + "arn:${local.partition}:bedrock:*::foundation-model/*", + "arn:${local.partition}:bedrock:*:*:inference-profile/*", + "arn:${local.partition}:bedrock:*:*:application-inference-profile/*" + ] + }, + { + "Effect" : "Allow", + "Action" : [ + "bedrock:GetInferenceProfile", + "bedrock:ListInferenceProfiles", + "bedrock:DeleteInferenceProfile", + "bedrock:TagResource", + "bedrock:UntagResource", + "bedrock:ListTagsForResource" + ], + "Resource" : [ + "arn:${local.partition}:bedrock:*:*:inference-profile/*", + "arn:${local.partition}:bedrock:*:*:application-inference-profile/*" + ] + } ] }) role = aws_iam_role.application_inference_profile_role[0].id @@ -353,63 +353,63 @@ resource "aws_iam_role_policy" "app_inference_profile_role_policy" { # Custom model resource "aws_iam_role" "custom_model_role" { - count = var.create_custom_model ? 1 : 0 - assume_role_policy = data.aws_iam_policy_document.custom_model_trust[0].json - permissions_boundary = var.permissions_boundary_arn - name_prefix = "CustomModelRole" + count = var.create_custom_model ? 1 : 0 + assume_role_policy = data.aws_iam_policy_document.custom_model_trust[0].json + permissions_boundary = var.permissions_boundary_arn + name_prefix = "CustomModelRole" } resource "aws_iam_role_policy" "custom_model_policy" { count = var.create_custom_model ? 1 : 0 policy = jsonencode({ - "Version": "2012-10-17", - "Statement": [ + "Version" : "2012-10-17", + "Statement" : [ { - "Effect": "Allow", - "Action": [ + "Effect" : "Allow", + "Action" : [ "s3:GetObject", "s3:PutObject", "s3:ListBucket", "kms:Decrypt" ], - "Resource": [ + "Resource" : [ "arn:${local.partition}:s3:::${var.custom_model_training_uri}", "arn:${local.partition}:s3:::${var.custom_model_training_uri}/*", ], - "Condition": { - "StringEquals": { - "aws:PrincipalAccount": local.account_id + "Condition" : { + "StringEquals" : { + "aws:PrincipalAccount" : local.account_id } } }, { - "Effect": "Allow", - "Action": [ + "Effect" : "Allow", + "Action" : [ "s3:GetObject", "s3:PutObject", "s3:ListBucket", "kms:Decrypt" ], - "Resource": var.custom_model_output_uri == null ? "arn:${local.partition}:s3:::${awscc_s3_bucket.custom_model_output[0].id}/" : "arn:${local.partition}:s3:::${var.custom_model_output_uri}", - - "Condition": { - "StringEquals": { - "aws:PrincipalAccount": local.account_id + "Resource" : var.custom_model_output_uri == null ? "arn:${local.partition}:s3:::${awscc_s3_bucket.custom_model_output[0].id}/" : "arn:${local.partition}:s3:::${var.custom_model_output_uri}", + + "Condition" : { + "StringEquals" : { + "aws:PrincipalAccount" : local.account_id } } }, { - "Effect": "Allow", - "Action": [ + "Effect" : "Allow", + "Action" : [ "s3:GetObject", "s3:PutObject", "s3:ListBucket", "kms:Decrypt" ], - "Resource": var.custom_model_output_uri == null ? "arn:${local.partition}:s3:::${awscc_s3_bucket.custom_model_output[0].id}/*" : "arn:${local.partition}:s3:::${var.custom_model_output_uri}/*", - "Condition": { - "StringEquals": { - "aws:PrincipalAccount": local.account_id + "Resource" : var.custom_model_output_uri == null ? "arn:${local.partition}:s3:::${awscc_s3_bucket.custom_model_output[0].id}/*" : "arn:${local.partition}:s3:::${var.custom_model_output_uri}/*", + "Condition" : { + "StringEquals" : { + "aws:PrincipalAccount" : local.account_id } } }, @@ -422,12 +422,12 @@ resource "aws_iam_role_policy" "custom_model_policy" { resource "aws_iam_policy" "bedrock_kb_kendra" { count = var.kb_role_arn != null || var.create_kendra_config == false ? 0 : 1 name = "AmazonBedrockKnowledgeBaseKendraIndexAccessStatement_${var.kendra_index_name}" - + policy = jsonencode({ "Version" = "2012-10-17" "Statement" = [ { - "Action" = [ + "Action" = [ "kendra:Retrieve", "kendra:DescribeIndex" ] @@ -514,8 +514,8 @@ resource "awscc_iam_role" "kendra_s3_datasource_role" { ] }) description = "IAM role for Kendra Data Source" - path = "/" - role_name = "kendra-datasource-role" + path = "/" + role_name = "kendra-datasource-role" policies = [ { @@ -529,19 +529,19 @@ resource "awscc_iam_role" "kendra_s3_datasource_role" { "s3:GetObject", "s3:ListBucket" ] - Resource = [ + Resource = [ local.kendra_data_source_bucket_arn, "${local.kendra_data_source_bucket_arn}/*" ] }, { - Effect: "Allow", - Action: [ - "kendra:BatchPutDocument", - "kendra:BatchDeleteDocument" + Effect : "Allow", + Action : [ + "kendra:BatchPutDocument", + "kendra:BatchDeleteDocument" ], - Resource: "arn:${local.partition}:kendra:${local.region}:${local.account_id}:index/${local.kendra_index_id}" - } + Resource : "arn:${local.partition}:kendra:${local.region}:${local.account_id}:index/${local.kendra_index_id}" + } ] }) } @@ -552,46 +552,46 @@ resource "awscc_iam_role" "kendra_s3_datasource_role" { resource "aws_iam_policy" "bedrock_kb_sql" { count = var.kb_role_arn != null || var.create_sql_config == false ? 0 : 1 name = "AmazonBedrockKnowledgeBaseRedshiftStatement_${var.kb_name}" - + policy = jsonencode({ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "RedshiftDataAPIStatementPermissions", - "Effect": "Allow", - "Action": [ - "redshift-data:GetStatementResult", - "redshift-data:DescribeStatement", - "redshift-data:CancelStatement" - ], - "Resource": [ - "*" - ], - "Condition": { - "StringEquals": { - "redshift-data:statement-owner-iam-userid": "$${aws:userid}" - } - } - }, - { - "Sid": "SqlWorkbenchAccess", - "Effect": "Allow", - "Action": [ - "sqlworkbench:GetSqlRecommendations", - "sqlworkbench:PutSqlGenerationContext", - "sqlworkbench:GetSqlGenerationContext", - "sqlworkbench:DeleteSqlGenerationContext" - ], - "Resource": "*" - }, - { - "Sid": "KbAccess", - "Effect": "Allow", - "Action": [ - "bedrock:GenerateQuery" - ], - "Resource": "*" + "Version" : "2012-10-17", + "Statement" : [ + { + "Sid" : "RedshiftDataAPIStatementPermissions", + "Effect" : "Allow", + "Action" : [ + "redshift-data:GetStatementResult", + "redshift-data:DescribeStatement", + "redshift-data:CancelStatement" + ], + "Resource" : [ + "*" + ], + "Condition" : { + "StringEquals" : { + "redshift-data:statement-owner-iam-userid" : "$${aws:userid}" } + } + }, + { + "Sid" : "SqlWorkbenchAccess", + "Effect" : "Allow", + "Action" : [ + "sqlworkbench:GetSqlRecommendations", + "sqlworkbench:PutSqlGenerationContext", + "sqlworkbench:GetSqlGenerationContext", + "sqlworkbench:DeleteSqlGenerationContext" + ], + "Resource" : "*" + }, + { + "Sid" : "KbAccess", + "Effect" : "Allow", + "Action" : [ + "bedrock:GenerateQuery" + ], + "Resource" : "*" + } ] }) } @@ -600,29 +600,29 @@ resource "aws_iam_policy" "bedrock_kb_sql" { resource "aws_iam_policy" "bedrock_kb_sql_serverless" { count = var.kb_role_arn != null || var.create_sql_config == false || var.redshift_query_engine_type != "SERVERLESS" ? 0 : 1 name = "AmazonBedrockKnowledgeBaseRedshiftServerlessStatement_${var.kb_name}" - + policy = jsonencode({ - "Version": "2012-10-17", - "Statement": [ - - { - "Sid": "RedshiftDataAPIExecutePermissions", - "Effect": "Allow", - "Action": [ - "redshift-data:ExecuteStatement" - ], - "Resource": [ - "arn:${local.partition}:redshift-serverless:${local.region}:${local.account_id}:workgroup:${split("/", var.sql_kb_workgroup_arn)[1]}" - ] - }, - { - "Sid": "RedshiftServerlessGetCredentials", - "Effect": "Allow", - "Action": "redshift-serverless:GetCredentials", - "Resource": [ - "arn:${local.partition}:redshift-serverless:${local.region}:${local.account_id}:workgroup:${split("/", var.sql_kb_workgroup_arn)[1]}" - ] - } + "Version" : "2012-10-17", + "Statement" : [ + + { + "Sid" : "RedshiftDataAPIExecutePermissions", + "Effect" : "Allow", + "Action" : [ + "redshift-data:ExecuteStatement" + ], + "Resource" : [ + "arn:${local.partition}:redshift-serverless:${local.region}:${local.account_id}:workgroup:${split("/", var.sql_kb_workgroup_arn)[1]}" + ] + }, + { + "Sid" : "RedshiftServerlessGetCredentials", + "Effect" : "Allow", + "Action" : "redshift-serverless:GetCredentials", + "Resource" : [ + "arn:${local.partition}:redshift-serverless:${local.region}:${local.account_id}:workgroup:${split("/", var.sql_kb_workgroup_arn)[1]}" + ] + } ] }) } @@ -631,28 +631,28 @@ resource "aws_iam_policy" "bedrock_kb_sql_serverless" { resource "aws_iam_policy" "bedrock_kb_sql_provisioned" { count = var.kb_role_arn != null || var.create_sql_config == false || var.redshift_query_engine_type != "PROVISIONED" ? 0 : 1 name = "AmazonBedrockKnowledgeBaseRedshiftProvisionedStatement_${var.kb_name}" - + policy = jsonencode({ - "Version": "2012-10-17", - "Statement": [ - { - "Sid": "RedshiftDataAPIExecutePermissions", - "Effect": "Allow", - "Action": [ - "redshift-data:ExecuteStatement" - ], - "Resource": [ - "arn:${local.partition}:redshift:${local.region}:${local.account_id}:cluster:${var.provisioned_config_cluster_identifier}" - ] - }, - { - "Sid": "GetCredentialsWithFederatedIAMCredentials", - "Effect": "Allow", - "Action": "redshift:GetClusterCredentialsWithIAM", - "Resource": [ - "arn:${local.partition}:redshift:${local.region}:${local.account_id}:dbname:${var.provisioned_config_cluster_identifier}/*" - ] - } + "Version" : "2012-10-17", + "Statement" : [ + { + "Sid" : "RedshiftDataAPIExecutePermissions", + "Effect" : "Allow", + "Action" : [ + "redshift-data:ExecuteStatement" + ], + "Resource" : [ + "arn:${local.partition}:redshift:${local.region}:${local.account_id}:cluster:${var.provisioned_config_cluster_identifier}" + ] + }, + { + "Sid" : "GetCredentialsWithFederatedIAMCredentials", + "Effect" : "Allow", + "Action" : "redshift:GetClusterCredentialsWithIAM", + "Resource" : [ + "arn:${local.partition}:redshift:${local.region}:${local.account_id}:dbname:${var.provisioned_config_cluster_identifier}/*" + ] + } ] }) } diff --git a/kendra.tf b/kendra.tf index 2bd24e0..5df4867 100644 --- a/kendra.tf +++ b/kendra.tf @@ -6,39 +6,39 @@ resource "awscc_kendra_index" "genai_kendra_index" { role_arn = awscc_iam_role.kendra_index_role[0].arn description = var.kendra_index_description capacity_units = { - query_capacity_units = var.kendra_index_query_capacity + query_capacity_units = var.kendra_index_query_capacity storage_capacity_units = var.kendra_index_storage_capacity } document_metadata_configurations = var.document_metadata_configurations server_side_encryption_configuration = var.kendra_kms_key_id != null ? { kms_key_id = var.kendra_kms_key_id } : null - user_context_policy = var.kendra_index_user_context_policy + user_context_policy = var.kendra_index_user_context_policy user_token_configurations = var.user_token_configurations - tags = var.kendra_index_tags + tags = var.kendra_index_tags } resource "time_sleep" "wait_after_kendra_index_creation" { count = var.create_kendra_config && var.kendra_index_arn == null ? 1 : 0 - depends_on = [ awscc_kendra_index.genai_kendra_index[0] ] + depends_on = [awscc_kendra_index.genai_kendra_index[0]] create_duration = "60s" # Wait for 60 seconds } # Create Kendra Data Source resource "awscc_kendra_data_source" "kendra_s3_data_source" { - count = var.create_kendra_s3_data_source == true ? 1 : 0 - index_id = var.kendra_index_arn != null ? var.kendra_index_arn : awscc_kendra_index.genai_kendra_index[0].id - name = "${random_string.solution_prefix.result}-${var.kendra_data_source_name}" - type = "S3" - role_arn = awscc_iam_role.kendra_s3_datasource_role[0].arn + count = var.create_kendra_s3_data_source == true ? 1 : 0 + index_id = var.kendra_index_arn != null ? var.kendra_index_arn : awscc_kendra_index.genai_kendra_index[0].id + name = "${random_string.solution_prefix.result}-${var.kendra_data_source_name}" + type = "S3" + role_arn = awscc_iam_role.kendra_s3_datasource_role[0].arn language_code = var.kendra_data_source_language_code - schedule = var.kendra_data_source_schedule - description = var.kendra_data_source_description - tags = var.kendra_data_source_tags + schedule = var.kendra_data_source_schedule + description = var.kendra_data_source_description + tags = var.kendra_data_source_tags data_source_configuration = { s3_configuration = { - bucket_name = var.s3_data_source_bucket_name != null ? var.s3_data_source_bucket_name : awscc_s3_bucket.s3_data_source[0].bucket_name + bucket_name = var.s3_data_source_bucket_name != null ? var.s3_data_source_bucket_name : awscc_s3_bucket.s3_data_source[0].bucket_name exclusion_patterns = var.s3_data_source_exclusion_patterns inclusion_patterns = var.s3_data_source_inclusion_patterns documents_metadata_configuration = { @@ -47,12 +47,12 @@ resource "awscc_kendra_data_source" "kendra_s3_data_source" { access_control_list_documents = { key_path = var.s3_data_source_key_path } - } + } } } resource "time_sleep" "wait_after_kendra_s3_data_source_creation" { count = var.create_kendra_s3_data_source ? 1 : 0 - depends_on = [ awscc_kendra_data_source.kendra_s3_data_source[0] ] + depends_on = [awscc_kendra_data_source.kendra_s3_data_source[0]] create_duration = "60s" # Wait for 60 seconds } diff --git a/knowledge-base.tf b/knowledge-base.tf index 7447347..ddd68de 100644 --- a/knowledge-base.tf +++ b/knowledge-base.tf @@ -24,7 +24,7 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_default" { embedding_model_arn = local.kb_embedding_model_arn embedding_model_configuration = var.embedding_model_dimensions != null ? { bedrock_embedding_model_configuration = { - dimensions = var.embedding_model_dimensions + dimensions = var.embedding_model_dimensions embedding_data_type = var.embedding_data_type } } : null @@ -40,7 +40,7 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_default" { } : null } } - depends_on = [ time_sleep.wait_after_index_creation ] + depends_on = [time_sleep.wait_after_index_creation] } # – Existing Vector KBs – @@ -77,7 +77,7 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_mongo" { embedding_model_arn = local.kb_embedding_model_arn embedding_model_configuration = var.embedding_model_dimensions != null ? { bedrock_embedding_model_configuration = { - dimensions = var.embedding_model_dimensions + dimensions = var.embedding_model_dimensions embedding_data_type = var.embedding_data_type } } : null @@ -106,8 +106,8 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_opensearch_managed" { storage_configuration = { type = "OPENSEARCH_MANAGED_CLUSTER" opensearch_managed_cluster_configuration = { - domain_arn = var.domain_arn - domain_endpoint = var.domain_endpoint + domain_arn = var.domain_arn + domain_endpoint = var.domain_endpoint vector_index_name = var.vector_index_name field_mapping = { metadata_field = var.metadata_field @@ -122,7 +122,7 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_opensearch_managed" { embedding_model_arn = local.kb_embedding_model_arn embedding_model_configuration = var.embedding_model_dimensions != null ? { bedrock_embedding_model_configuration = { - dimensions = var.embedding_model_dimensions + dimensions = var.embedding_model_dimensions embedding_data_type = var.embedding_data_type } } : null @@ -166,7 +166,7 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_opensearch" { embedding_model_arn = local.kb_embedding_model_arn embedding_model_configuration = var.embedding_model_dimensions != null ? { bedrock_embedding_model_configuration = { - dimensions = var.embedding_model_dimensions + dimensions = var.embedding_model_dimensions embedding_data_type = var.embedding_data_type } } : null @@ -208,7 +208,7 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_neptune_analytics" { embedding_model_arn = local.kb_embedding_model_arn embedding_model_configuration = var.embedding_model_dimensions != null ? { bedrock_embedding_model_configuration = { - dimensions = var.embedding_model_dimensions + dimensions = var.embedding_model_dimensions embedding_data_type = var.embedding_data_type } } : null @@ -252,7 +252,7 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_pinecone" { embedding_model_arn = local.kb_embedding_model_arn embedding_model_configuration = var.embedding_model_dimensions != null ? { bedrock_embedding_model_configuration = { - dimensions = var.embedding_model_dimensions + dimensions = var.embedding_model_dimensions embedding_data_type = var.embedding_data_type } } : null @@ -286,10 +286,10 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_rds" { resource_arn = var.resource_arn table_name = var.table_name field_mapping = { - metadata_field = var.metadata_field - primary_key_field = var.primary_key_field - text_field = var.text_field - vector_field = var.vector_field + metadata_field = var.metadata_field + primary_key_field = var.primary_key_field + text_field = var.text_field + vector_field = var.vector_field custom_metadata_field = var.custom_metadata_field } } @@ -300,7 +300,7 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_rds" { embedding_model_arn = local.kb_embedding_model_arn embedding_model_configuration = var.embedding_model_dimensions != null ? { bedrock_embedding_model_configuration = { - dimensions = var.embedding_model_dimensions + dimensions = var.embedding_model_dimensions embedding_data_type = var.embedding_data_type } } : null @@ -334,7 +334,7 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_kendra" { } } - depends_on = [ time_sleep.wait_after_kendra_index_creation, time_sleep.wait_after_kendra_s3_data_source_creation ] + depends_on = [time_sleep.wait_after_kendra_index_creation, time_sleep.wait_after_kendra_s3_data_source_creation] } # – SQL Knowledge Base – @@ -355,22 +355,22 @@ resource "awscc_bedrock_knowledge_base" "knowledge_base_sql" { serverless_configuration = var.sql_kb_workgroup_arn == null ? null : { workgroup_arn = var.sql_kb_workgroup_arn auth_configuration = var.serverless_auth_configuration != null ? { - type = var.serverless_auth_configuration.type + type = var.serverless_auth_configuration.type username_password_secret_arn = var.serverless_auth_configuration.username_password_secret_arn } : null } provisioned_configuration = var.provisioned_config_cluster_identifier == null ? null : { cluster_identifier = var.provisioned_config_cluster_identifier auth_configuration = var.provisioned_auth_configuration != null ? { - type = var.provisioned_auth_configuration.type - database_user = var.provisioned_auth_configuration.database_user + type = var.provisioned_auth_configuration.type + database_user = var.provisioned_auth_configuration.database_user username_password_secret_arn = var.provisioned_auth_configuration.username_password_secret_arn } : null - } + } type = var.redshift_query_engine_type } query_generation_configuration = var.query_generation_configuration - storage_configurations = var.redshift_storage_configuration + storage_configurations = var.redshift_storage_configuration } } } diff --git a/main.tf b/main.tf index 7367a4a..72d2d39 100644 --- a/main.tf +++ b/main.tf @@ -86,7 +86,7 @@ resource "awscc_bedrock_agent" "bedrock_agent" { idle_session_ttl_in_seconds = var.idle_session_ttl agent_resource_role_arn = var.agent_resource_role_arn != null ? var.agent_resource_role_arn : aws_iam_role.agent_role[0].arn orchestration_type = var.orchestration_type - custom_orchestration = var.orchestration_type == "CUSTOM" ? { + custom_orchestration = var.orchestration_type == "CUSTOM" ? { executor = { lambda = var.custom_orchestration_lambda_arn } @@ -106,10 +106,10 @@ resource "awscc_bedrock_agent" "bedrock_agent" { stop_sequences = var.stop_sequences maximum_length = var.max_length } - base_prompt_template = var.base_prompt_template - parser_mode = var.parser_mode - prompt_creation_mode = var.prompt_creation_mode - prompt_state = var.prompt_state + base_prompt_template = var.base_prompt_template + parser_mode = var.parser_mode + prompt_creation_mode = var.prompt_creation_mode + prompt_state = var.prompt_state additional_model_request_fields = var.additional_model_request_fields }] override_lambda = var.override_lambda_arn @@ -196,15 +196,18 @@ resource "awscc_bedrock_guardrail" "guardrail" { blocked_input_messaging = var.blocked_input_messaging blocked_outputs_messaging = var.blocked_outputs_messaging description = var.guardrail_description - + + # Automated reasoning policy configuration + automated_reasoning_policy_config = var.automated_reasoning_policy_config + # Cross region configuration cross_region_config = var.guardrail_cross_region_config # Content policy configuration - content_policy_config = { - filters_config = var.filters_config + content_policy_config = (var.filters_config != null || var.content_filters_tier_config != null) ? { + filters_config = var.filters_config content_filters_tier_config = var.content_filters_tier_config - } + } : null # Contextual grounding policy configuration contextual_grounding_policy_config = var.contextual_grounding_policy_filters != null ? { @@ -212,20 +215,20 @@ resource "awscc_bedrock_guardrail" "guardrail" { } : null # Sensitive information policy configuration - sensitive_information_policy_config = { + sensitive_information_policy_config = (var.pii_entities_config != null || var.regexes_config != null) ? { pii_entities_config = var.pii_entities_config regexes_config = var.regexes_config - } + } : null # Word policy configuration - word_policy_config = { + word_policy_config = (var.managed_word_lists_config != null || var.words_config != null) ? { managed_word_lists_config = var.managed_word_lists_config words_config = var.words_config - } + } : null # Topic policy configuration topic_policy_config = var.topics_config == null ? null : { - topics_config = var.topics_config + topics_config = var.topics_config topics_tier_config = var.topics_tier_config } diff --git a/opensearch.tf b/opensearch.tf index 3e150f2..86bbe7d 100644 --- a/opensearch.tf +++ b/opensearch.tf @@ -1,15 +1,15 @@ # – OpenSearch Serverless Default – module "oss_knowledgebase" { - count = var.create_default_kb ? 1 : 0 - source = "aws-ia/opensearch-serverless/aws" - version = "0.0.5" + count = var.create_default_kb ? 1 : 0 + source = "aws-ia/opensearch-serverless/aws" + version = "0.0.5" allow_public_access_network_policy = var.allow_opensearch_public_access - number_of_shards = var.number_of_shards - number_of_replicas = var.number_of_replicas - create_vector_index = true - collection_tags = var.kb_tags != null ? [for k, v in var.kb_tags : { key = k, value = v }] : [] - vector_index_mappings = <<-EOF + number_of_shards = var.number_of_shards + number_of_replicas = var.number_of_replicas + create_vector_index = true + collection_tags = var.kb_tags != null ? [for k, v in var.kb_tags : { key = k, value = v }] : [] + vector_index_mappings = <<-EOF { "properties": { "bedrock-knowledge-base-default-vector": { @@ -83,6 +83,6 @@ resource "aws_opensearchserverless_access_policy" "updated_data_policy" { resource "time_sleep" "wait_after_index_creation" { count = var.create_default_kb ? 1 : 0 - depends_on = [ module.oss_knowledgebase[0].vector_index ] + depends_on = [module.oss_knowledgebase[0].vector_index] create_duration = "60s" # Wait for 60 seconds before creating the index } diff --git a/prompt.tf b/prompt.tf index 273e7a5..e4a671c 100644 --- a/prompt.tf +++ b/prompt.tf @@ -3,13 +3,13 @@ resource "awscc_bedrock_prompt_version" "prompt_version" { count = var.create_prompt_version ? 1 : 0 prompt_arn = awscc_bedrock_prompt.prompt[0].arn - description = var.prompt_version_description + description = var.prompt_version_description tags = var.prompt_version_tags } resource "awscc_bedrock_prompt" "prompt" { count = var.create_prompt ? 1 : 0 - name = "${random_string.solution_prefix.result}-${var.prompt_name}" + name = "${random_string.solution_prefix.result}-${var.prompt_name}" description = var.prompt_description customer_encryption_key_arn = var.customer_encryption_key_arn default_variant = var.default_variant diff --git a/variables.tf b/variables.tf index 6b29d7e..412108c 100644 --- a/variables.tf +++ b/variables.tf @@ -64,7 +64,7 @@ variable "orchestration_type" { description = "The type of orchestration strategy for the agent. Valid values: DEFAULT, CUSTOM_ORCHESTRATION" type = string default = "DEFAULT" - + validation { condition = contains(["DEFAULT", "CUSTOM_ORCHESTRATION"], var.orchestration_type) error_message = "The orchestration_type must be either DEFAULT or CUSTOM_ORCHESTRATION." @@ -403,48 +403,95 @@ variable "guardrail_description" { } variable "filters_config" { - description = "List of content filter configs in content policy." - type = list(map(string)) - default = null + description = "List of content filter configs in content policy. Supports both text and image filters. Use 'input_modalities' and 'output_modalities' (list of strings) to specify content types: ['TEXT'] for text-only, ['IMAGE'] for image-only, or ['TEXT', 'IMAGE'] to apply the same filter to both text and image content in a single filter configuration. Filter types include: HATE, INSULTS, MISCONDUCT, PROMPT_ATTACK, SEXUAL, VIOLENCE." + type = list(object({ + input_action = optional(string) + input_enabled = optional(bool) + input_modalities = optional(list(string)) + input_strength = optional(string) + output_action = optional(string) + output_enabled = optional(bool) + output_modalities = optional(list(string)) + output_strength = optional(string) + type = optional(string) + })) + default = null } variable "contextual_grounding_policy_filters" { description = "The contextual grounding policy filters for the guardrail." - type = list(map(string)) - default = null + type = list(object({ + action = optional(string) + enabled = optional(bool) + threshold = optional(number) + type = optional(string) + })) + default = null } variable "pii_entities_config" { - description = "List of entities." - type = list(map(string)) - default = null + description = "List of PII entities configuration for sensitive information policy." + type = list(object({ + action = optional(string) + input_action = optional(string) + input_enabled = optional(bool) + output_action = optional(string) + output_enabled = optional(bool) + type = optional(string) + })) + default = null } variable "regexes_config" { - description = "List of regex." - type = list(map(string)) - default = null + description = "List of regex patterns for sensitive information policy." + type = list(object({ + action = optional(string) + description = optional(string) + input_action = optional(string) + input_enabled = optional(bool) + name = optional(string) + output_action = optional(string) + output_enabled = optional(bool) + pattern = optional(string) + })) + default = null } variable "managed_word_lists_config" { - description = "A config for the list of managed words." - type = list(map(string)) - default = null + description = "A config for the list of managed words in word policy." + type = list(object({ + input_action = optional(string) + input_enabled = optional(bool) + output_action = optional(string) + output_enabled = optional(bool) + type = optional(string) + })) + default = null } variable "words_config" { - description = "List of custom word configs." - type = list(map(string)) - default = null + description = "List of custom word configs in word policy." + type = list(object({ + input_action = optional(string) + input_enabled = optional(bool) + output_action = optional(string) + output_enabled = optional(bool) + text = optional(string) + })) + default = null } variable "topics_config" { - description = "List of topic configs in topic policy" + description = "List of topic configs in topic policy." type = list(object({ - name = string - examples = list(string) - type = string - definition = string + definition = optional(string) + examples = optional(list(string)) + input_action = optional(string) + input_enabled = optional(bool) + name = optional(string) + output_action = optional(string) + output_enabled = optional(bool) + type = optional(string) })) default = null } @@ -461,6 +508,16 @@ variable "guardrail_kms_key_arn" { default = null } +# – Guardrail Automated Reasoning Policy Configuration – +variable "automated_reasoning_policy_config" { + description = "Optional configuration for integrating Automated Reasoning policies with the guardrail." + type = object({ + confidence_threshold = optional(number) + policies = optional(list(string)) + }) + default = null +} + # – Guardrail Cross Region Configuration – variable "guardrail_cross_region_config" { description = "The system-defined guardrail profile to use with your guardrail." @@ -1222,9 +1279,9 @@ variable "prompt_tags" { variable "variants_list" { description = "List of prompt variants." type = list(object({ - name = optional(string) - template_type = optional(string) - model_id = optional(string) + name = optional(string) + template_type = optional(string) + model_id = optional(string) additional_model_request_fields = optional(string) metadata = optional(list(object({ key = optional(string) @@ -1235,7 +1292,7 @@ variable "variants_list" { agent_identifier = optional(string) })) })) - + inference_configuration = optional(object({ text = optional(object({ max_tokens = optional(number) @@ -1248,8 +1305,8 @@ variable "variants_list" { template_configuration = optional(object({ chat = optional(object({ - input_variables = optional(list(object({ - name = optional(string) + input_variables = optional(list(object({ + name = optional(string) }))) messages = optional(list(object({ content = optional(list(object({ @@ -1288,7 +1345,7 @@ variable "variants_list" { }))) })) })), - + text = optional(object({ input_variables = optional(list(object({ name = optional(string) }))) text = optional(string) @@ -1690,7 +1747,7 @@ variable "provisioned_auth_configuration" { description = "Configurations for provisioned Redshift query engine" type = object({ database_user = optional(string) - type = optional(string) # Auth type explicitly defined + type = optional(string) # Auth type explicitly defined username_password_secret_arn = optional(string) }) default = null @@ -1706,7 +1763,7 @@ variable "provisioned_config_cluster_identifier" { variable "serverless_auth_configuration" { description = "Configuration for the Redshift serverless query engine." type = object({ - type = optional(string) # Auth type explicitly defined + type = optional(string) # Auth type explicitly defined username_password_secret_arn = optional(string) }) default = null @@ -1718,21 +1775,21 @@ variable "query_generation_configuration" { type = object({ generation_context = optional(object({ curated_queries = optional(list(object({ - natural_language = optional(string) # Question for the query - sql = optional(string) # SQL answer for the query + natural_language = optional(string) # Question for the query + sql = optional(string) # SQL answer for the query }))) tables = optional(list(object({ columns = optional(list(object({ - description = optional(string) # Column description - inclusion = optional(string) # Include or exclude status - name = optional(string) # Column name + description = optional(string) # Column description + inclusion = optional(string) # Include or exclude status + name = optional(string) # Column name }))) - description = optional(string) # Table description - inclusion = optional(string) # Include or exclude status - name = optional(string) # Table name (three-part notation) + description = optional(string) # Table description + inclusion = optional(string) # Include or exclude status + name = optional(string) # Table name (three-part notation) }))) })) - execution_timeout_seconds = optional(number) # Max query execution timeout + execution_timeout_seconds = optional(number) # Max query execution timeout }) default = null } @@ -1741,7 +1798,7 @@ variable "redshift_storage_configuration" { description = "List of configurations for available Redshift query engine storage types." type = list(object({ aws_data_catalog_configuration = optional(object({ - table_names = optional(list(string)) # List of table names in AWS Data Catalog + table_names = optional(list(string)) # List of table names in AWS Data Catalog })) redshift_configuration = optional(object({ database_name = optional(string)