diff --git a/Makefile b/Makefile
index affb4f3..15f1d75 100644
--- a/Makefile
+++ b/Makefile
@@ -77,7 +77,7 @@ test: _pull-tf
echo "------------------------------------------------------------"; \
echo "# Terraform init"; \
echo "------------------------------------------------------------"; \
- if docker run $$(tty -s && echo "-it" || echo) --rm -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" hashicorp/terraform:$(TF_VERSION) \
+ if docker run $$(tty -s && echo "-it" || echo) --rm --network host -v "$(CURRENT_DIR):/t" --workdir "$${DOCKER_PATH}" hashicorp/terraform:$(TF_VERSION) \
init \
-lock=false \
-upgrade \
diff --git a/README.md b/README.md
index da64134..2c0d2c5 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,10 @@
-# terraform-module-template
-Template for Terraform modules
-
-
+# terraform-aws-bedrock-agent
+
+Terraform module for Amazon Bedrock Agent resources
+
+[![lint](https://github.com/flaconi/terraform-aws-bedrock-agent/workflows/lint/badge.svg)](https://github.com/flaconi/terraform-aws-bedrock-agent/actions?query=workflow%3Alint)
+[![test](https://github.com/flaconi/terraform-aws-bedrock-agent/workflows/test/badge.svg)](https://github.com/flaconi/terraform-aws-bedrock-agent/actions?query=workflow%3Atest)
+[![Tag](https://img.shields.io/github/tag/flaconi/terraform-aws-bedrock-agent.svg)](https://github.com/flaconi/terraform-aws-bedrock-agent/releases)
[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
For requirements regarding module structure: [style-guide-terraform.md](https://github.com/Flaconi/devops-docs/blob/master/doc/conventions/style-guide-terraform.md)
@@ -18,7 +17,9 @@ For requirements regarding module structure: [style-guide-terraform.md](https://
## Providers
-No providers.
+| Name | Version |
+|------|---------|
+| [aws](#provider\_aws) | ~> 5.73 |
@@ -28,17 +29,88 @@ No providers.
| Name | Version |
|------|---------|
| [terraform](#requirement\_terraform) | ~> 1.3 |
+| [aws](#requirement\_aws) | ~> 5.73 |
## Required Inputs
-No required inputs.
+The following input variables are required:
+
+### [name](#input\_name)
+
+Description: Name for the agent.
+
+Type: `string`
+
+### [alias\_name](#input\_alias\_name)
+
+Description: Name for the agent alias.
+
+Type: `string`
+
+### [knowledgebase\_name](#input\_knowledgebase\_name)
+
+Description: Name for the knowledgebase.
+
+Type: `string`
+
+### [s3\_arn](#input\_s3\_arn)
+
+Description: ARN of S3 bucket with data
+
+Type: `string`
+
+### [oss\_arn](#input\_oss\_arn)
+
+Description: ARN of OpenSearch Serverless Collection.
+
+Type: `string`
## Optional Inputs
-No optional inputs.
+The following input variables are optional (have default values):
+
+### [alias\_description](#input\_alias\_description)
+
+Description: Description for the agent alias.
+
+Type: `string`
+
+Default: `null`
+
+### [agent\_model\_id](#input\_agent\_model\_id)
+
+Description: Model identifier for agent.
+
+Type: `string`
+
+Default: `"anthropic.claude-v2"`
+
+### [knowledgebase\_decription](#input\_knowledgebase\_decription)
+
+Description: Description for the knowledgebase.
+
+Type: `string`
+
+Default: `null`
+
+### [knowledgebase\_model\_id](#input\_knowledgebase\_model\_id)
+
+Description: Model identifier for Knowledgebase.
+
+Type: `string`
+
+Default: `"amazon.titan-embed-text-v1"`
+
+### [tags](#input\_tags)
+
+Description: A map of tags to assign to the customization job and custom model.
+
+Type: `map(string)`
+
+Default: `{}`
@@ -53,4 +125,4 @@ No outputs.
**[MIT License](LICENSE)**
-Copyright (c) 2023 **[Flaconi GmbH](https://github.com/flaconi)**
+Copyright (c) 2024 **[Flaconi GmbH](https://github.com/flaconi)**
diff --git a/data.tf b/data.tf
new file mode 100644
index 0000000..7fb84bd
--- /dev/null
+++ b/data.tf
@@ -0,0 +1,97 @@
+data "aws_caller_identity" "current" {}
+
+data "aws_region" "current" {}
+
+data "aws_bedrock_foundation_model" "agent" {
+ model_id = var.agent_model_id
+}
+
+data "aws_bedrock_foundation_model" "knowledgebase" {
+ model_id = var.knowledgebase_model_id
+}
+
+data "aws_iam_policy_document" "agent_trust" {
+ statement {
+ actions = ["sts:AssumeRole"]
+ principals {
+ identifiers = ["bedrock.amazonaws.com"]
+ type = "Service"
+ }
+ condition {
+ test = "StringEquals"
+ values = [data.aws_caller_identity.current.account_id]
+ variable = "aws:SourceAccount"
+ }
+ condition {
+ test = "ArnLike"
+ values = ["arn:aws:bedrock:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:agent/*"]
+ variable = "AWS:SourceArn"
+ }
+ }
+}
+
+data "aws_iam_policy_document" "agent_permissions" {
+ statement {
+ actions = ["bedrock:InvokeModel"]
+ resources = [
+ data.aws_bedrock_foundation_model.agent.model_arn,
+ ]
+ }
+}
+
+data "aws_iam_policy_document" "knowledgebase_trust" {
+ statement {
+ actions = ["sts:AssumeRole"]
+ principals {
+ identifiers = ["bedrock.amazonaws.com"]
+ type = "Service"
+ }
+ condition {
+ test = "StringEquals"
+ values = [data.aws_caller_identity.current.account_id]
+ variable = "aws:SourceAccount"
+ }
+ condition {
+ test = "ArnLike"
+ values = ["arn:aws:bedrock:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:knowledge-base/*"]
+ variable = "AWS:SourceArn"
+ }
+ }
+}
+
+data "aws_iam_policy_document" "knowledgebase_permissions" {
+ statement {
+ actions = ["bedrock:InvokeModel"]
+ resources = [
+ data.aws_bedrock_foundation_model.knowledgebase.model_arn,
+ ]
+ }
+ statement {
+ actions = ["aoss:APIAccessAll"]
+ resources = [
+ var.oss_arn
+ ]
+ }
+ statement {
+ actions = ["s3:ListBucket"]
+ resources = [
+ var.s3_arn
+ ]
+ condition {
+ test = "StringEquals"
+ values = [data.aws_caller_identity.current.account_id]
+ variable = "aws:ResourceAccount"
+ }
+ }
+ statement {
+ actions = ["s3:GetObject"]
+ resources = [
+ "${var.s3_arn}/*"
+ ]
+ condition {
+ test = "StringEquals"
+ values = [data.aws_caller_identity.current.account_id]
+ variable = "aws:ResourceAccount"
+ }
+ }
+}
diff --git a/main.tf b/main.tf
new file mode 100644
index 0000000..f4259ed
--- /dev/null
+++ b/main.tf
@@ -0,0 +1,73 @@
+resource "aws_iam_role" "agent" {
+ assume_role_policy = data.aws_iam_policy_document.agent_trust.json
+ name_prefix = "BedrockExecutionRoleForAgents_"
+}
+
+resource "aws_iam_role_policy" "agent" {
+ policy = data.aws_iam_policy_document.agent_permissions.json
+ role = aws_iam_role.agent.id
+}
+
+resource "aws_iam_role" "knowledgebase" {
+ assume_role_policy = data.aws_iam_policy_document.knowledgebase_trust.json
+ name_prefix = "BedrockExecutionRoleForKnowledgeBase_"
+}
+
+resource "aws_iam_role_policy" "knowledgebase" {
+ policy = data.aws_iam_policy_document.knowledgebase_permissions.json
+ role = aws_iam_role.agent.id
+}
+
+resource "aws_bedrockagent_agent" "this" {
+ agent_name = var.name
+ agent_resource_role_arn = aws_iam_role.agent.arn
+ idle_session_ttl_in_seconds = 500
+ foundation_model = var.agent_model_id
+}
+
+resource "aws_bedrockagent_knowledge_base" "this" {
+ name = var.knowledgebase_name
+ role_arn = aws_iam_role.knowledgebase.arn
+ knowledge_base_configuration {
+ vector_knowledge_base_configuration {
+ embedding_model_arn = data.aws_bedrock_foundation_model.knowledgebase.model_arn
+ }
+ type = "VECTOR"
+ }
+ storage_configuration {
+ type = "OPENSEARCH_SERVERLESS"
+ opensearch_serverless_configuration {
+ collection_arn = var.oss_arn
+ vector_index_name = "bedrock-knowledge-base-default-index"
+ field_mapping {
+ vector_field = "bedrock-knowledge-base-default-vector"
+ text_field = "AMAZON_BEDROCK_TEXT_CHUNK"
+ metadata_field = "AMAZON_BEDROCK_METADATA"
+ }
+ }
+ }
+}
+
+resource "aws_bedrockagent_agent_alias" "this" {
+ agent_alias_name = var.alias_name
+ agent_id = aws_bedrockagent_agent.this.agent_id
+ description = var.alias_description
+}
+
+resource "aws_bedrockagent_data_source" "this" {
+ knowledge_base_id = aws_bedrockagent_knowledge_base.this.id
+ name = var.knowledgebase_name
+ data_source_configuration {
+ type = "S3"
+ s3_configuration {
+ bucket_arn = var.s3_arn
+ }
+ }
+}
+
+resource "aws_bedrockagent_agent_knowledge_base_association" "this" {
+ agent_id = aws_bedrockagent_agent.this.id
+ description = var.knowledgebase_decription
+ knowledge_base_id = aws_bedrockagent_knowledge_base.this.id
+ knowledge_base_state = "ENABLED"
+}
diff --git a/variables.tf b/variables.tf
new file mode 100644
index 0000000..8500a7e
--- /dev/null
+++ b/variables.tf
@@ -0,0 +1,54 @@
+variable "name" {
+ description = "Name for the agent."
+ type = string
+}
+
+variable "alias_name" {
+ description = "Name for the agent alias."
+ type = string
+}
+
+variable "alias_description" {
+ description = "Description for the agent alias."
+ type = string
+ default = null
+}
+
+variable "agent_model_id" {
+ description = "Model identifier for agent."
+ type = string
+ default = "anthropic.claude-v2"
+}
+
+variable "knowledgebase_name" {
+ description = "Name for the knowledgebase."
+ type = string
+}
+
+variable "knowledgebase_decription" {
+ description = "Description for the knowledgebase."
+ type = string
+ default = null
+}
+
+variable "knowledgebase_model_id" {
+ description = "Model identifier for Knowledgebase."
+ type = string
+ default = "amazon.titan-embed-text-v1"
+}
+
+variable "s3_arn" {
+ description = "ARN of S3 bucket with data"
+ type = string
+}
+
+variable "oss_arn" {
+ description = "ARN of OpenSearch Serverless Collection."
+ type = string
+}
+
+variable "tags" {
+ description = "A map of tags to assign to the customization job and custom model."
+ type = map(string)
+ default = {}
+}
diff --git a/versions.tf b/versions.tf
index e6b4cbd..c06253b 100644
--- a/versions.tf
+++ b/versions.tf
@@ -1,3 +1,9 @@
terraform {
required_version = "~> 1.3"
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ version = "~> 5.73"
+ }
+ }
}