Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,5 @@ aws/studio/certificate.yaml
secret_db.json

# Dev
aws/setup/environment-variables-dev.sh
aws/setup/environment-variables-dev.sh
AmazonRootCA1.pem
7 changes: 7 additions & 0 deletions aws/configure/db-init.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ spec:
echo "GRANT ALL PRIVILEGES ON SCHEMA public TO $DB_STUDIO_USERNAME;" | psql -qtAX --set=sslmode=require
echo "granted schema public to keycloak"

echo "create analytics database and user"
echo "CREATE USER $DB_ANALYTICS_USERNAME;" | psql -qtAX --set=sslmode=require
echo "GRANT rds_iam TO $DB_ANALYTICS_USERNAME;" | psql -qtAX --set=sslmode=require
echo "CREATE DATABASE $DB_ANALYTICS_DATABASE WITH ENCODING = 'UTF8';" | psql -qtAX --set=sslmode=require
echo "GRANT ALL PRIVILEGES ON DATABASE $DB_ANALYTICS_DATABASE TO $DB_ANALYTICS_USERNAME;" | psql -qtAX --set=sslmode=require
echo "ALTER DATABASE $DB_ANALYTICS_DATABASE OWNER TO $DB_ANALYTICS_USERNAME;" | psql -qtAX --set=sslmode=require

sleep 10
echo "done"
env:
Expand Down
7 changes: 6 additions & 1 deletion aws/configure/get-infra-values.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ export DB_PORT=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw db_port)
export DB_HOST=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw db_host)
export DB_HOST="${DB_HOST%:$DB_PORT}"

export REDIS_HOST=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw elasticache_primary_endpoint)
export REDIS_HOST=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw elasticache_cfg_endpoint)
export REDIS_CLUSTER_NAME=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw elasticache_cluster_name)

export KAFKA_BOOTSTRAP_SERVER=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw msk_bootstrap_brokers | awk -F',' '{print $1}')

export SERVICE_ACCOUNT_DNS=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw service_account_dns)
export SERVICE_ACCOUNT_ASSISTANT=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw service_account_assistant)
export SERVICE_ACCOUNT_ANALYTICS=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw service_account_analytics)
export SERVICE_ACCOUNT_STUDIO=$($TF_CMD -chdir=$TARGET_DIR_ABSOLUTE output -raw service_account_studio)

echo "Infrastructure values fetched successfully:"
Expand All @@ -42,4 +45,6 @@ echo "REDIS_HOST=$REDIS_HOST"
echo "REDIS_CLUSTER_NAME=$REDIS_CLUSTER_NAME"
echo "SERVICE_ACCOUNT_DNS=$SERVICE_ACCOUNT_DNS"
echo "SERVICE_ACCOUNT_ASSISTANT=$SERVICE_ACCOUNT_ASSISTANT"
echo "SERVICE_ACCOUNT_ANALYTICS=$SERVICE_ACCOUNT_ANALYTICS"
echo "SERVICE_ACCOUNT_STUDIO=$SERVICE_ACCOUNT_STUDIO"
echo "KAFKA_BOOTSTRAP_SERVER=$KAFKA_BOOTSTRAP_SERVER"
201 changes: 194 additions & 7 deletions aws/deploy/main.tf.template
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ variable "elasticache_subnets" {
default = ["$CIDR_ELASTICACHE_A", "$CIDR_ELASTICACHE_B", "$CIDR_ELASTICACHE_C"]
}

variable "msk_subnets" {
default = ["$CIDR_MSK_A", "$CIDR_MSK_B", "$CIDR_MSK_C"]
}

