Skip to content
Merged
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
30 changes: 26 additions & 4 deletions terraform/foundation/ai.tf
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,28 @@ variable "mimir_vpc_enabled" {
default = false
}

variable "jaeger_vpc_enabled" {
type = bool
default = false
nullable = false
description = "Attach the Jaeger query Lambda to private subnets. Requires agentcore_enabled and integrations_enabled; routing, DNS and target ingress must be operator-configured. Default false → no-op ($0). PERSIST in live terraform.tfvars."
validation {
condition = !var.jaeger_vpc_enabled || (var.agentcore_enabled && var.integrations_enabled)
error_message = "jaeger_vpc_enabled requires agentcore_enabled and integrations_enabled."
}
}

variable "dynatrace_vpc_enabled" {
type = bool
default = false
nullable = false
description = "Attach the Dynatrace environment API Lambda to private subnets for a private ActiveGate endpoint. Requires agentcore_enabled and integrations_enabled; routing, DNS and egress (including to hosted SaaS environments) must be operator-configured. Does not affect the official hosted MCP preset. Default false → no-op ($0). PERSIST in live terraform.tfvars."
validation {
condition = !var.dynatrace_vpc_enabled || (var.agentcore_enabled && var.integrations_enabled)
error_message = "dynatrace_vpc_enabled requires agentcore_enabled and integrations_enabled."
}
}

variable "istio_vpc_enabled" {
type = bool
description = "Attach the istio-read Lambda to the private subnets so it can reach a PRIVATE-ONLY EKS API endpoint. Requires agentcore_enabled. Default false → no-op ($0); off = non-VPC (reaches a public/public+private cluster endpoint). PERSIST in live terraform.tfvars."
Expand Down Expand Up @@ -509,10 +531,10 @@ resource "aws_iam_role_policy" "agent_lambda_opensearch" {
})
}

# ENI perms for the opensearch-mcp Lambda ONLY when it is VPC-attached (opensearch_vpc_enabled).
# ENI permissions exist only while a managed Lambda VPC option is enabled.
# Compound-gated: references agent_lambda[0], which exists only when agentcore_enabled → guard both.
resource "aws_iam_role_policy" "agent_lambda_vpc_eni" {
count = var.agentcore_enabled && (var.opensearch_vpc_enabled || var.clickhouse_vpc_enabled || var.prometheus_vpc_enabled || var.loki_vpc_enabled || var.tempo_vpc_enabled || var.mimir_vpc_enabled || var.istio_vpc_enabled) ? 1 : 0
count = var.agentcore_enabled && (var.opensearch_vpc_enabled || var.clickhouse_vpc_enabled || var.prometheus_vpc_enabled || var.loki_vpc_enabled || var.tempo_vpc_enabled || var.mimir_vpc_enabled || var.jaeger_vpc_enabled || var.dynatrace_vpc_enabled || var.istio_vpc_enabled) ? 1 : 0
name = "${var.project}-agent-lambda-vpc-eni"
role = aws_iam_role.agent_lambda[0].id
policy = jsonencode({
Expand Down Expand Up @@ -967,10 +989,10 @@ resource "aws_lambda_function" "agent" {
}

# Per-Lambda VPC opt-in: attach a connector to the private subnets ONLY when its <name>_vpc_enabled
# flag is set (opensearch/clickhouse/prometheus/loki/tempo/mimir for VPC-only datasources;
# flag is set (opensearch/clickhouse/prometheus/loki/tempo/mimir/jaeger/dynatrace for private datasources;
# istio-read for a private-only EKS API endpoint). Off (default) → no vpc_config → non-VPC.
dynamic "vpc_config" {
for_each = ((each.key == "opensearch-mcp" && var.opensearch_vpc_enabled) || (each.key == "clickhouse-mcp" && var.clickhouse_vpc_enabled) || (each.key == "prometheus-mcp" && var.prometheus_vpc_enabled) || (each.key == "loki-mcp" && var.loki_vpc_enabled) || (each.key == "tempo-mcp" && var.tempo_vpc_enabled) || (each.key == "mimir-mcp" && var.mimir_vpc_enabled) || (each.key == "istio-read" && var.istio_vpc_enabled)) ? [1] : []
for_each = ((each.key == "opensearch-mcp" && var.opensearch_vpc_enabled) || (each.key == "clickhouse-mcp" && var.clickhouse_vpc_enabled) || (each.key == "prometheus-mcp" && var.prometheus_vpc_enabled) || (each.key == "loki-mcp" && var.loki_vpc_enabled) || (each.key == "tempo-mcp" && var.tempo_vpc_enabled) || (each.key == "mimir-mcp" && var.mimir_vpc_enabled) || (each.key == "jaeger-mcp" && var.jaeger_vpc_enabled) || (each.key == "dynatrace-mcp" && var.dynatrace_vpc_enabled) || (each.key == "istio-read" && var.istio_vpc_enabled)) ? [1] : []
content {
subnet_ids = local.private_subnet_ids
security_group_ids = [aws_security_group.service.id]
Expand Down
34 changes: 34 additions & 0 deletions terraform/foundation/tests/runtime_iam.tftest.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,40 @@ run "defaults_remain_dark" {
condition = (length(aws_iam_role_policy.agentcore) == 0 && length(aws_iam_role_policy.official_mcp_credentials) == 0 && length(aws_iam_role_policy.steampipe_task) == 0 && length(aws_iam_role_policy.worker_lambda) == 0 && !var.inventory_host_only && var.steampipe_image_digest == null && var.worker_image_digest == null && !var.remediation_enabled && !var.diagnosis_notify_enabled && !var.integrations_write_enabled)
error_message = "Core runtime and host/image overrides must remain opt-in."
}
assert {
condition = !var.jaeger_vpc_enabled && !var.dynatrace_vpc_enabled && length(aws_iam_role_policy.agent_lambda_vpc_eni) == 0
error_message = "Private external datasource networking must remain default-off."
}
}

run "private_datasource_flags_require_applied_prerequisites" {
command = plan
variables {
jaeger_vpc_enabled = true
dynatrace_vpc_enabled = true
}
expect_failures = [var.jaeger_vpc_enabled, var.dynatrace_vpc_enabled]
}

run "private_jaeger_and_dynatrace_attach_only_the_selected_lambdas" {
command = plan
variables {
agentcore_enabled = true
integrations_enabled = true
jaeger_vpc_enabled = true
dynatrace_vpc_enabled = true
}
assert {
condition = (
aws_lambda_function.agent["jaeger-mcp"].vpc_config[0].subnet_ids == toset(var.existing_private_subnet_ids) &&
aws_lambda_function.agent["dynatrace-mcp"].vpc_config[0].subnet_ids == toset(var.existing_private_subnet_ids) &&
length(aws_lambda_function.agent["datadog-mcp"].vpc_config) == 0 &&
length(aws_lambda_function.agent["prometheus-mcp"].vpc_config) == 0 &&
length(aws_iam_role_policy.agent_lambda_vpc_eni) == 1 &&
!var.official_mcp_enabled && !var.remediation_enabled && !var.integrations_write_enabled
)
error_message = "Private datasource attachment must be selective and must not activate MCP/write gates."
}
}

run "explicit_inventory_targets_pin_metadata_permissions_and_actual_principal" {
Expand Down
Loading