From ad8e58ad196c39308c83a46f017b89876edb7141 Mon Sep 17 00:00:00 2001 From: Alex Bezpalko Date: Fri, 31 Jul 2026 15:22:08 +0200 Subject: [PATCH 1/3] =?UTF-8?q?feat!:=20remove=20module=20provider=20"aws"?= =?UTF-8?q?=20block=20=E2=80=94=20caller=20owns=20credentials=20(v5.0.1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING (operational, not API): the module no longer declares its own provider "aws". As a child module, a self-declared provider block takes precedence for the modules resources and IGNORES the callers provider, stripping the wrapper control over credentials (assume_role / profile / region) and default_tags — the deprecated pattern, and the root cause of the STSaaS-account 403 workaround in atlantis.yaml (the module credential-less provider ran as ambient atlantis-sa instead of the assumed STSaaS role). The module keeps its provider *requirement* (versions.tf required_providers). Now every module.comet resource inherits the CALLERs provider. Wrapper migration required when bumping to v5.0.1: * ensure the wrapper provider "aws" carries region + assume_role/profile (stsaasuat already does, via var.provider_assume_role_arn) * move default_tags (Terraform / Environment / common_tags) onto the wrapper provider — the module no longer sets them * the atlantis.yaml assume-role-and-export-creds shell hack for the stsaas workflow can then be replaced with a normal provider-level assume_role No aliased/region-specific providers exist in the module (checked: no configuration_aliases, no provider = aws.*), so single-provider inheritance is safe. terraform init + validate pass. Co-Authored-By: Claude Opus 4.8 (1M context) --- providers.tf | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/providers.tf b/providers.tf index f4d10b7..fe83b83 100644 --- a/providers.tf +++ b/providers.tf @@ -1,13 +1,14 @@ -provider "aws" { - region = var.region - - default_tags { - tags = merge( - { - Terraform = "true" - }, - var.environment_tag != "" ? { Environment = var.environment_tag } : {}, - var.common_tags - ) - } -} +# No provider "aws" configuration block here — on purpose. +# +# This module is consumed as a child module (module "comet" { source = "...?ref=" }), +# so it must NOT declare its own provider config. A child module's provider block +# takes precedence for the module's resources and IGNORES the caller's provider, +# which strips the wrapper's control over credentials (assume_role / profile / +# region) and default_tags. That is the deprecated pattern. +# +# The module only declares its provider *requirement* (versions.tf → +# required_providers). Credential + region + default_tags configuration is owned +# by the CALLER's `provider "aws"` block, which the module inherits. +# +# Wrappers: put region, the assume_role/profile, and default_tags on YOUR +# provider "aws" — everything in this module runs through it. From a136e0d93985ac9c8f74891a654f5a730deae68c Mon Sep 17 00:00:00 2001 From: Alex Bezpalko Date: Fri, 31 Jul 2026 15:32:18 +0200 Subject: [PATCH 2/3] chore(deps): set module aws provider floor to >= 6.52 (matches upstream eks) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the loose/inconsistent aws constraints (~> 6.0 root, >= 6.0 comet_eks) with an honest floor: >= 6.52, the minimum required by the pinned terraform-aws-modules/eks ~> 21.24. Anything looser was misleading — init could never resolve below 6.52 anyway. No upper bound and no bad-build exclusion (e.g. != 6.57.0) in the module: those are deployment policy and stay in the wrappers. Effective resolved constraint with the stsaasuat wrapper is >= 6.52, < 7.0, != 6.57.0. Co-Authored-By: Claude Opus 4.8 (1M context) --- modules/comet_eks/versions.tf | 7 +++++-- versions.tf | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/comet_eks/versions.tf b/modules/comet_eks/versions.tf index 0500978..3060ce7 100644 --- a/modules/comet_eks/versions.tf +++ b/modules/comet_eks/versions.tf @@ -1,8 +1,11 @@ terraform { required_providers { aws = { - source = "hashicorp/aws" - version = ">= 6.0" + source = "hashicorp/aws" + # Floor = terraform-aws-modules/eks ~> 21.24 requires aws >= 6.52. Keep in + # sync with the root module versions.tf. Ceiling/bad-build pins live in the + # wrapper, not here. + version = ">= 6.52" } time = { source = "hashicorp/time" diff --git a/versions.tf b/versions.tf index 940e686..cd3ae62 100644 --- a/versions.tf +++ b/versions.tf @@ -3,8 +3,11 @@ terraform { required_providers { aws = { - source = "hashicorp/aws" - version = "~> 6.0" + source = "hashicorp/aws" + # Floor = the tightest real dependency: terraform-aws-modules/eks ~> 21.24 + # requires aws >= 6.52. No upper bound / bad-build exclusion here — that is + # deployment policy (the wrapper pins e.g. "~> 6.50, != 6.57.0"). + version = ">= 6.52" } random = { source = "hashicorp/random" From fab7a312edbe93e39796de9a20f02b02f6bf865e Mon Sep 17 00:00:00 2001 From: Alex Bezpalko Date: Fri, 31 Jul 2026 16:46:13 +0200 Subject: [PATCH 3/3] fix(eks): guard provider-region == var.region; refresh stale comet_eks README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses baz review on #57: * Region consistency (medium): with the module provider block removed, the provider region now comes from the caller while several resources still key off var.region as a string — notably the Karpenter controller IAM policy (EC2 ARNs scoped to arn:aws:ec2:${var.region}:... and an aws:RequestedRegion == var.region condition). If the caller provider region diverges, those grants target the wrong region and deny. Add data.aws_region.current + a terraform_data precondition that fails fast at plan when they mismatch. (Kept var.region in the ARNs — it is the intended region; the guard just enforces the provider agrees. Lighter and clearer than threading data.aws_region through every ARN.) * Stale docs (low): modules/comet_eks/README.md advertised aws >= 5.0 and a kubernetes >= 2.10 requirement. Update to aws >= 6.52 (matches versions.tf) and drop kubernetes (removed in v5.0.0); add the time provider the module actually uses. Skipped baz driver-README direct-consumer note: this module is only consumed as a wrapper child (no backend of its own); the new precondition already fails fast on a region mismatch, covering the substantive concern. Co-Authored-By: Claude Opus 4.8 (1M context) --- modules/comet_eks/README.md | 7 ++++--- modules/comet_eks/main.tf | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/modules/comet_eks/README.md b/modules/comet_eks/README.md index 8f60bf2..6ca41e0 100644 --- a/modules/comet_eks/README.md +++ b/modules/comet_eks/README.md @@ -2,14 +2,15 @@ | Name | Version | |------|---------| -| [aws](#requirement\_aws) | >= 5.0 | -| [kubernetes](#requirement\_kubernetes) | >= 2.10 | +| [aws](#requirement\_aws) | >= 6.52 | +| [time](#requirement\_time) | >= 0.9 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | >= 5.0 | +| [aws](#provider\_aws) | >= 6.52 | +| [time](#provider\_time) | >= 0.9 | ## Modules diff --git a/modules/comet_eks/main.tf b/modules/comet_eks/main.tf index 9d32b25..05931db 100644 --- a/modules/comet_eks/main.tf +++ b/modules/comet_eks/main.tf @@ -1068,6 +1068,26 @@ module "cloudwatch_exporter_irsa_role" { data "aws_caller_identity" "current" {} +# Region consistency guard. +# +# This module no longer declares its own provider "aws" (the caller owns it), so +# the provider's region comes from the wrapper. Several resources below still key +# off var.region as a string — the Karpenter controller IAM policy scopes EC2 ARNs +# to arn:aws:ec2:${var.region}:... and pins an aws:RequestedRegion == var.region +# condition. If the caller's provider region diverges from var.region, Karpenter's +# grants would target the wrong region and deny actions. Fail fast at plan time +# instead. (.region is the aws provider v6 attribute; .name is deprecated.) +data "aws_region" "current" {} + +resource "terraform_data" "region_consistency" { + lifecycle { + precondition { + condition = data.aws_region.current.region == var.region + error_message = "The AWS provider region (${data.aws_region.current.region}) must match var.region (${var.region}). This module inherits the caller's provider — set the wrapper's provider \"aws\" { region = ... } to the same region you pass as region/eks region, or the Karpenter IAM ARNs and aws:RequestedRegion condition will target the wrong region." + } + } +} + # Tag private subnets for Karpenter node discovery resource "aws_ec2_tag" "karpenter_subnet" { for_each = var.enable_karpenter ? toset(var.eks_private_subnets) : toset([])