From 98d7437f455bc9686b74623b97e211b13e7f913e Mon Sep 17 00:00:00 2001 From: David Fernandez Date: Thu, 9 Apr 2026 15:55:48 -0300 Subject: [PATCH 1/2] fix: remove provider --- infrastructure/azure/acr/provider.tf | 7 ------- infrastructure/azure/aks/provider.tf | 6 ------ infrastructure/azure/dns/provider.tf | 7 ------- infrastructure/azure/private_dns/provider.tf | 6 ------ infrastructure/azure/resource_group/provider.tf | 7 ------- infrastructure/azure/vnet/provider.tf | 7 ------- 6 files changed, 40 deletions(-) diff --git a/infrastructure/azure/acr/provider.tf b/infrastructure/azure/acr/provider.tf index ef7f06eb..a2489744 100644 --- a/infrastructure/azure/acr/provider.tf +++ b/infrastructure/azure/acr/provider.tf @@ -8,10 +8,3 @@ terraform { } } -provider "azurerm" { - features {} - resource_provider_registrations = "none" - use_cli = true - subscription_id = var.subscription_id -} - diff --git a/infrastructure/azure/aks/provider.tf b/infrastructure/azure/aks/provider.tf index 7ecaa77c..a2489744 100644 --- a/infrastructure/azure/aks/provider.tf +++ b/infrastructure/azure/aks/provider.tf @@ -8,9 +8,3 @@ terraform { } } -provider "azurerm" { - features {} - resource_provider_registrations = "none" - use_cli = true - subscription_id = var.subscription_id -} diff --git a/infrastructure/azure/dns/provider.tf b/infrastructure/azure/dns/provider.tf index ef7f06eb..a2489744 100644 --- a/infrastructure/azure/dns/provider.tf +++ b/infrastructure/azure/dns/provider.tf @@ -8,10 +8,3 @@ terraform { } } -provider "azurerm" { - features {} - resource_provider_registrations = "none" - use_cli = true - subscription_id = var.subscription_id -} - diff --git a/infrastructure/azure/private_dns/provider.tf b/infrastructure/azure/private_dns/provider.tf index 7ecaa77c..a2489744 100644 --- a/infrastructure/azure/private_dns/provider.tf +++ b/infrastructure/azure/private_dns/provider.tf @@ -8,9 +8,3 @@ terraform { } } -provider "azurerm" { - features {} - resource_provider_registrations = "none" - use_cli = true - subscription_id = var.subscription_id -} diff --git a/infrastructure/azure/resource_group/provider.tf b/infrastructure/azure/resource_group/provider.tf index ef7f06eb..a2489744 100644 --- a/infrastructure/azure/resource_group/provider.tf +++ b/infrastructure/azure/resource_group/provider.tf @@ -8,10 +8,3 @@ terraform { } } -provider "azurerm" { - features {} - resource_provider_registrations = "none" - use_cli = true - subscription_id = var.subscription_id -} - diff --git a/infrastructure/azure/vnet/provider.tf b/infrastructure/azure/vnet/provider.tf index ef7f06eb..a2489744 100644 --- a/infrastructure/azure/vnet/provider.tf +++ b/infrastructure/azure/vnet/provider.tf @@ -8,10 +8,3 @@ terraform { } } -provider "azurerm" { - features {} - resource_provider_registrations = "none" - use_cli = true - subscription_id = var.subscription_id -} - From 4d01fc685cdc3daae61367f306fc226e52cb8558 Mon Sep 17 00:00:00 2001 From: David Fernandez Date: Wed, 1 Jul 2026 13:55:12 -0300 Subject: [PATCH 2/2] feat(iam/agent)!: require explicit assume_role_arns, drop implicit permissions role The agent module no longer injects the k8s permissions role ARN by naming convention into the sts:AssumeRole policy. Callers must now pass every role the agent should assume explicitly via assume_role_arns and/or permissions_roles. - Remove [local.permissions_role_arn] from the assume-role policy Resource - Remove the now-dead permissions_role_name variable, permissions_role_arn local, and nullplatform_agent_permissions_role_arn output - Add a lifecycle precondition requiring at least one assumable role, so an empty Resource (rejected by AWS) fails fast at plan with a clear message - Update tests and README accordingly BREAKING CHANGE: clusters that relied on the implicit permissions role must now pass it explicitly in assume_role_arns. Co-Authored-By: Claude Opus 4.8 (1M context) --- infrastructure/aws/iam/agent/README.md | 32 ++++++------ infrastructure/aws/iam/agent/main.tf | 42 +++++++++------- infrastructure/aws/iam/agent/outputs.tf | 5 -- .../aws/iam/agent/tests/agent.tftest.hcl | 50 +++++++++++-------- infrastructure/aws/iam/agent/variables.tf | 6 --- 5 files changed, 70 insertions(+), 65 deletions(-) diff --git a/infrastructure/aws/iam/agent/README.md b/infrastructure/aws/iam/agent/README.md index accbba59..3dd48090 100644 --- a/infrastructure/aws/iam/agent/README.md +++ b/infrastructure/aws/iam/agent/README.md @@ -2,19 +2,20 @@ ## Description -Creates an IRSA (IAM Roles for Service Accounts) role for a nullplatform agent on EKS, with an assume-role policy allowing the agent to assume a conventional permissions role and any additional roles +Creates an IRSA (IAM Roles for Service Accounts) role for a nullplatform agent on EKS, with an assume-role policy allowing the agent to assume the roles explicitly provided by the caller (via assume_role_arns and/or permissions_roles) ## Architecture -The module uses the terraform-aws-modules/iam//modules/iam-role-for-service-accounts module to create an aws_iam_role with an OIDC trust policy scoped to a specific Kubernetes namespace and service account. An aws_iam_policy (nullplatform_assume_role_policy) is created and attached to the agent role, granting sts:AssumeRole on a conventionally named permissions role ARN, any extra permissions roles, and any caller-supplied assume_role_arns. Optionally, one or more aws_iam_role resources (extra_permissions) are created via for_each from var.permissions_roles, each trusting only the agent role ARN, with aws_iam_role_policy_attachment resources wiring the provided policy ARNs to each extra role. +The module uses the terraform-aws-modules/iam//modules/iam-role-for-service-accounts module to create an aws_iam_role with an OIDC trust policy scoped to a specific Kubernetes namespace and service account. An aws_iam_policy (nullplatform_assume_role_policy) is created and attached to the agent role, granting sts:AssumeRole only on the roles the caller supplies: any extra permissions roles created via var.permissions_roles plus any caller-supplied var.assume_role_arns. The module no longer injects any permissions role by naming convention; a lifecycle precondition requires at least one role to be provided. Optionally, one or more aws_iam_role resources (extra_permissions) are created via for_each from var.permissions_roles, each trusting only the agent role ARN, with aws_iam_role_policy_attachment resources wiring the provided policy ARNs to each extra role. ## Features - Creates IRSA-enabled aws_iam_role scoped to a specific Kubernetes namespace and service account via OIDC provider trust -- Creates aws_iam_policy granting sts:AssumeRole on a conventional permissions role ARN and any additional supplied role ARNs +- Creates aws_iam_policy granting sts:AssumeRole only on the role ARNs explicitly supplied by the caller (no implicit permissions role by convention) +- Requires at least one assumable role (via assume_role_arns or permissions_roles) through a lifecycle precondition - Creates optional extra aws_iam_role resources (permissions_roles) trusted exclusively by the agent role with configurable policy attachments - Attaches additional caller-supplied policy ARNs directly to the agent role via var.additional_policies -- Outputs the agent role ARN, the conventional permissions role ARN, and a map of extra permissions role ARNs for downstream consumption +- Outputs the agent role ARN and a map of extra permissions role ARNs for downstream consumption - Derives deterministic role ARNs from account ID and name locals to avoid circular dependencies between role trust and assume policies ## Basic Usage @@ -26,6 +27,12 @@ module "agent" { agent_namespace = "your-agent-namespace" aws_iam_openid_connect_provider_arn = "your-aws-iam-openid-connect-provider-arn" cluster_name = "your-cluster-name" + + # The agent no longer assumes any role by convention. Pass every role it must + # assume explicitly, e.g. the k8s permissions role created by the k8s scope module: + assume_role_arns = [ + "arn:aws:iam::123456789012:role/nullplatform-your-cluster-name-agent-permissions-role", + ] } ``` @@ -70,7 +77,6 @@ resource "example_resource" "this" { | [assume\_role\_arns](#input\_assume\_role\_arns) | List of IAM role ARNs the agent is allowed to assume via sts:AssumeRole | `list(string)` | `[]` | no | | [aws\_iam\_openid\_connect\_provider\_arn](#input\_aws\_iam\_openid\_connect\_provider\_arn) | ARN of the AWS IAM OIDC provider for EKS service account authentication | `string` | n/a | yes | | [cluster\_name](#input\_cluster\_name) | Name of the cluster where the policy runs | `string` | n/a | yes | -| [permissions\_role\_name](#input\_permissions\_role\_name) | Override for the permissions IAM role name. Defaults to nullplatform-{cluster\_name}-agent-permissions-role | `string` | `""` | no | | [permissions\_roles](#input\_permissions\_roles) | Additional permissions roles created by this module and assumable by the agent role. Map key is a logical name; name overrides the role name (defaults to nullplatform-{cluster\_name}-{key}); policy\_arns are the policy ARNs attached to the role. |
map(object({
name = optional(string)
policy_arns = optional(list(string), [])
}))
| `{}` | no | | [policies\_name\_prefix](#input\_policies\_name\_prefix) | Override for IAM policy name prefix. Defaults to nullplatform\_{cluster\_name} | `string` | `""` | no | | [role\_name](#input\_role\_name) | Override for the IAM role name. Defaults to nullplatform-{cluster\_name}-agent-role | `string` | `""` | no | @@ -81,21 +87,21 @@ resource "example_resource" "this" { | Name | Description | |------|-------------| | [nullplatform\_agent\_extra\_permissions\_role\_arns](#output\_nullplatform\_agent\_extra\_permissions\_role\_arns) | Map of logical name to ARN for each additional permissions role created via permissions\_roles | -| [nullplatform\_agent\_permissions\_role\_arn](#output\_nullplatform\_agent\_permissions\_role\_arn) | Conventional ARN of the permissions role the agent role is allowed to assume. The role itself is created externally (k8s scope tofu module), not by this module. | | [nullplatform\_agent\_role\_arn](#output\_nullplatform\_agent\_role\_arn) | ARN of the agent role |