terraform {
required_providers {
aws = {
Expand Down Expand Up @@ -101,6 +105,20 @@ module "vpc" {
}
}

# MSK Subnets =========================================

resource "aws_subnet" "msk_subnets" {
count = length(var.msk_subnets)

vpc_id = module.vpc.vpc_id
cidr_block = var.msk_subnets[count.index]
availability_zone = var.zones[count.index]

tags = {
Name = "${NAME}-msk-${count.index + 1}"
"kubernetes.io/cluster/${NAME}" = "shared"
}
}

# Kubernetes cluster EKS =========================================

Expand Down Expand Up @@ -392,6 +410,11 @@ resource "aws_elasticache_parameter_group" "default" {
name = "maxmemory-policy"
value = "volatile-lru"
}

parameter {
name = "cluster-enabled"
value = "yes"
}
}


Expand Down Expand Up @@ -434,12 +457,12 @@ resource "aws_elasticache_user_group" "iam_user_group" {

resource "aws_elasticache_replication_group" "group1" {
automatic_failover_enabled = true
multi_az_enabled = true
preferred_cache_cluster_azs = slice(var.zones, 0, 2)
replication_group_id = "${local.elasticache_id}-group1"
description = "Rasa ${NAME} Redis Elasticache group 1"
node_type = "cache.m5.xlarge"
num_cache_clusters = 2
num_node_groups = 2
replicas_per_node_group = 1
cluster_mode = "enabled"

parameter_group_name = aws_elasticache_parameter_group.default.name
engine = "redis"
Expand All @@ -455,8 +478,8 @@ resource "aws_elasticache_replication_group" "group1" {
security_group_ids = [module.elasticache_security_group.security_group_id]
}

output "elasticache_primary_endpoint" {
value = aws_elasticache_replication_group.group1.primary_endpoint_address
output "elasticache_cfg_endpoint" {
value = aws_elasticache_replication_group.group1.configuration_endpoint_address
}

output "redis_iam_user" {
Expand All @@ -472,6 +495,74 @@ output "elasticache_cluster_name" {
}


# MSK Kafka Cluster =========================================

locals {
msk_cluster_id = "rasa-${NAME}-kafka"
}

module "msk_security_group" {
source = "terraform-aws-modules/security-group/aws"
version = "~> 5.3"

name = "rasa-${NAME}-msk"
description = "Security group for MSK ${NAME}"
vpc_id = module.vpc.vpc_id

ingress_cidr_blocks = module.vpc.private_subnets_cidr_blocks
ingress_rules = ["kafka-broker-tcp", "kafka-broker-tls-tcp"]

egress_cidr_blocks = [module.vpc.vpc_cidr_block]
egress_rules = ["all-all"]

tags = {
Name = "rasa-${NAME}-msk"
}
}

resource "aws_msk_cluster" "kafka_cluster" {
cluster_name = local.msk_cluster_id
kafka_version = "3.8.x"
number_of_broker_nodes = 3

broker_node_group_info {
instance_type = "kafka.m5.large"
client_subnets = aws_subnet.msk_subnets[*].id
security_groups = [module.msk_security_group.security_group_id]

storage_info {
ebs_storage_info {
volume_size = 100
}
}
}

client_authentication {
sasl {
iam = true
}
}

encryption_info {
encryption_in_transit {
client_broker = "TLS"
in_cluster = true
}
}

tags = {
Name = local.msk_cluster_id
}
}

output "msk_cluster_arn" {
value = aws_msk_cluster.kafka_cluster.arn
}

output "msk_bootstrap_brokers" {
value = aws_msk_cluster.kafka_cluster.bootstrap_brokers_sasl_iam
}

# DNS Identity =========================================

module "iam_role_dns" {
Expand Down Expand Up @@ -500,7 +591,7 @@ output "service_account_dns" {
}


# Rasa Assistent Identity =========================================
# Rasa Assistant Identity =========================================

# S3 IAM Access Policy

Expand Down Expand Up @@ -561,7 +652,8 @@ resource "aws_iam_policy" "rds_database_access" {
"rds-db:connect"
]
Resource = [
"arn:aws:rds-db:${REGION}:${data.aws_caller_identity.current.account_id}:dbuser:${module.rds_main.db_instance_resource_id}/${DB_ASSISTANT_USERNAME}"
"arn:aws:rds-db:${REGION}:${data.aws_caller_identity.current.account_id}:dbuser:${module.rds_main.db_instance_resource_id}/${DB_ASSISTANT_USERNAME}",
"arn:aws:rds-db:${REGION}:${data.aws_caller_identity.current.account_id}:dbuser:${module.rds_main.db_instance_resource_id}/${DB_ANALYTICS_USERNAME}"
]
},
]
Expand All @@ -586,6 +678,72 @@ module "iam_role_rds_database" {
}
}

# Bedrock IAM Access Policy
resource "aws_iam_policy" "bedrock_access" {
name = "${NAME}_bedrock_access"
path = "/"
description = "Rasa ${NAME} Bedrock model access for inference and logging"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"bedrock:GetModelInvocationLoggingConfiguration",
]
Resource = "*"
},
]
})
}

# MSK IAM Access Policy
resource "aws_iam_policy" "msk_access" {
name = "${NAME}_msk_access"
path = "/"
description = "Rasa ${NAME} MSK Kafka access"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"kafka-cluster:Connect",
"kafka-cluster:DescribeCluster"
]
Resource = "*"
},
{
Effect = "Allow"
Action = [
"kafka-cluster:*Topic*",
"kafka-cluster:WriteData",
"kafka-cluster:ReadData"
]
Resource = "*"
},
{
"Effect": "Allow",
"Action": [
"kafka-cluster:AlterGroup",
"kafka-cluster:DescribeGroup"
],
"Resource": "*"
}
]
})
}


module "iam_role_assistant" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
Expand All @@ -597,6 +755,8 @@ module "iam_role_assistant" {
s3 = aws_iam_policy.s3_access.arn
redis = aws_iam_policy.redis_access.arn
rds = aws_iam_policy.rds_database_access.arn
bedrock = aws_iam_policy.bedrock_access.arn
msk = aws_iam_policy.msk_access.arn
}

