Skip to content
2 changes: 1 addition & 1 deletion modules/aws_ecs/ecs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ resource "aws_launch_configuration" "this" {
instance_type = var.instance_type # e.g. t2.medium

enable_monitoring = true
associate_public_ip_address = true
associate_public_ip_address = var.associate_public_ip_address

# This user data represents a collection of “scripts” that will be executed the first time the machine starts.
# This specific example makes sure the EC2 instance is automatically attached to the ECS cluster that we create earlier
Expand Down
1 change: 1 addition & 0 deletions modules/aws_ecs/loadbalancers.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
resource "aws_lb" "this" {
name = "${var.deployment_name}-alb"
idle_timeout = var.alb_idle_timeout
internal = var.alb_internal

security_groups = [aws_security_group.alb.id]
subnets = var.public_subnet_ids
Expand Down
81 changes: 42 additions & 39 deletions modules/aws_ecs/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,48 @@ locals {
// Use var.ecs_telemetry_fluentbit_image if defined, otherwise fallback to the same tag as var.ecs_retool_image
ecs_telemetry_fluentbit_image = var.ecs_telemetry_fluentbit_image != "" ? var.ecs_telemetry_fluentbit_image : format("%s:%s", "tryretool/retool-aws-for-fluent-bit", split(":", var.ecs_retool_image)[1])

secret_environment_variables = concat(
[
{
name = "POSTGRES_USER"
valueFrom = aws_secretsmanager_secret.rds_username.arn
},
{
name = "POSTGRES_PASSWORD"
valueFrom = aws_secretsmanager_secret.rds_password.arn
},
{
name = "JWT_SECRET"
valueFrom = aws_secretsmanager_secret.jwt_secret.arn
},
{
name = "ENCRYPTION_KEY"
valueFrom = aws_secretsmanager_secret.encryption_key.arn
}
],
var.retool_license_key != "" ? [
{
name = "LICENSE_KEY"
valueFrom = aws_secretsmanager_secret.retool_license_key[0].arn
}
] : [],
var.temporal_cluster_config.tls_enabled && var.temporal_cluster_config.tls_crt != null ? [
{
name = "WORKFLOW_TEMPORAL_TLS_CRT"
valueFrom = aws_secretsmanager_secret.temporal_tls_crt[0].arn
}
] : [],
var.temporal_cluster_config.tls_enabled && var.temporal_cluster_config.tls_key != null ? [
{
name = "WORKFLOW_TEMPORAL_TLS_KEY"
valueFrom = aws_secretsmanager_secret.temporal_tls_key[0].arn
}
] : []
)

environment_variables = concat(
var.additional_env_vars, # add additional environment variables
local.base_environment_variables,
local.temporal_mtls_config,
var.code_executor_enabled ? [
{
name = "CODE_EXECUTOR_INGRESS_DOMAIN"
Expand Down Expand Up @@ -68,26 +106,6 @@ locals {
name = "POSTGRES_PORT"
value = "5432"
},
{
"name" = "POSTGRES_USER",
"value" = var.rds_username
},
{
"name" = "POSTGRES_PASSWORD",
"value" = random_string.rds_password.result
},
{
"name" : "JWT_SECRET",
"value" : random_string.jwt_secret.result
},
{
"name" : "ENCRYPTION_KEY",
"value" : random_string.encryption_key.result
},
{
"name" : "LICENSE_KEY",
"value" : var.retool_license_key
},
# Workflows-specific
{
"name" : "WORKFLOW_BACKEND_HOST",
Expand Down Expand Up @@ -123,7 +141,7 @@ locals {
auto_create_group = "true"
log_stream_prefix = "SERVICE_RETOOL/"
}
} : {
} : {
logDriver = "awslogs"
options = {
awslogs-group = aws_cloudwatch_log_group.this.id
Expand All @@ -143,7 +161,7 @@ locals {
memory = var.launch_type == "EC2" ? var.ecs_task_resource_map["fluentbit"]["memory"] : null

firelensConfiguration = {
type = "fluentbit"
type = "fluentbit"
options = {
config-file-type = "file"
config-file-value = "/extra.conf"
Expand All @@ -152,7 +170,7 @@ locals {

logConfiguration = {
logDriver = "awslogs"
options = {
options = {
awslogs-group = aws_cloudwatch_log_group.this.id
awslogs-region = var.aws_region
awslogs-stream-prefix = "SERVICE_RETOOL"
Expand All @@ -171,19 +189,4 @@ locals {
}
] : []
)

temporal_mtls_config = (
var.temporal_cluster_config.tls_enabled && var.temporal_cluster_config.tls_crt != null && var.temporal_cluster_config.tls_key != null ?
[
{
"name" : "WORKFLOW_TEMPORAL_TLS_CRT",
"value" : var.temporal_cluster_config.tls_crt
},
{
"name" : "WORKFLOW_TEMPORAL_TLS_KEY",
"value" : var.temporal_cluster_config.tls_key
}
] :
[]
)
}
46 changes: 27 additions & 19 deletions modules/aws_ecs/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ resource "aws_db_instance" "this" {
storage_throughput = var.rds_storage_throughput
iops = var.rds_iops
multi_az = var.rds_multi_az
backup_retention_period = var.rds_backup_retention_period
backup_window = var.rds_backup_window

skip_final_snapshot = true
apply_immediately = true
Expand Down Expand Up @@ -79,7 +81,7 @@ resource "aws_ecs_service" "retool" {
security_groups = [
aws_security_group.containers.id
]
assign_public_ip = true
assign_public_ip = var.assign_public_ip
}
}
}
Expand Down Expand Up @@ -107,7 +109,7 @@ resource "aws_ecs_service" "jobs_runner" {
security_groups = [
aws_security_group.containers.id
]
assign_public_ip = true
assign_public_ip = var.assign_public_ip
}
}
}
Expand Down Expand Up @@ -140,7 +142,7 @@ resource "aws_ecs_service" "workflows_backend" {
security_groups = [
aws_security_group.containers.id
]
assign_public_ip = true
assign_public_ip = var.assign_public_ip
}
}
}
Expand Down Expand Up @@ -169,7 +171,7 @@ resource "aws_ecs_service" "workflows_worker" {
security_groups = [
aws_security_group.containers.id
]
assign_public_ip = true
assign_public_ip = var.assign_public_ip
}
}
}
Expand Down Expand Up @@ -201,7 +203,7 @@ resource "aws_ecs_service" "code_executor" {
security_groups = [
aws_security_group.containers.id
]
assign_public_ip = true
assign_public_ip = var.assign_public_ip
}
}
}
Expand Down Expand Up @@ -234,7 +236,7 @@ resource "aws_ecs_service" "telemetry" {
security_groups = [
aws_security_group.containers.id
]
assign_public_ip = true
assign_public_ip = var.assign_public_ip
}
}
}
Expand Down Expand Up @@ -278,7 +280,8 @@ resource "aws_ecs_task_definition" "retool_jobs_runner" {
value = "JOBS_RUNNER"
}
]
)
),
secrets = local.secret_environment_variables
}
]
))
Expand Down Expand Up @@ -328,7 +331,8 @@ resource "aws_ecs_task_definition" "retool" {
"value" = tostring(var.cookie_insecure)
}
]
)
),
secrets = local.secret_environment_variables
}
]
))
Expand Down Expand Up @@ -379,7 +383,8 @@ resource "aws_ecs_task_definition" "retool_workflows_backend" {
"value" = tostring(var.cookie_insecure)
}
]
)
),
secrets = local.secret_environment_variables
}
]
))
Expand Down Expand Up @@ -434,7 +439,8 @@ resource "aws_ecs_task_definition" "retool_workflows_worker" {
"value" = tostring(var.cookie_insecure)
}
]
)
),
secrets = local.secret_environment_variables
}
]
))
Expand All @@ -454,12 +460,12 @@ resource "aws_ecs_task_definition" "retool_code_executor" {
local.common_containers,
[
{
name = "retool-code-executor"
essential = true
image = local.ecs_code_executor_image
cpu = var.launch_type == "EC2" ? var.ecs_task_resource_map["code_executor"]["cpu"] : null
memory = var.launch_type == "EC2" ? var.ecs_task_resource_map["code_executor"]["memory"] : null
user = var.launch_type == "EC2" ? null : "1001:1001"
name = "retool-code-executor"
essential = true
image = local.ecs_code_executor_image
cpu = var.launch_type == "EC2" ? var.ecs_task_resource_map["code_executor"]["cpu"] : null
memory = var.launch_type == "EC2" ? var.ecs_task_resource_map["code_executor"]["memory"] : null
user = var.launch_type == "EC2" ? null : "1001:1001"
# required to use nsjail sandboxing, which is required for custom libraries for JS and Python
# Learn more here: https://docs.retool.com/self-hosted/concepts/architecture#code-executor
# If not using nsjail sandboxing, update this to be false and use user = "1001:1001"
Expand All @@ -486,7 +492,7 @@ resource "aws_ecs_task_definition" "retool_code_executor" {
local.base_environment_variables,
[
{
name = "NODE_OPTIONS",
name = "NODE_OPTIONS",
value = "--max_old_space_size=1024"
}
],
Expand Down Expand Up @@ -580,7 +586,8 @@ resource "aws_ecs_task_definition" "retool_telemetry" {
value = base64encode(file(var.telemetry_custom_config_path))
}
] : []
)
),
secrets = local.secret_environment_variables
}
]
)
Expand Down Expand Up @@ -635,7 +642,7 @@ resource "aws_service_discovery_service" "retool_code_executor_service" {

resource "aws_service_discovery_service" "retool_telemetry_service" {
count = var.telemetry_enabled ? 1 : 0
name = "telemetry"
name = "telemetry"

dns_config {
namespace_id = aws_service_discovery_private_dns_namespace.retool_namespace[0].id
Expand Down Expand Up @@ -701,5 +708,6 @@ module "temporal" {
aws_ecs_capacity_provider_name = var.launch_type == "EC2" ? aws_ecs_capacity_provider.this[0].name : null
task_propagate_tags = var.task_propagate_tags
service_discovery_namespace = local.service_discovery_namespace
assign_public_ip = var.assign_public_ip
iam_partition = var.iam_partition
}
22 changes: 22 additions & 0 deletions modules/aws_ecs/roles.tf
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,28 @@ resource "aws_iam_role_policy_attachment" "execution_role" {
policy_arn = "arn:${var.iam_partition}:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}

data "aws_iam_policy_document" "execution_role_secrets_policy" {
count = var.launch_type == "FARGATE" ? 1 : 0
statement {
actions = [
"secretsmanager:GetSecretValue",
]
resources = [for secret in local.secret_environment_variables : secret.valueFrom]
}
}

resource "aws_iam_policy" "execution_role_secrets_policy" {
count = var.launch_type == "FARGATE" ? 1 : 0
name = "${var.deployment_name}-execution-role-secrets-policy"
policy = data.aws_iam_policy_document.execution_role_secrets_policy[0].json
}

resource "aws_iam_role_policy_attachment" "execution_role_secrets" {
count = var.launch_type == "FARGATE" ? 1 : 0
role = aws_iam_role.execution_role[0].name
policy_arn = aws_iam_policy.execution_role_secrets_policy[0].arn
}

# IAM Role for EC2 instances
resource "aws_iam_instance_profile" "ec2" {
count = var.launch_type == "EC2" ? 1 : 0
Expand Down
37 changes: 37 additions & 0 deletions modules/aws_ecs/secrets.tf
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,40 @@ resource "aws_secretsmanager_secret_version" "encryption_key" {
secret_id = aws_secretsmanager_secret.encryption_key.id
secret_string = random_string.encryption_key.result
}

resource "aws_secretsmanager_secret" "retool_license_key" {
count = var.retool_license_key != "" ? 1 : 0
name = "${var.deployment_name}-retool-license-key"
description = "This is the Retool license key"
recovery_window_in_days = 0
}

resource "aws_secretsmanager_secret_version" "retool_license_key" {
count = var.retool_license_key != "" ? 1 : 0
secret_id = aws_secretsmanager_secret.retool_license_key[0].id
secret_string = var.retool_license_key
}

resource "aws_secretsmanager_secret" "temporal_tls_crt" {
count = var.temporal_cluster_config.tls_enabled && var.temporal_cluster_config.tls_crt != null ? 1 : 0
name = "${var.deployment_name}-temporal-tls-crt"
description = "Temporal client certificate"
}

resource "aws_secretsmanager_secret_version" "temporal_tls_crt" {
count = var.temporal_cluster_config.tls_enabled && var.temporal_cluster_config.tls_crt != null ? 1 : 0
secret_id = aws_secretsmanager_secret.temporal_tls_crt[0].id
secret_string = var.temporal_cluster_config.tls_crt
}

resource "aws_secretsmanager_secret" "temporal_tls_key" {
count = var.temporal_cluster_config.tls_enabled && var.temporal_cluster_config.tls_key != null ? 1 : 0
name = "${var.deployment_name}-temporal-tls-key"
description = "Temporal client key"
}

resource "aws_secretsmanager_secret_version" "temporal_tls_key" {
count = var.temporal_cluster_config.tls_enabled && var.temporal_cluster_config.tls_key != null ? 1 : 0
secret_id = aws_secretsmanager_secret.temporal_tls_key[0].id
secret_string = var.temporal_cluster_config.tls_key
}
8 changes: 0 additions & 8 deletions modules/aws_ecs/temporal/locals.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@ locals {
"name": "POSTGRES_PORT",
"value": tostring(module.temporal_aurora_rds.cluster_port)
},
{
"name": "POSTGRES_USER",
"value": var.temporal_aurora_username
},
{
"name": "POSTGRES_PASSWORD",
"value": random_string.temporal_aurora_password.result
},
{
"name": "DBNAME",
"value": "temporal"
Expand Down
Loading