Skip to content

feat(iam/agent): split agent role into agent + permissions roles#397

Merged
davidf-null merged 22 commits into
mainfrom
feat/assume-rol
Jun 25, 2026
Merged

feat(iam/agent): split agent role into agent + permissions roles#397
davidf-null merged 22 commits into
mainfrom
feat/assume-rol

Conversation

@davidf-null

@davidf-null davidf-null commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Qué cambia

Aplica separación de privilegios al módulo infrastructure/aws/iam/agent. El rol IRSA del agente deja de cargar las políticas de workload directamente: ahora solo tiene una política sts:AssumeRole y asume un rol de permisos separado que concentra las políticas Route53/EKS/ELB/AVP y que confía únicamente en el rol agente. Además se agrega soporte para crear N roles de permisos adicionales vía permissions_roles.

Arquitectura resultante

Service Account (K8s)
   │ OIDC / IRSA
   ▼
Rol agente: nullplatform-{cluster}-agent-role
   │  política única: sts:AssumeRole → [ rol default, *roles extra, *assume_role_arns ]
   │  + additional_policies
   ▼ (assume)
Rol de permisos default: nullplatform-{cluster}-agent-permissions-role  (NUEVO)
   │   trust: principal = ARN del rol agente
   │   políticas pegadas: route53, eks, elb, avp
   │
   └── Roles de permisos extra (for_each sobre permissions_roles)         (NUEVO)
         trust: principal = ARN del rol agente
         políticas pegadas: las policy_arns que le pases

Detalles

  • Rol agente: solo sts:AssumeRole (rol default + roles extra + assume_role_arns) + additional_policies.
  • Rol de permisos default (nuevo): aws_iam_role que confía solo en el rol agente, con las 4 políticas de workload pegadas.
  • Roles de permisos extra (nuevo): var.permissions_roles (mapa) crea roles adicionales con for_each, cada uno confiando en el agente y con sus policy_arns pegados.
  • Los ARNs se derivan de los nombres + aws_caller_identity para evitar la dependencia circular entre roles.
  • assume_role_policy ahora siempre se crea (antes condicional). moved block migra el state de nullplatform_assume_role_policy[0]nullplatform_assume_role_policy.
  • Nuevas variables permissions_role_name, permissions_roles. Nuevos outputs nullplatform_agent_permissions_role_arn, nullplatform_agent_extra_permissions_role_arns.

⚠️ Breaking change

El token IRSA ya no tiene permisos Route53/EKS/ELB/AVP de forma directa. El agente debe asumir el rol de permisos (output nullplatform_agent_permissions_role_arn) para usarlos. Coordinar el cambio del lado del runtime del agente.

Testing

  • tofu fmt -check, tofu validate
  • tofu test12/12 pass (incluye naming, trust, attachments, assume targeting del rol default, suma de assume_role_arns, y los roles extra: creación condicional, naming/override, trust y inclusión en la assume policy).

Spec de diseño: docs/superpowers/specs/2026-06-19-iam-agent-role-split-design.md

🤖 Generated with Claude Code

David Fernandez and others added 19 commits April 9, 2026 15:55
…ns roles

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apply privilege separation to the agent IAM module. The IRSA agent role
no longer carries the workload policies directly; it only holds an
sts:AssumeRole policy and assumes a separate permissions role that holds
the Route53/EKS/ELB/AVP policies and trusts only the agent role.

- agent role: only sts:AssumeRole (permissions role + assume_role_arns)
  plus additional_policies
- new permissions role (nullplatform-{cluster}-agent-permissions-role)
  with the four workload policies attached, trusting the agent role
- ARNs derived from names + caller account id to avoid a circular
  dependency between the two roles
- assume_role_policy is now always created (moved block migrates it from
  the previous conditional [0] address)
- new permissions_role_name variable and
  nullplatform_agent_permissions_role_arn output

BREAKING CHANGE: the IRSA token no longer has Route53/EKS/ELB/AVP
permissions directly. The agent must assume the permissions role (exposed
via the nullplatform_agent_permissions_role_arn output) to use them.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add var.permissions_roles (map) to create additional permissions roles
assumable by the agent role, on top of the default permissions role.

- each entry creates an aws_iam_role via for_each, trusting only the
  agent role, with the given policy_arns attached
- names/ARNs are computed from name + caller account id (like the default
  role) so the agent assume policy stays deterministic and free of
  circular dependencies
- the agent sts:AssumeRole policy now targets the default permissions
  role + every extra role + assume_role_arns
- new output nullplatform_agent_extra_permissions_role_arns (map of
  logical name to ARN)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
David Fernandez and others added 2 commits June 23, 2026 18:37
The default permissions role (nullplatform_agent_permissions) and its workload
policies (Route53, ELB, EKS, AVP) are no longer created by this module. They are
now provisioned per-cluster by the k8s scope's OpenTofu module
(scopes: k8s/scope/tofu/iam/modules).

This module keeps only the agent IRSA role and its sts:AssumeRole policy, which
still authorizes assuming the permissions role by its conventional ARN
(nullplatform-{cluster_name}-agent-permissions-role). The output now returns
that computed ARN instead of a created resource.

Removed: nullplatform_agent_permissions role, its 4 policy attachments, the 4
workload policies, and the now-unused aws_region data source. Tests and README
updated accordingly.

NOTE: existing consumers will destroy the permissions role on next apply; the
scope module must create the replacement under the same conventional name.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@davidf-null davidf-null reopened this Jun 24, 2026
@davidf-null davidf-null changed the title feat(iam/agent)!: split agent role into agent + permissions roles feat(iam/agent): split agent role into agent + permissions roles Jun 25, 2026
@davidf-null davidf-null merged commit 9df28f5 into main Jun 25, 2026
44 checks passed
@davidf-null davidf-null deleted the feat/assume-rol branch June 25, 2026 15:43
This was referenced Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants