Skip to content

feat(iam): add Pod Identity support to cert-manager and external-dns modules#409

Merged
jcastiarena merged 13 commits into
mainfrom
feat/cert-manager-external-dns-pod-identity
Jun 26, 2026
Merged

feat(iam): add Pod Identity support to cert-manager and external-dns modules#409
jcastiarena merged 13 commits into
mainfrom
feat/cert-manager-external-dns-pod-identity

Conversation

@jcastiarena

@jcastiarena jcastiarena commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds `identity_mode` variable (`"irsa"` default | `"pod_identity"`) to both `cert_manager` and `external_dns` IAM modules
  • IRSA mode (default): unchanged behavior — uses the `terraform-aws-modules/iam` community module with OIDC federation
  • Pod Identity mode: creates a native `aws_iam_role` with `pods.eks.amazonaws.com` trust principal + `aws_eks_pod_identity_association` resources

Changes

  • `main.tf`: IRSA module gets `count` guard; new `aws_iam_role.pod_identity`, `aws_iam_role_policy_attachment.pod_identity`, and `aws_eks_pod_identity_association.this` resources
  • `variables.tf`: new `identity_mode` variable with validation; `aws_iam_openid_connect_provider_arn` made optional (`default = null`) with cross-variable validation requiring it only for IRSA mode
  • `outputs.tf`: conditional ARN output using `one(resource[*].attr)` pattern
  • Tests: new `*_pod_identity.tftest.hcl` files + mode-exclusivity, output ARN and policy attachment assertions added to existing IRSA tests (28 tests total per module pair)

Backward compatibility

No breaking changes. Default `identity_mode = "irsa"` preserves the existing behavior. `moved` blocks handle the state address change from the `count` refactor on the community submodule — consumers upgrading from v4.5.x see a no-op plan when keeping the default.

Note (mode switching only): deliberately changing `identity_mode` on an existing deployment replaces the IAM role. Both modes use the same role name so `create_before_destroy` is not feasible; cert-manager/external-dns will lose Route53 permissions during the transition until apply completes. Plan carefully before switching modes in production.

Test plan

  • `tofu test` passes for both modules (28 tests, 0 failures)
  • `pre-commit run --all-files` passes (fmt, validate, test, trailing whitespace)
  • IRSA mode: existing behavior unchanged, pod_identity resources confirmed absent
  • Pod Identity mode: correct trust policy (`pods.eks.amazonaws.com` + `sts:TagSession`), associations created with correct namespace/SA keys, IRSA module confirmed absent
  • Validation: `identity_mode = "wireguard"` rejected; `aws_iam_openid_connect_provider_arn` required only for IRSA
  • Validated end-to-end against Galicia 2 environment

🤖 Generated with Claude Code

jcastiarena and others added 11 commits June 25, 2026 14:45
…modules

Add identity_mode variable ('irsa' default | 'pod_identity') to both modules.
Pod Identity mode creates a native aws_iam_role with pods.eks.amazonaws.com trust
and aws_eks_pod_identity_association resources instead of the OIDC community module.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use one(resource[*].attr) instead of resource[0].attr in for_each
  bodies and outputs to avoid plan errors when count = 0
- Make aws_iam_openid_connect_provider_arn optional (default null)
  with cross-variable validation requiring it only for irsa mode
- Add destructive mode-switch warning to identity_mode description
- Add mode-exclusivity test assertions (irsa/pod_identity resources
  must not coexist) and output ARN assertions in both modules

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…refactor

Consumers upgrading from a version where the IRSA submodule had no count
would see destroy+recreate of the IAM role without these moved blocks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… aws_identity_mode=pod_identity

Add aws_identity_mode variable (irsa|pod_identity, default irsa). In pod_identity
mode the eks.amazonaws.com/role-arn annotation is omitted from the cert-manager
service account — EKS Pod Identity injects credentials via the agent instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… aws_identity_mode=pod_identity

Add aws_identity_mode variable (irsa|pod_identity, default irsa). In pod_identity
mode the eks.amazonaws.com/role-arn annotation is omitted from the external-dns
service account — EKS Pod Identity injects credentials via the agent instead.

Validated with tofu validate (tofu test disabled for AWS provider due to
preexisting OCI eager-evaluation bug in locals.tf; commented test added for
when the bug is fixed).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add policy attachment count + role assertions to creates_pod_identity_role
- Add ARN output value assertion (vs mock ARN, not just != null)
- Add pod_identity_does_not_require_oidc_arn run for both modules
- Clarify moved block comment: IRSA path only, pod_identity has no prior state

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d external-dns

- Regenerate BEGIN_TF_DOCS sections via terraform-docs (identity_mode/aws_identity_mode
  now appear in inputs table, aws_iam_openid_connect_provider_arn marked optional,
  new resources listed)
- Update narrative sections to describe both IRSA and Pod Identity modes
- Add Pod Identity usage examples with correct ref=v4.6.0
- Update AI_METADATA descriptions and feature lists

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace WARNING with Note in identity_mode description: the default 'irsa'
is backward compatible with v4.5.x (no state changes on upgrade). Mode-switch
note is preserved but scoped to the deliberate irsa<->pod_identity transition.
Regenerate README TF docs to reflect updated variable description.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaced fabricated hex values with original hashes from before the PR.
These will be stale until the indexing tool reruns — but they are real values,
not invented ones.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The AWS test file was fully commented out citing an OCI eager-evaluation
bug in locals.tf that no longer reproduces. Re-enable it and fix the
expect_failures tests to target the terraform_data.provider_validation
resource (validation lives in preconditions, not variable validation
blocks) and use empty strings instead of null. Add nullable = false to
the AWS string variables so an explicit null fails clearly instead of
crashing length().

Recovers 9 tests, including aws_pod_identity_omits_role_annotation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread infrastructure/aws/iam/external_dns/variables.tf
…ernal-dns-pod-identity

# Conflicts:
#	infrastructure/aws/iam/cert_manager/README.md
#	infrastructure/aws/iam/external_dns/README.md
@jcastiarena jcastiarena merged commit 1f4e5ff into main Jun 26, 2026
44 checks passed
@jcastiarena jcastiarena deleted the feat/cert-manager-external-dns-pod-identity branch June 26, 2026 22:33
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.

3 participants