oidc_providers = {
Expand All @@ -615,6 +775,33 @@ output "service_account_assistant" {
value = local.service_account_assistant
}

module "iam_role_analytics" {
source = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
version = "~> 5.59"

role_name = "${NAME}-analytics"

role_policy_arns = {
rds = aws_iam_policy.rds_database_access.arn
msk = aws_iam_policy.msk_access.arn
}

oidc_providers = {
rasa = {
provider_arn = module.eks.oidc_provider_arn
namespace_service_accounts = ["${NAMESPACE}:rasa-analytics"]
}
}
}

locals {
service_account_analytics = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${module.iam_role_analytics.iam_role_name}"
}

output "service_account_analytics" {
value = local.service_account_analytics
}


# Rasa Studio Identity =========================================

Expand Down
4 changes: 3 additions & 1 deletion aws/permissions/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"arn:aws:iam::*:role/aws-service-role/eks.amazonaws.com/AWSServiceRoleForAmazonEKS",
"arn:aws:iam::*:role/aws-service-role/eks-nodegroup.amazonaws.com/AWSServiceRoleForAmazonEKSNodegroup",
"arn:aws:iam::*:role/aws-service-role/elasticache.amazonaws.com/AWSServiceRoleForElastiCache",
"arn:aws:iam::*:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS"
"arn:aws:iam::*:role/aws-service-role/rds.amazonaws.com/AWSServiceRoleForRDS",
"arn:aws:iam::*:role/aws-service-role/kafka.amazonaws.com/AWSServiceRoleForKafka"
]
},
{
Expand Down Expand Up @@ -100,6 +101,7 @@
"elasticache:ModifyUser",
"elasticache:ModifyUserGroup",
"elasticache:Connect",
"kafka:*",
"iam:AttachRolePolicy",
"iam:CreateOpenIDConnectProvider",
"iam:CreatePolicy",
Expand Down
10 changes: 5 additions & 5 deletions aws/rasa/assistant/setup-assistant.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,18 @@ kubectl get ns
# This Helm chart contains instructions for setting up the Rasa bot and Analytics components.
print_info "Pulling Rasa Helm chart..."
mkdir $SCRIPT_DIR/repos
helm pull oci://europe-west3-docker.pkg.dev/rasa-releases/helm-charts/rasa --version 1.2.5 --untar --destination $SCRIPT_DIR/repos/rasa-helm
helm pull oci://europe-west3-docker.pkg.dev/rasa-releases/helm-charts/rasa --version 1.3.0-rc.2 --untar --destination $SCRIPT_DIR/repos/rasa-helm

# Next, we'll ensure that other passwords and secret values that Rasa requires are set, before creating a Kubernetes Secret to securely store them in a way that we can reference later on:
print_info "Creating secrets for the Rasa assistant to use..."
export AUTH_TOKEN=$(openssl rand -hex 8 | base64)
export JWT_SECRET=$(openssl rand -hex 8 | base64)
export KAFKA_CLIENT_PASSWORD=$(kubectl get secret kafka-user-passwords -n $NAMESPACE -o jsonpath='{.data.client-passwords}' | base64 -d | cut -d ',' -f 1)
export RASA_PRO_LICENSE=${RASA_PRO_LICENSE:-'Rasa License is not set! Set it manually with `export RASA_PRO_LICENSE=yourlicense`'}
export OPENAI_API_KEY=${OPENAI_API_KEY:-'OpenAI API Key is not set! Set it manually with `export OPENAI_API_KEY=yourkey`'}

print_info "Secret values retrieved. If any of the values below are not set, be sure to set them manually and re-run this script."
print_info "AUTH_TOKEN: $AUTH_TOKEN"
print_info "JWT_SECRET: $JWT_SECRET"
print_info "KAFKA_CLIENT_PASSWORD: $KAFKA_CLIENT_PASSWORD"
print_info "RASA_PRO_LICENSE: $RASA_PRO_LICENSE"
print_info "OPENAI_API_KEY: $OPENAI_API_KEY"

Expand All @@ -45,5 +43,7 @@ create secret generic rasa-secrets \
--from-literal=rasaProLicense="$(echo $RASA_PRO_LICENSE )" \
--from-literal=authToken="$(echo $AUTH_TOKEN )" \
--from-literal=jwtSecret="$(echo $JWT_SECRET)" \
--from-literal=kafkaSslPassword="$(echo $KAFKA_CLIENT_PASSWORD)" \
--from-literal=openaiApiKey="$(echo $OPENAI_API_KEY)"
--from-literal=openaiApiKey="$(echo $OPENAI_API_KEY)"

kubectl --namespace $NAMESPACE create secret generic msk-ssl-ca --from-file=$SCRIPT_DIR/AmazonRootCA1.pem
print_info "Kubernetes secret created successfully!"
Loading