From 66258d598d9f9bad011f00a37acb5b73fc88fe00 Mon Sep 17 00:00:00 2001 From: Gonzalo Rojas Date: Thu, 16 Apr 2026 12:43:32 -0300 Subject: [PATCH 1/5] fix(infra): security hardening, unused vars cleanup and file naming consistency - Replace verifiedpermissions:* with least-privilege actions in aws/iam/agent - Remove force_destroy from Route53 zones in aws/dns - Migrate GCP artifact registry from service account keys to workload identity - Remove unused subscription_id variable from azure/acr, azure/dns, azure/private_dns - Rename output.tf -> outputs.tf, provider.tf -> providers.tf, variable.tf -> variables.tf across all modules --- .../aws/acm/{output.tf => outputs.tf} | 0 .../aws/backend/.terraform.lock.hcl | 41 ------------------- infrastructure/aws/dns/main.tf | 6 +-- .../aws/dns/{output.tf => outputs.tf} | 0 .../aws/eks/{output.tf => outputs.tf} | 0 infrastructure/aws/iam/agent/main.tf | 28 +++++++++---- .../aws/iam/agent/{output.tf => outputs.tf} | 0 .../{output.tf => outputs.tf} | 0 .../cert_manager/{output.tf => outputs.tf} | 0 .../external_dns/{output.tf => outputs.tf} | 0 .../aws/iam/s3/{output.tf => outputs.tf} | 0 .../aws/vpc/{output.tf => outputs.tf} | 0 .../azure/acr/{output.tf => outputs.tf} | 0 .../azure/acr/{provider.tf => providers.tf} | 0 infrastructure/azure/acr/variables.tf | 5 --- .../azure/aks/{output.tf => outputs.tf} | 0 .../azure/aks/{provider.tf => providers.tf} | 0 .../azure/dns/{output.tf => outputs.tf} | 0 .../azure/dns/{provider.tf => providers.tf} | 0 infrastructure/azure/dns/variables.tf | 5 --- .../azure/iam/{output.tf => outputs.tf} | 0 .../azure/iam/{provider.tf => providers.tf} | 0 .../private_dns/{output.tf => outputs.tf} | 0 .../private_dns/{provider.tf => providers.tf} | 0 infrastructure/azure/private_dns/variables.tf | 5 --- .../resource_group/{output.tf => outputs.tf} | 0 .../{provider.tf => providers.tf} | 0 .../azure/vnet/{output.tf => outputs.tf} | 0 .../azure/vnet/{provider.tf => providers.tf} | 0 .../{provider.tf => providers.tf} | 0 .../{provider.tf => providers.tf} | 0 .../istio/{provider.tf => providers.tf} | 0 .../prometheus/{provider.tf => providers.tf} | 0 infrastructure/gcp/acr/main.tf | 10 +++-- .../gcp/acr/{output.tf => outputs.tf} | 7 ++-- .../gcp/acr/{provider.tf => providers.tf} | 0 infrastructure/gcp/acr/variables.tf | 9 ++++ infrastructure/gcp/artifact-registry/main.tf | 10 +++-- .../gcp/artifact-registry/outputs.tf | 7 ++-- .../gcp/artifact-registry/variables.tf | 9 ++++ .../gcp/dns/{output.tf => outputs.tf} | 0 .../gcp/dns/{provider.tf => providers.tf} | 0 .../gcp/gke/{output.tf => outputs.tf} | 0 .../gcp/gke/{provider.tf => providers.tf} | 0 .../gcp/iam/{output.tf => outputs.tf} | 0 .../gcp/iam/{provider.tf => providers.tf} | 0 .../gcp/nat/{output.tf => outputs.tf} | 0 .../gcp/nat/{provider.tf => providers.tf} | 0 .../gcp/vnet/{output.tf => outputs.tf} | 0 .../gcp/vnet/{provider.tf => providers.tf} | 0 .../oci/dns/{output.tf => outputs.tf} | 0 .../oci/dns/{provider.tf => providers.tf} | 0 .../{provider.tf => providers.tf} | 0 .../oci/oke/{output.tf => outputs.tf} | 0 .../oci/oke/{provider.tf => providers.tf} | 0 .../oci/vcn/{provider.tf => providers.tf} | 0 .../{provider.tf => providers.tf} | 0 .../gcp/cloud/{provider.tf => providers.tf} | 0 .../oci/cloud/{provider.tf => providers.tf} | 0 .../{provider.tf => providers.tf} | 0 .../aks/{provider.tf => providers.tf} | 0 .../eks/{provider.tf => providers.tf} | 0 .../gke/{provider.tf => providers.tf} | 0 .../gke/{variable.tf => variables.tf} | 0 .../oke/{provider.tf => providers.tf} | 0 .../metrics/{provider.tf => providers.tf} | 0 .../{provider.tf => providers.tf} | 0 .../{provider.tf => providers.tf} | 0 68 files changed, 59 insertions(+), 83 deletions(-) rename infrastructure/aws/acm/{output.tf => outputs.tf} (100%) delete mode 100644 infrastructure/aws/backend/.terraform.lock.hcl rename infrastructure/aws/dns/{output.tf => outputs.tf} (100%) rename infrastructure/aws/eks/{output.tf => outputs.tf} (100%) rename infrastructure/aws/iam/agent/{output.tf => outputs.tf} (100%) rename infrastructure/aws/iam/aws_load_balancer_controller_iam/{output.tf => outputs.tf} (100%) rename infrastructure/aws/iam/cert_manager/{output.tf => outputs.tf} (100%) rename infrastructure/aws/iam/external_dns/{output.tf => outputs.tf} (100%) rename infrastructure/aws/iam/s3/{output.tf => outputs.tf} (100%) rename infrastructure/aws/vpc/{output.tf => outputs.tf} (100%) rename infrastructure/azure/acr/{output.tf => outputs.tf} (100%) rename infrastructure/azure/acr/{provider.tf => providers.tf} (100%) rename infrastructure/azure/aks/{output.tf => outputs.tf} (100%) rename infrastructure/azure/aks/{provider.tf => providers.tf} (100%) rename infrastructure/azure/dns/{output.tf => outputs.tf} (100%) rename infrastructure/azure/dns/{provider.tf => providers.tf} (100%) rename infrastructure/azure/iam/{output.tf => outputs.tf} (100%) rename infrastructure/azure/iam/{provider.tf => providers.tf} (100%) rename infrastructure/azure/private_dns/{output.tf => outputs.tf} (100%) rename infrastructure/azure/private_dns/{provider.tf => providers.tf} (100%) rename infrastructure/azure/resource_group/{output.tf => outputs.tf} (100%) rename infrastructure/azure/resource_group/{provider.tf => providers.tf} (100%) rename infrastructure/azure/vnet/{output.tf => outputs.tf} (100%) rename infrastructure/azure/vnet/{provider.tf => providers.tf} (100%) rename infrastructure/commons/cert_manager/{provider.tf => providers.tf} (100%) rename infrastructure/commons/external_dns/{provider.tf => providers.tf} (100%) rename infrastructure/commons/istio/{provider.tf => providers.tf} (100%) rename infrastructure/commons/prometheus/{provider.tf => providers.tf} (100%) rename infrastructure/gcp/acr/{output.tf => outputs.tf} (61%) rename infrastructure/gcp/acr/{provider.tf => providers.tf} (100%) rename infrastructure/gcp/dns/{output.tf => outputs.tf} (100%) rename infrastructure/gcp/dns/{provider.tf => providers.tf} (100%) rename infrastructure/gcp/gke/{output.tf => outputs.tf} (100%) rename infrastructure/gcp/gke/{provider.tf => providers.tf} (100%) rename infrastructure/gcp/iam/{output.tf => outputs.tf} (100%) rename infrastructure/gcp/iam/{provider.tf => providers.tf} (100%) rename infrastructure/gcp/nat/{output.tf => outputs.tf} (100%) rename infrastructure/gcp/nat/{provider.tf => providers.tf} (100%) rename infrastructure/gcp/vnet/{output.tf => outputs.tf} (100%) rename infrastructure/gcp/vnet/{provider.tf => providers.tf} (100%) rename infrastructure/oci/dns/{output.tf => outputs.tf} (100%) rename infrastructure/oci/dns/{provider.tf => providers.tf} (100%) rename infrastructure/oci/dynamic_groups/{provider.tf => providers.tf} (100%) rename infrastructure/oci/oke/{output.tf => outputs.tf} (100%) rename infrastructure/oci/oke/{provider.tf => providers.tf} (100%) rename infrastructure/oci/vcn/{provider.tf => providers.tf} (100%) rename nullplatform/asset/docker_server/{provider.tf => providers.tf} (100%) rename nullplatform/cloud/gcp/cloud/{provider.tf => providers.tf} (100%) rename nullplatform/cloud/oci/cloud/{provider.tf => providers.tf} (100%) rename nullplatform/code_repository/{provider.tf => providers.tf} (100%) rename nullplatform/container_orchestration/aks/{provider.tf => providers.tf} (100%) rename nullplatform/container_orchestration/eks/{provider.tf => providers.tf} (100%) rename nullplatform/container_orchestration/gke/{provider.tf => providers.tf} (100%) rename nullplatform/container_orchestration/gke/{variable.tf => variables.tf} (100%) rename nullplatform/container_orchestration/oke/{provider.tf => providers.tf} (100%) rename nullplatform/metrics/{provider.tf => providers.tf} (100%) rename nullplatform/scope_definition/{provider.tf => providers.tf} (100%) rename nullplatform/scope_definition_agent_association/{provider.tf => providers.tf} (100%) diff --git a/infrastructure/aws/acm/output.tf b/infrastructure/aws/acm/outputs.tf similarity index 100% rename from infrastructure/aws/acm/output.tf rename to infrastructure/aws/acm/outputs.tf diff --git a/infrastructure/aws/backend/.terraform.lock.hcl b/infrastructure/aws/backend/.terraform.lock.hcl deleted file mode 100644 index a388c581..00000000 --- a/infrastructure/aws/backend/.terraform.lock.hcl +++ /dev/null @@ -1,41 +0,0 @@ -# This file is maintained automatically by "tofu init". -# Manual edits may be lost in future updates. - -provider "registry.opentofu.org/hashicorp/aws" { - version = "6.40.0" - constraints = "~> 6.0" - hashes = [ - "h1:7BnIMXbqx8KNZB4lCrqe0bkRvFXDI/fQ8LV0CxpfMAY=", - "zh:0afa48ff254e87987ab58656c0c9ce408c223df084ca3aa73170eb264c7ffdd8", - "zh:1cac5867dde6803c251b2eecfdce870a2f19cb04e09ad28b6d895d3faf8fd853", - "zh:2e6c6267dda9a12c6945bbafd4405af6238c3d2617736a2fe6a129ea82b05b81", - "zh:38ad3eefbf5a0544b049fcdadec9a1d9cf56f18c9c0cd03659133d635a8e0042", - "zh:462a69e653529aff033b22e41332c6b170dfbcd2dac357e0ae40dc84d809a964", - "zh:5007c5d67ccd5ef271eb9f512e71a0ef55dae23b6099eec1762a06995d62d4b0", - "zh:51778e221c1bf898c5c93acaba0f42dc6b0df14d0982db97d52615061874cae3", - "zh:711de3f42d0b26efb5332989e20135079c9a09ee39a5d7e0a2c0e73541991133", - "zh:8596ca6540cb2b5bce0de8ad89f030c8ef8088f1128c438f9c362b0657dc89af", - "zh:923a632c0995dbcc2cf8678e1e418cc4f3c57a6b3aa0b4cee719b91e7296ef8d", - "zh:9839e87b4c3f0112750eeb387f1ec9a982200b67184ccd9482be4b577e1e48f6", - "zh:9d994cbaa6a03d78274fd32d4a00b9c97ad202605f11973d738737f20995746c", - "zh:a73c5687001b7a79b3cbbcf4a6d4b162cb3a0b73ed322382615b77d3f392f880", - "zh:a86a021475165ff3bed8172d846e932cbc047169bb6ee42ce28b41301a7e3988", - "zh:c200c757634fb83456e21006281d663c71415845450c5448b9598698aa780e7c", - ] -} - -provider "registry.opentofu.org/hashicorp/random" { - version = "3.8.1" - hashes = [ - "h1:LsYuJLZcYl1RiH7Hd3w90Ra5+k5cNqfdRUQXItkTI8Y=", - "zh:25c458c7c676f15705e872202dad7dcd0982e4a48e7ea1800afa5fc64e77f4c8", - "zh:2edeaf6f1b20435b2f81855ad98a2e70956d473be9e52a5fdf57ccd0098ba476", - "zh:44becb9d5f75d55e36dfed0c5beabaf4c92e0a2bc61a3814d698271c646d48e7", - "zh:7699032612c3b16cc69928add8973de47b10ce81b1141f30644a0e8a895b5cd3", - "zh:86d07aa98d17703de9fbf402c89590dc1e01dbe5671dd6bc5e487eb8fe87eee0", - "zh:8c411c77b8390a49a8a1bc9f176529e6b32369dd33a723606c8533e5ca4d68c1", - "zh:a5ecc8255a612652a56b28149994985e2c4dc046e5d34d416d47fa7767f5c28f", - "zh:aea3fe1a5669b932eda9c5c72e5f327db8da707fe514aaca0d0ef60cb24892f9", - "zh:f56e26e6977f755d7ae56fa6320af96ecf4bb09580d47cb481efbf27f1c5afff", - ] -} diff --git a/infrastructure/aws/dns/main.tf b/infrastructure/aws/dns/main.tf index 2be9640e..91f99576 100644 --- a/infrastructure/aws/dns/main.tf +++ b/infrastructure/aws/dns/main.tf @@ -1,11 +1,9 @@ resource "aws_route53_zone" "public_zone" { - name = var.domain_name - force_destroy = true + name = var.domain_name } resource "aws_route53_zone" "private_zone" { - name = var.domain_name - force_destroy = true + name = var.domain_name vpc { vpc_id = var.vpc_id } diff --git a/infrastructure/aws/dns/output.tf b/infrastructure/aws/dns/outputs.tf similarity index 100% rename from infrastructure/aws/dns/output.tf rename to infrastructure/aws/dns/outputs.tf diff --git a/infrastructure/aws/eks/output.tf b/infrastructure/aws/eks/outputs.tf similarity index 100% rename from infrastructure/aws/eks/output.tf rename to infrastructure/aws/eks/outputs.tf diff --git a/infrastructure/aws/iam/agent/main.tf b/infrastructure/aws/iam/agent/main.tf index 40b240cd..c92a30c2 100644 --- a/infrastructure/aws/iam/agent/main.tf +++ b/infrastructure/aws/iam/agent/main.tf @@ -157,23 +157,33 @@ resource "aws_iam_policy" "nullplatform_eks_policy" { # Grant permissions to describe and list EKS cluster resources resource "aws_iam_policy" "nullplatform_avp_policy" { name = "nullplatform_${var.cluster_name}_avp_policy" - description = "Policy for managing AVP resources" + description = "Policy for reading and evaluating AVP policy stores" policy = jsonencode({ "Version" : "2012-10-17", "Statement" : [ { "Effect" : "Allow", "Action" : [ - "verifiedpermissions:*" + "verifiedpermissions:IsAuthorized", + "verifiedpermissions:IsAuthorizedWithToken", + "verifiedpermissions:BatchIsAuthorized", + "verifiedpermissions:BatchIsAuthorizedWithToken", + "verifiedpermissions:GetPolicyStore", + "verifiedpermissions:ListPolicyStores", + "verifiedpermissions:GetPolicy", + "verifiedpermissions:ListPolicies", + "verifiedpermissions:GetPolicyTemplate", + "verifiedpermissions:ListPolicyTemplates", + "verifiedpermissions:GetSchema" ], "Resource" : "*", - # "Condition" : { - # "StringEquals" : { - # "aws:RequestedRegion" : [ - # data.aws_region.current.region - # ] - # } - # } + "Condition" : { + "StringEquals" : { + "aws:RequestedRegion" : [ + data.aws_region.current.region + ] + } + } } ] }) diff --git a/infrastructure/aws/iam/agent/output.tf b/infrastructure/aws/iam/agent/outputs.tf similarity index 100% rename from infrastructure/aws/iam/agent/output.tf rename to infrastructure/aws/iam/agent/outputs.tf diff --git a/infrastructure/aws/iam/aws_load_balancer_controller_iam/output.tf b/infrastructure/aws/iam/aws_load_balancer_controller_iam/outputs.tf similarity index 100% rename from infrastructure/aws/iam/aws_load_balancer_controller_iam/output.tf rename to infrastructure/aws/iam/aws_load_balancer_controller_iam/outputs.tf diff --git a/infrastructure/aws/iam/cert_manager/output.tf b/infrastructure/aws/iam/cert_manager/outputs.tf similarity index 100% rename from infrastructure/aws/iam/cert_manager/output.tf rename to infrastructure/aws/iam/cert_manager/outputs.tf diff --git a/infrastructure/aws/iam/external_dns/output.tf b/infrastructure/aws/iam/external_dns/outputs.tf similarity index 100% rename from infrastructure/aws/iam/external_dns/output.tf rename to infrastructure/aws/iam/external_dns/outputs.tf diff --git a/infrastructure/aws/iam/s3/output.tf b/infrastructure/aws/iam/s3/outputs.tf similarity index 100% rename from infrastructure/aws/iam/s3/output.tf rename to infrastructure/aws/iam/s3/outputs.tf diff --git a/infrastructure/aws/vpc/output.tf b/infrastructure/aws/vpc/outputs.tf similarity index 100% rename from infrastructure/aws/vpc/output.tf rename to infrastructure/aws/vpc/outputs.tf diff --git a/infrastructure/azure/acr/output.tf b/infrastructure/azure/acr/outputs.tf similarity index 100% rename from infrastructure/azure/acr/output.tf rename to infrastructure/azure/acr/outputs.tf diff --git a/infrastructure/azure/acr/provider.tf b/infrastructure/azure/acr/providers.tf similarity index 100% rename from infrastructure/azure/acr/provider.tf rename to infrastructure/azure/acr/providers.tf diff --git a/infrastructure/azure/acr/variables.tf b/infrastructure/azure/acr/variables.tf index 02ec3cfc..20adfff0 100644 --- a/infrastructure/azure/acr/variables.tf +++ b/infrastructure/azure/acr/variables.tf @@ -22,11 +22,6 @@ variable "containerregistry_name" { } } -variable "subscription_id" { - type = string - description = "The ID of the Azure subscription" -} - ############################################################################### # OPTIONAL VARIABLES - REGISTRY CONFIGURATION ############################################################################### diff --git a/infrastructure/azure/aks/output.tf b/infrastructure/azure/aks/outputs.tf similarity index 100% rename from infrastructure/azure/aks/output.tf rename to infrastructure/azure/aks/outputs.tf diff --git a/infrastructure/azure/aks/provider.tf b/infrastructure/azure/aks/providers.tf similarity index 100% rename from infrastructure/azure/aks/provider.tf rename to infrastructure/azure/aks/providers.tf diff --git a/infrastructure/azure/dns/output.tf b/infrastructure/azure/dns/outputs.tf similarity index 100% rename from infrastructure/azure/dns/output.tf rename to infrastructure/azure/dns/outputs.tf diff --git a/infrastructure/azure/dns/provider.tf b/infrastructure/azure/dns/providers.tf similarity index 100% rename from infrastructure/azure/dns/provider.tf rename to infrastructure/azure/dns/providers.tf diff --git a/infrastructure/azure/dns/variables.tf b/infrastructure/azure/dns/variables.tf index feaded4e..48f3138d 100644 --- a/infrastructure/azure/dns/variables.tf +++ b/infrastructure/azure/dns/variables.tf @@ -12,11 +12,6 @@ variable "domain_name" { description = "The domain name to use for the DNS zone (e.g., example.com)" } -variable "subscription_id" { - type = string - description = "The ID of the Azure subscription" -} - ############################################################################### # OPTIONAL VARIABLES - TAGS ############################################################################### diff --git a/infrastructure/azure/iam/output.tf b/infrastructure/azure/iam/outputs.tf similarity index 100% rename from infrastructure/azure/iam/output.tf rename to infrastructure/azure/iam/outputs.tf diff --git a/infrastructure/azure/iam/provider.tf b/infrastructure/azure/iam/providers.tf similarity index 100% rename from infrastructure/azure/iam/provider.tf rename to infrastructure/azure/iam/providers.tf diff --git a/infrastructure/azure/private_dns/output.tf b/infrastructure/azure/private_dns/outputs.tf similarity index 100% rename from infrastructure/azure/private_dns/output.tf rename to infrastructure/azure/private_dns/outputs.tf diff --git a/infrastructure/azure/private_dns/provider.tf b/infrastructure/azure/private_dns/providers.tf similarity index 100% rename from infrastructure/azure/private_dns/provider.tf rename to infrastructure/azure/private_dns/providers.tf diff --git a/infrastructure/azure/private_dns/variables.tf b/infrastructure/azure/private_dns/variables.tf index 645fc46c..e20e3316 100644 --- a/infrastructure/azure/private_dns/variables.tf +++ b/infrastructure/azure/private_dns/variables.tf @@ -12,11 +12,6 @@ variable "domain_name" { description = "The domain name to use for the private DNS zone (e.g., privatelink.database.windows.net)" } -variable "subscription_id" { - type = string - description = "The ID of the Azure subscription" -} - ############################################################################### # VNET LINK ############################################################################### diff --git a/infrastructure/azure/resource_group/output.tf b/infrastructure/azure/resource_group/outputs.tf similarity index 100% rename from infrastructure/azure/resource_group/output.tf rename to infrastructure/azure/resource_group/outputs.tf diff --git a/infrastructure/azure/resource_group/provider.tf b/infrastructure/azure/resource_group/providers.tf similarity index 100% rename from infrastructure/azure/resource_group/provider.tf rename to infrastructure/azure/resource_group/providers.tf diff --git a/infrastructure/azure/vnet/output.tf b/infrastructure/azure/vnet/outputs.tf similarity index 100% rename from infrastructure/azure/vnet/output.tf rename to infrastructure/azure/vnet/outputs.tf diff --git a/infrastructure/azure/vnet/provider.tf b/infrastructure/azure/vnet/providers.tf similarity index 100% rename from infrastructure/azure/vnet/provider.tf rename to infrastructure/azure/vnet/providers.tf diff --git a/infrastructure/commons/cert_manager/provider.tf b/infrastructure/commons/cert_manager/providers.tf similarity index 100% rename from infrastructure/commons/cert_manager/provider.tf rename to infrastructure/commons/cert_manager/providers.tf diff --git a/infrastructure/commons/external_dns/provider.tf b/infrastructure/commons/external_dns/providers.tf similarity index 100% rename from infrastructure/commons/external_dns/provider.tf rename to infrastructure/commons/external_dns/providers.tf diff --git a/infrastructure/commons/istio/provider.tf b/infrastructure/commons/istio/providers.tf similarity index 100% rename from infrastructure/commons/istio/provider.tf rename to infrastructure/commons/istio/providers.tf diff --git a/infrastructure/commons/prometheus/provider.tf b/infrastructure/commons/prometheus/providers.tf similarity index 100% rename from infrastructure/commons/prometheus/provider.tf rename to infrastructure/commons/prometheus/providers.tf diff --git a/infrastructure/gcp/acr/main.tf b/infrastructure/gcp/acr/main.tf index 918f1fab..7019cd47 100644 --- a/infrastructure/gcp/acr/main.tf +++ b/infrastructure/gcp/acr/main.tf @@ -7,7 +7,6 @@ resource "google_artifact_registry_repository" "registry" { labels = var.tags } - resource "google_service_account" "artifact_sa" { account_id = "artifact-registry-sa" display_name = "Service Account for Artifact Registry" @@ -20,7 +19,12 @@ resource "google_project_iam_member" "artifact_sa_role" { member = "serviceAccount:${google_service_account.artifact_sa.email}" } -resource "google_service_account_key" "artifact_sa_key" { +resource "google_service_account_iam_member" "workload_identity" { + for_each = { + for wi in var.workload_identity_bindings : "${wi.namespace}-${wi.ksa_name}" => wi + } + service_account_id = google_service_account.artifact_sa.name - public_key_type = "TYPE_X509_PEM_FILE" + role = "roles/iam.workloadIdentityUser" + member = "serviceAccount:${var.project_id}.svc.id.goog[${each.value.namespace}/${each.value.ksa_name}]" } diff --git a/infrastructure/gcp/acr/output.tf b/infrastructure/gcp/acr/outputs.tf similarity index 61% rename from infrastructure/gcp/acr/output.tf rename to infrastructure/gcp/acr/outputs.tf index b85d98a9..40391fbe 100644 --- a/infrastructure/gcp/acr/output.tf +++ b/infrastructure/gcp/acr/outputs.tf @@ -8,8 +8,7 @@ output "acr_login_server" { value = "${var.location}-docker.pkg.dev/${var.project_id}/${var.containerregistry_name}" } -output "service_account_key_json" { - description = "The Service Account key for container registry access" - value = google_service_account_key.artifact_sa_key.private_key - sensitive = true +output "service_account_email" { + description = "Service Account email to use with Workload Identity" + value = google_service_account.artifact_sa.email } diff --git a/infrastructure/gcp/acr/provider.tf b/infrastructure/gcp/acr/providers.tf similarity index 100% rename from infrastructure/gcp/acr/provider.tf rename to infrastructure/gcp/acr/providers.tf diff --git a/infrastructure/gcp/acr/variables.tf b/infrastructure/gcp/acr/variables.tf index e95ec31d..cc8ecec3 100644 --- a/infrastructure/gcp/acr/variables.tf +++ b/infrastructure/gcp/acr/variables.tf @@ -36,3 +36,12 @@ variable "tags" { description = "A mapping of labels to assign to the container registry" default = {} } + +variable "workload_identity_bindings" { + description = "List of Kubernetes service accounts to bind via Workload Identity" + type = list(object({ + namespace = string + ksa_name = string + })) + default = [] +} diff --git a/infrastructure/gcp/artifact-registry/main.tf b/infrastructure/gcp/artifact-registry/main.tf index 855ddca6..1e815f78 100644 --- a/infrastructure/gcp/artifact-registry/main.tf +++ b/infrastructure/gcp/artifact-registry/main.tf @@ -5,7 +5,6 @@ resource "google_artifact_registry_repository" "registry" { format = var.format } - resource "google_service_account" "artifact_sa" { account_id = "artifact-registry-sa" display_name = "Service Account para Artifact Registry" @@ -18,7 +17,12 @@ resource "google_project_iam_member" "artifact_sa_role" { member = "serviceAccount:${google_service_account.artifact_sa.email}" } -resource "google_service_account_key" "artifact_sa_key" { +resource "google_service_account_iam_member" "workload_identity" { + for_each = { + for wi in var.workload_identity_bindings : "${wi.namespace}-${wi.ksa_name}" => wi + } + service_account_id = google_service_account.artifact_sa.name - public_key_type = "TYPE_X509_PEM_FILE" + role = "roles/iam.workloadIdentityUser" + member = "serviceAccount:${var.project_id}.svc.id.goog[${each.value.namespace}/${each.value.ksa_name}]" } diff --git a/infrastructure/gcp/artifact-registry/outputs.tf b/infrastructure/gcp/artifact-registry/outputs.tf index 0739cc74..39a6ccc0 100644 --- a/infrastructure/gcp/artifact-registry/outputs.tf +++ b/infrastructure/gcp/artifact-registry/outputs.tf @@ -6,8 +6,7 @@ output "repository_url" { value = "${var.location}-docker.pkg.dev/${var.project_id}/${var.repository_id}" } -output "service_account_key_json" { - description = "Service Account key" - value = google_service_account_key.artifact_sa_key.private_key - sensitive = true +output "service_account_email" { + description = "Service Account email to use with Workload Identity" + value = google_service_account.artifact_sa.email } diff --git a/infrastructure/gcp/artifact-registry/variables.tf b/infrastructure/gcp/artifact-registry/variables.tf index e57f2b0d..694c8940 100644 --- a/infrastructure/gcp/artifact-registry/variables.tf +++ b/infrastructure/gcp/artifact-registry/variables.tf @@ -18,3 +18,12 @@ variable "format" { description = "The format (DOCKER, NPM, PYTHON, etc)" default = "DOCKER" } + +variable "workload_identity_bindings" { + description = "List of Kubernetes service accounts to bind via Workload Identity" + type = list(object({ + namespace = string + ksa_name = string + })) + default = [] +} diff --git a/infrastructure/gcp/dns/output.tf b/infrastructure/gcp/dns/outputs.tf similarity index 100% rename from infrastructure/gcp/dns/output.tf rename to infrastructure/gcp/dns/outputs.tf diff --git a/infrastructure/gcp/dns/provider.tf b/infrastructure/gcp/dns/providers.tf similarity index 100% rename from infrastructure/gcp/dns/provider.tf rename to infrastructure/gcp/dns/providers.tf diff --git a/infrastructure/gcp/gke/output.tf b/infrastructure/gcp/gke/outputs.tf similarity index 100% rename from infrastructure/gcp/gke/output.tf rename to infrastructure/gcp/gke/outputs.tf diff --git a/infrastructure/gcp/gke/provider.tf b/infrastructure/gcp/gke/providers.tf similarity index 100% rename from infrastructure/gcp/gke/provider.tf rename to infrastructure/gcp/gke/providers.tf diff --git a/infrastructure/gcp/iam/output.tf b/infrastructure/gcp/iam/outputs.tf similarity index 100% rename from infrastructure/gcp/iam/output.tf rename to infrastructure/gcp/iam/outputs.tf diff --git a/infrastructure/gcp/iam/provider.tf b/infrastructure/gcp/iam/providers.tf similarity index 100% rename from infrastructure/gcp/iam/provider.tf rename to infrastructure/gcp/iam/providers.tf diff --git a/infrastructure/gcp/nat/output.tf b/infrastructure/gcp/nat/outputs.tf similarity index 100% rename from infrastructure/gcp/nat/output.tf rename to infrastructure/gcp/nat/outputs.tf diff --git a/infrastructure/gcp/nat/provider.tf b/infrastructure/gcp/nat/providers.tf similarity index 100% rename from infrastructure/gcp/nat/provider.tf rename to infrastructure/gcp/nat/providers.tf diff --git a/infrastructure/gcp/vnet/output.tf b/infrastructure/gcp/vnet/outputs.tf similarity index 100% rename from infrastructure/gcp/vnet/output.tf rename to infrastructure/gcp/vnet/outputs.tf diff --git a/infrastructure/gcp/vnet/provider.tf b/infrastructure/gcp/vnet/providers.tf similarity index 100% rename from infrastructure/gcp/vnet/provider.tf rename to infrastructure/gcp/vnet/providers.tf diff --git a/infrastructure/oci/dns/output.tf b/infrastructure/oci/dns/outputs.tf similarity index 100% rename from infrastructure/oci/dns/output.tf rename to infrastructure/oci/dns/outputs.tf diff --git a/infrastructure/oci/dns/provider.tf b/infrastructure/oci/dns/providers.tf similarity index 100% rename from infrastructure/oci/dns/provider.tf rename to infrastructure/oci/dns/providers.tf diff --git a/infrastructure/oci/dynamic_groups/provider.tf b/infrastructure/oci/dynamic_groups/providers.tf similarity index 100% rename from infrastructure/oci/dynamic_groups/provider.tf rename to infrastructure/oci/dynamic_groups/providers.tf diff --git a/infrastructure/oci/oke/output.tf b/infrastructure/oci/oke/outputs.tf similarity index 100% rename from infrastructure/oci/oke/output.tf rename to infrastructure/oci/oke/outputs.tf diff --git a/infrastructure/oci/oke/provider.tf b/infrastructure/oci/oke/providers.tf similarity index 100% rename from infrastructure/oci/oke/provider.tf rename to infrastructure/oci/oke/providers.tf diff --git a/infrastructure/oci/vcn/provider.tf b/infrastructure/oci/vcn/providers.tf similarity index 100% rename from infrastructure/oci/vcn/provider.tf rename to infrastructure/oci/vcn/providers.tf diff --git a/nullplatform/asset/docker_server/provider.tf b/nullplatform/asset/docker_server/providers.tf similarity index 100% rename from nullplatform/asset/docker_server/provider.tf rename to nullplatform/asset/docker_server/providers.tf diff --git a/nullplatform/cloud/gcp/cloud/provider.tf b/nullplatform/cloud/gcp/cloud/providers.tf similarity index 100% rename from nullplatform/cloud/gcp/cloud/provider.tf rename to nullplatform/cloud/gcp/cloud/providers.tf diff --git a/nullplatform/cloud/oci/cloud/provider.tf b/nullplatform/cloud/oci/cloud/providers.tf similarity index 100% rename from nullplatform/cloud/oci/cloud/provider.tf rename to nullplatform/cloud/oci/cloud/providers.tf diff --git a/nullplatform/code_repository/provider.tf b/nullplatform/code_repository/providers.tf similarity index 100% rename from nullplatform/code_repository/provider.tf rename to nullplatform/code_repository/providers.tf diff --git a/nullplatform/container_orchestration/aks/provider.tf b/nullplatform/container_orchestration/aks/providers.tf similarity index 100% rename from nullplatform/container_orchestration/aks/provider.tf rename to nullplatform/container_orchestration/aks/providers.tf diff --git a/nullplatform/container_orchestration/eks/provider.tf b/nullplatform/container_orchestration/eks/providers.tf similarity index 100% rename from nullplatform/container_orchestration/eks/provider.tf rename to nullplatform/container_orchestration/eks/providers.tf diff --git a/nullplatform/container_orchestration/gke/provider.tf b/nullplatform/container_orchestration/gke/providers.tf similarity index 100% rename from nullplatform/container_orchestration/gke/provider.tf rename to nullplatform/container_orchestration/gke/providers.tf diff --git a/nullplatform/container_orchestration/gke/variable.tf b/nullplatform/container_orchestration/gke/variables.tf similarity index 100% rename from nullplatform/container_orchestration/gke/variable.tf rename to nullplatform/container_orchestration/gke/variables.tf diff --git a/nullplatform/container_orchestration/oke/provider.tf b/nullplatform/container_orchestration/oke/providers.tf similarity index 100% rename from nullplatform/container_orchestration/oke/provider.tf rename to nullplatform/container_orchestration/oke/providers.tf diff --git a/nullplatform/metrics/provider.tf b/nullplatform/metrics/providers.tf similarity index 100% rename from nullplatform/metrics/provider.tf rename to nullplatform/metrics/providers.tf diff --git a/nullplatform/scope_definition/provider.tf b/nullplatform/scope_definition/providers.tf similarity index 100% rename from nullplatform/scope_definition/provider.tf rename to nullplatform/scope_definition/providers.tf diff --git a/nullplatform/scope_definition_agent_association/provider.tf b/nullplatform/scope_definition_agent_association/providers.tf similarity index 100% rename from nullplatform/scope_definition_agent_association/provider.tf rename to nullplatform/scope_definition_agent_association/providers.tf From 3f8fb8510b071cb1a5ff512149b5ff0fc7ce3a92 Mon Sep 17 00:00:00 2001 From: Gonzalo Rojas Date: Thu, 16 Apr 2026 13:50:20 -0300 Subject: [PATCH 2/5] fix(infra): align dns test with hardening and enrich gcp workload identity docs - Update aws/dns test to assert force_destroy == false, matching the removal of the attribute in 5f1e9fc and documenting the intent to protect Route53 records against accidental deletion - Enrich descriptions on gcp/acr and gcp/artifact-registry so terraform-docs surfaces actionable Workload Identity guidance: - workload_identity_bindings: document the granted role and principal - service_account_email: inline the iam.gke.io/gcp-service-account annotation the consumer needs on the Kubernetes ServiceAccount - Add missing descriptions to artifact-registry outputs --- infrastructure/aws/dns/tests/dns.tftest.hcl | 10 +++++----- infrastructure/gcp/acr/outputs.tf | 2 +- infrastructure/gcp/acr/variables.tf | 2 +- infrastructure/gcp/artifact-registry/outputs.tf | 8 +++++--- infrastructure/gcp/artifact-registry/variables.tf | 2 +- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/infrastructure/aws/dns/tests/dns.tftest.hcl b/infrastructure/aws/dns/tests/dns.tftest.hcl index 00e27eaa..3fce7806 100644 --- a/infrastructure/aws/dns/tests/dns.tftest.hcl +++ b/infrastructure/aws/dns/tests/dns.tftest.hcl @@ -23,16 +23,16 @@ run "private_zone_uses_same_domain" { } } -run "both_zones_force_destroy" { +run "both_zones_are_destroy_protected" { command = plan assert { - condition = aws_route53_zone.public_zone.force_destroy == true - error_message = "Public zone should have force_destroy enabled" + condition = aws_route53_zone.public_zone.force_destroy == false + error_message = "Public zone must not have force_destroy enabled (protects records against accidental deletion)" } assert { - condition = aws_route53_zone.private_zone.force_destroy == true - error_message = "Private zone should have force_destroy enabled" + condition = aws_route53_zone.private_zone.force_destroy == false + error_message = "Private zone must not have force_destroy enabled (protects records against accidental deletion)" } } diff --git a/infrastructure/gcp/acr/outputs.tf b/infrastructure/gcp/acr/outputs.tf index 40391fbe..2bacb500 100644 --- a/infrastructure/gcp/acr/outputs.tf +++ b/infrastructure/gcp/acr/outputs.tf @@ -9,6 +9,6 @@ output "acr_login_server" { } output "service_account_email" { - description = "Service Account email to use with Workload Identity" + description = "GCP Service Account email. Annotate the Kubernetes ServiceAccount bound via workload_identity_bindings with iam.gke.io/gcp-service-account= to impersonate this account from pods." value = google_service_account.artifact_sa.email } diff --git a/infrastructure/gcp/acr/variables.tf b/infrastructure/gcp/acr/variables.tf index cc8ecec3..feb924c6 100644 --- a/infrastructure/gcp/acr/variables.tf +++ b/infrastructure/gcp/acr/variables.tf @@ -38,7 +38,7 @@ variable "tags" { } variable "workload_identity_bindings" { - description = "List of Kubernetes service accounts to bind via Workload Identity" + description = "Kubernetes ServiceAccounts allowed to impersonate the GCP Service Account via Workload Identity. Each entry grants roles/iam.workloadIdentityUser on the GSA to the KSA identified by namespace/ksa_name." type = list(object({ namespace = string ksa_name = string diff --git a/infrastructure/gcp/artifact-registry/outputs.tf b/infrastructure/gcp/artifact-registry/outputs.tf index 39a6ccc0..238f82e1 100644 --- a/infrastructure/gcp/artifact-registry/outputs.tf +++ b/infrastructure/gcp/artifact-registry/outputs.tf @@ -1,12 +1,14 @@ output "repository_id" { - value = google_artifact_registry_repository.registry.repository_id + description = "The Artifact Registry repository ID" + value = google_artifact_registry_repository.registry.repository_id } output "repository_url" { - value = "${var.location}-docker.pkg.dev/${var.project_id}/${var.repository_id}" + description = "The fully-qualified Docker-compatible URL of the Artifact Registry repository" + value = "${var.location}-docker.pkg.dev/${var.project_id}/${var.repository_id}" } output "service_account_email" { - description = "Service Account email to use with Workload Identity" + description = "GCP Service Account email. Annotate the Kubernetes ServiceAccount bound via workload_identity_bindings with iam.gke.io/gcp-service-account= to impersonate this account from pods." value = google_service_account.artifact_sa.email } diff --git a/infrastructure/gcp/artifact-registry/variables.tf b/infrastructure/gcp/artifact-registry/variables.tf index 694c8940..cccd01eb 100644 --- a/infrastructure/gcp/artifact-registry/variables.tf +++ b/infrastructure/gcp/artifact-registry/variables.tf @@ -20,7 +20,7 @@ variable "format" { } variable "workload_identity_bindings" { - description = "List of Kubernetes service accounts to bind via Workload Identity" + description = "Kubernetes ServiceAccounts allowed to impersonate the GCP Service Account via Workload Identity. Each entry grants roles/iam.workloadIdentityUser on the GSA to the KSA identified by namespace/ksa_name." type = list(object({ namespace = string ksa_name = string From 0bff9174a211cc3c457020dbda6835d27d92be04 Mon Sep 17 00:00:00 2001 From: Gonzalo Rojas Date: Thu, 16 Apr 2026 14:57:25 -0300 Subject: [PATCH 3/5] revert(iam): restore verifiedpermissions:* in AVP policy pending validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reverts the least-privilege hardening of the nullplatform AVP policy introduced in 5f1e9fc. The narrowed action list and region condition are still the desired end state, but we lack empirical data to confirm the runtime agent only invokes the 11 allow-listed actions. Leaving the wildcard in place until usage can be validated via CloudTrail analysis of the agent role or a staging deploy. To be revisited — see in-branch discussion. --- infrastructure/aws/iam/agent/main.tf | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/infrastructure/aws/iam/agent/main.tf b/infrastructure/aws/iam/agent/main.tf index c92a30c2..40b240cd 100644 --- a/infrastructure/aws/iam/agent/main.tf +++ b/infrastructure/aws/iam/agent/main.tf @@ -157,33 +157,23 @@ resource "aws_iam_policy" "nullplatform_eks_policy" { # Grant permissions to describe and list EKS cluster resources resource "aws_iam_policy" "nullplatform_avp_policy" { name = "nullplatform_${var.cluster_name}_avp_policy" - description = "Policy for reading and evaluating AVP policy stores" + description = "Policy for managing AVP resources" policy = jsonencode({ "Version" : "2012-10-17", "Statement" : [ { "Effect" : "Allow", "Action" : [ - "verifiedpermissions:IsAuthorized", - "verifiedpermissions:IsAuthorizedWithToken", - "verifiedpermissions:BatchIsAuthorized", - "verifiedpermissions:BatchIsAuthorizedWithToken", - "verifiedpermissions:GetPolicyStore", - "verifiedpermissions:ListPolicyStores", - "verifiedpermissions:GetPolicy", - "verifiedpermissions:ListPolicies", - "verifiedpermissions:GetPolicyTemplate", - "verifiedpermissions:ListPolicyTemplates", - "verifiedpermissions:GetSchema" + "verifiedpermissions:*" ], "Resource" : "*", - "Condition" : { - "StringEquals" : { - "aws:RequestedRegion" : [ - data.aws_region.current.region - ] - } - } + # "Condition" : { + # "StringEquals" : { + # "aws:RequestedRegion" : [ + # data.aws_region.current.region + # ] + # } + # } } ] }) From e027121261780b22f2868ac2836d640469f3ca0c Mon Sep 17 00:00:00 2001 From: Gonzalo Rojas Date: Mon, 20 Apr 2026 14:26:15 -0300 Subject: [PATCH 4/5] fix(dns): use != true in force_destroy assertions to handle null --- infrastructure/aws/dns/tests/dns.tftest.hcl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure/aws/dns/tests/dns.tftest.hcl b/infrastructure/aws/dns/tests/dns.tftest.hcl index 3fce7806..0f89adba 100644 --- a/infrastructure/aws/dns/tests/dns.tftest.hcl +++ b/infrastructure/aws/dns/tests/dns.tftest.hcl @@ -27,12 +27,12 @@ run "both_zones_are_destroy_protected" { command = plan assert { - condition = aws_route53_zone.public_zone.force_destroy == false + condition = aws_route53_zone.public_zone.force_destroy != true error_message = "Public zone must not have force_destroy enabled (protects records against accidental deletion)" } assert { - condition = aws_route53_zone.private_zone.force_destroy == false + condition = aws_route53_zone.private_zone.force_destroy != true error_message = "Private zone must not have force_destroy enabled (protects records against accidental deletion)" } } From 239f9d424c022ebccb779a6c795172e6574eaa9a Mon Sep 17 00:00:00 2001 From: Gonzalo Rojas Date: Mon, 20 Apr 2026 14:26:48 -0300 Subject: [PATCH 5/5] fix(dns): explicitly set force_destroy=false so test assertion is meaningful --- infrastructure/aws/dns/main.tf | 6 ++++-- infrastructure/aws/dns/tests/dns.tftest.hcl | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/infrastructure/aws/dns/main.tf b/infrastructure/aws/dns/main.tf index 91f99576..8281e80a 100644 --- a/infrastructure/aws/dns/main.tf +++ b/infrastructure/aws/dns/main.tf @@ -1,9 +1,11 @@ resource "aws_route53_zone" "public_zone" { - name = var.domain_name + name = var.domain_name + force_destroy = false } resource "aws_route53_zone" "private_zone" { - name = var.domain_name + name = var.domain_name + force_destroy = false vpc { vpc_id = var.vpc_id } diff --git a/infrastructure/aws/dns/tests/dns.tftest.hcl b/infrastructure/aws/dns/tests/dns.tftest.hcl index 0f89adba..3fce7806 100644 --- a/infrastructure/aws/dns/tests/dns.tftest.hcl +++ b/infrastructure/aws/dns/tests/dns.tftest.hcl @@ -27,12 +27,12 @@ run "both_zones_are_destroy_protected" { command = plan assert { - condition = aws_route53_zone.public_zone.force_destroy != true + condition = aws_route53_zone.public_zone.force_destroy == false error_message = "Public zone must not have force_destroy enabled (protects records against accidental deletion)" } assert { - condition = aws_route53_zone.private_zone.force_destroy != true + condition = aws_route53_zone.private_zone.force_destroy == false error_message = "Private zone must not have force_destroy enabled (protects records against accidental deletion)" } }