Skip to content

Commit 5a3406e

Browse files
Benbentwoclaude
andcommitted
docs: add next-gen component migration guide blog post
New blog post explaining how to migrate components to use Atmos Auth and the next-generation authentication approach, including practical guidance on using Atmos mixins to update any component regardless of version. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent b46e686 commit 5a3406e

1 file changed

Lines changed: 252 additions & 0 deletions

File tree

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
---
2+
title: "Migrating to Next-Gen Components with Atmos Auth"
3+
slug: nextgen-component-migration
4+
authors: [Benbentwo]
5+
tags: [reference-architecture, identity, migration, atmos-auth, components]
6+
date: 2026-02-25
7+
---
8+
import Intro from '@site/src/components/Intro';
9+
import Steps from '@site/src/components/Steps';
10+
11+
<Intro>
12+
Over the past couple of months, we've shipped two changes that fundamentally simplify how components authenticate with AWS: **Atmos Auth** and the **deprecation of `account-map`**. This post is a practical migration guide for upgrading any component — old or new — to work with the next generation of the Cloud Posse Reference Architecture.
13+
</Intro>
14+
15+
<!--truncate-->
16+
17+
## What Changed
18+
19+
Two major improvements landed recently:
20+
21+
| Change | What It Does |
22+
|--------|--------------|
23+
| **Atmos Auth** | Handles AWS authentication before Terraform runs no more dynamic role assumption in `providers.tf` |
24+
| **Account-Map Deprecation** | Replaces the `account-map` Terraform component with a static YAML variable, eliminating a critical deploy-time dependency |
25+
26+
Together, these remove the need for `account-map`, `aws-teams`, and `aws-team-roles`. If you missed the announcement, see [Reference Architecture v2: Deprecating Account-Map](/blog/deprecate-account-map/).
27+
28+
## How to Tell Which Generation You're On
29+
30+
The quickest way to tell is to look at your component's `providers.tf`.
31+
32+
### Legacy (Account-Map + Team Roles)
33+
34+
If your `providers.tf` looks like this, you're on the older generation:
35+
36+
```hcl
37+
provider "aws" {
38+
region = var.region
39+
40+
# Profile is deprecated in favor of terraform_role_arn. When profiles are not in use, terraform_profile_name is null.
41+
profile = module.iam_roles.terraform_profile_name
42+
43+
dynamic "assume_role" {
44+
# module.iam_roles.terraform_role_arn may be null, in which case do not assume a role.
45+
for_each = compact([module.iam_roles.terraform_role_arn])
46+
content {
47+
role_arn = assume_role.value
48+
}
49+
}
50+
}
51+
52+
module "iam_roles" {
53+
source = "../account-map/modules/iam-roles"
54+
context = module.this.context
55+
}
56+
```
57+
58+
This pattern depends on `account-map`, `aws-teams`, and `aws-team-roles` being deployed. The `iam_roles` module reaches into the `account-map` remote state to figure out which role to assume.
59+
60+
### Next-Gen (Atmos Auth)
61+
62+
With Atmos Auth, authentication happens _before_ Terraform runs. The provider is simply:
63+
64+
```hcl
65+
provider "aws" {
66+
region = var.region
67+
}
68+
```
69+
70+
That's it. Whatever AWS credentials Atmos Auth has configured for the target account are already active. No dynamic role assumptions, no remote state lookups, no `account-map` dependency.
71+
72+
The full next-gen `providers.tf` also includes the `account_map` variable (a static map of account names to IDs) and a dummy `iam_roles` module for backward compatibility:
73+
74+
```hcl
75+
variable "account_map_enabled" {
76+
type = bool
77+
description = "Enable the account map component"
78+
default = false
79+
}
80+
81+
variable "account_map" {
82+
type = object({
83+
full_account_map = map(string)
84+
audit_account_account_name = optional(string, "")
85+
root_account_account_name = optional(string, "")
86+
identity_account_account_name = optional(string, "")
87+
aws_partition = optional(string, "aws")
88+
iam_role_arn_templates = optional(map(string), {})
89+
})
90+
description = "Map of account names to account IDs."
91+
default = {
92+
full_account_map = {}
93+
audit_account_account_name = ""
94+
root_account_account_name = ""
95+
identity_account_account_name = ""
96+
aws_partition = "aws"
97+
iam_role_arn_templates = {}
98+
}
99+
}
100+
101+
provider "aws" {
102+
region = var.region
103+
}
104+
105+
# Dummy module to satisfy legacy references to module.iam_roles
106+
module "iam_roles" {
107+
source = "cloudposse/label/null"
108+
context = module.this.context
109+
}
110+
```
111+
112+
## Migrating Any Component with Mixins
113+
114+
Here's the key insight: **you don't need to manually rewrite `providers.tf`**. We publish Atmos mixins that handle this for you. Just add two lines to your component's `component.yaml`.
115+
116+
### The Two Mixins
117+
118+
Add the following to the `mixins` section of your `component.yaml`:
119+
120+
```yaml
121+
# components/terraform/<component-name>/component.yaml
122+
apiVersion: atmos/v1
123+
kind: ComponentVendorConfig
124+
spec:
125+
source:
126+
uri: github.com/cloudposse-terraform-components/aws-<component>.git//src?ref={{ .Version }}
127+
version: v1.x.x
128+
included_paths:
129+
- "**/**"
130+
excluded_paths:
131+
- "providers.tf" # Exclude the upstream providers.tf
132+
mixins:
133+
# Use upstream mixin for providers.tf without account-map dependency
134+
- uri: https://raw.githubusercontent.com/cloudposse-terraform-components/mixins/{{ .Version }}/src/mixins/provider-without-account-map.tf
135+
version: v0.3.2
136+
filename: providers.tf
137+
# Use upstream mixin for account verification
138+
- uri: https://raw.githubusercontent.com/cloudposse-terraform-components/mixins/{{ .Version }}/src/mixins/account-verification.mixin.tf
139+
version: v0.3.2
140+
filename: account-verification.mixin.tf
141+
```
142+
143+
Then vendor (or re-vendor) the component:
144+
145+
```bash
146+
atmos vendor pull -c <component-name>
147+
```
148+
149+
### What Each Mixin Does
150+
151+
**`provider-without-account-map.tf`** (vendored as `providers.tf`)
152+
153+
This replaces the legacy `providers.tf`. It:
154+
155+
<Steps>
156+
1. Defines the `account_map_enabled` and `account_map` variables so your component can receive the static account map from stack configuration
157+
1. Configures the AWS provider with just `region = var.region` Atmos Auth handles the credentials
158+
1. Includes a dummy `iam_roles` module so existing code that references `module.iam_roles` doesn't break
159+
</Steps>
160+
161+
**`account-verification.mixin.tf`**
162+
163+
This is a safety net. It verifies that the AWS account you're deploying to is the one you _intend_ to deploy to. If Atmos Auth is misconfigured and you're authenticated to the wrong account, this mixin will catch it before Terraform makes any changes.
164+
165+
## Step-by-Step Migration
166+
167+
### 1. Set Up Atmos Auth
168+
169+
Configure Atmos Auth profiles in your `atmos.yaml`. This tells Atmos how to authenticate to each account before running Terraform:
170+
171+
```bash
172+
# Authenticate with your profile
173+
atmos auth login
174+
```
175+
176+
See [Atmos Auth](https://atmos.tools/cli/auth) for configuration details.
177+
178+
### 2. Add the Static Account Map
179+
180+
Define account IDs in your stack defaults so components can look up accounts without remote state:
181+
182+
```yaml
183+
# stacks/orgs/acme/_defaults.yaml
184+
vars:
185+
account_map_enabled: false
186+
account_map:
187+
full_account_map:
188+
core-root: "123456789012"
189+
core-artifacts: "234567890123"
190+
core-audit: "345678901234"
191+
core-auto: "456789012345"
192+
plat-dev: "567890123456"
193+
plat-staging: "678901234567"
194+
plat-prod: "789012345678"
195+
root_account_account_name: core-root
196+
audit_account_account_name: core-audit
197+
```
198+
199+
### 3. Update component.yaml
200+
201+
For each component, add the mixins and exclude the upstream `providers.tf` as shown above. Then re-vendor:
202+
203+
```bash
204+
atmos vendor pull -c <component-name>
205+
```
206+
207+
### 4. Verify
208+
209+
Run a plan against a non-production environment to confirm everything works:
210+
211+
```bash
212+
atmos terraform plan <component-name> -s plat-ue1-dev
213+
```
214+
215+
The plan should succeed without any `account-map` remote state lookups.
216+
217+
## Works Regardless of Component Version
218+
219+
The mixins approach works whether you're running the latest component versions or older ones. The key is the `excluded_paths` and `mixins` configuration in `component.yaml`:
220+
221+
<Steps>
222+
1. `excluded_paths: ["providers.tf"]` Throws away whatever `providers.tf` ships with the component
223+
1. The `provider-without-account-map.tf` mixin replaces it with the next-gen version
224+
1. The `account-verification.mixin.tf` mixin adds the safety check
225+
</Steps>
226+
227+
This means you can migrate components incrementally update one at a time, test, and move on without needing to upgrade the component source code itself.
228+
229+
## Summary
230+
231+
| Before | After |
232+
|--------|-------|
233+
| `account-map` component deployed first | Static `account_map` variable in stack config |
234+
| `aws-teams` + `aws-team-roles` for IAM | AWS SSO Permission Sets + Atmos Auth |
235+
| Dynamic role assumption in `providers.tf` | Atmos Auth handles credentials before Terraform |
236+
| Complex `iam_roles` module in every component | Simple `region = var.region` provider |
237+
| Tight coupling between components via remote state | Components are independent |
238+
239+
The net result: fewer components to manage, simpler authentication, no deploy ordering dependencies, and a provider configuration you can actually read at a glance.
240+
241+
## Learn More
242+
243+
<Steps>
244+
1. [Deprecating Account-Map](/blog/deprecate-account-map/) The full deprecation announcement
245+
1. [Migrate from Account-Map](/layers/project/tutorials/migrate-from-account-map/) Detailed step-by-step migration guide
246+
1. [Atmos Auth](https://atmos.tools/cli/auth) Authentication configuration reference
247+
1. [How to Log into AWS](/layers/identity/how-to-log-into-aws/) Authentication workflows for human users
248+
</Steps>
249+
250+
:::tip Need Help?
251+
Migrating core authentication infrastructure is a significant change. If you need assistance, reach out in the [SweetOps Slack](https://cloudposse.com/slack) or contact [Cloud Posse support](https://cloudposse.com/support).
252+
:::

0 commit comments

Comments
 (0)