# Multi-account

> Onboard every AWS account in your organization at once, from the dashboard or by deploying one CloudFormation StackSet in the management account, by hand or with Terraform.

Source: https://docs.levelfour.ai/connectors/aws/multi-account


If your company uses AWS Organizations, you can onboard every member account in one deployment. CloudFormation StackSets creates the LevelFour cross-account role in every account under your deployment target: your organization's root, which covers every account, or a specific OU, which covers a subset. Accounts that join later are covered too.

If you only have a handful of accounts or you do not use AWS Organizations, see the [single-account path](/connectors/aws/single-account) instead.

## Self-service path (recommended)

The whole flow runs from the LevelFour dashboard without an onboarding contact in the loop. Go to **Connect Providers > AWS** in the dashboard (`https://dashboard.levelfour.ai/connect-accounts/aws`), switch the tab to **AWS Organization**, paste your AWS Organizations **root ID** (`r-...`) or an **OU ID** (`ou-...-...`) into the input, then click **Connect via AWS Console**.

The dashboard opens AWS Console with the v2 StackSet wrapper template fully pre-filled: handshake, per-click integration ID, pingback ARN and the target ID are all populated. One click on **Create stack** kicks off the deploy.

Once the wrapper stack finishes in your management account, LevelFour verifies the role and registers every active member account.

> **Success**
>
> The dashboard flips to **Connected** with the full discovered list within ~30 seconds. That is the whole confirmation, and there is nothing to send us.

You do not need to run the preflight script for this path. The dashboard collects the one piece of information the AWS Console cannot pre-fill itself, your Root or OU ID. The `Find this →` link in the dashboard input opens the AWS Organizations console where the Root ID is shown at the top of the accounts tree.

## How it works

You deploy a small **wrapper template** in your management account. The wrapper contains a `AWS::CloudFormation::StackSet` resource that references the standard LevelFour onboarding template and fans it out to every account under the deployment target you specify (root or OU).

* One deploy, one approval, the same as the single-account Launch Stack flow
* Auto-deployment is enabled by default
* LevelFour discovers all your accounts via AWS Organizations after deployment and locates the role in each at `arn:aws:iam::<account_id>:role/LevelFourCrossAccountRole`, so you do not copy any role ARNs back to LevelFour
* Each account gets the read-only `LevelFourCrossAccountRole` plus an empty `LevelFourSavingsExec` role for [Automated Savings](/connectors/aws/automated-savings). See [what the stack creates](/connectors/aws/single-account#what-the-stack-creates)

## Prerequisites

These need to be true before you deploy.

### AWS Organizations is in "all features" mode

Open the AWS Organizations console > **Settings**. The "Feature set" must show **All features**. If it shows "Consolidated billing," click **Begin process to enable all features** and have every member account accept the invitation before continuing.

### Trusted access for CloudFormation StackSets is enabled

This is a **two-sided** toggle. Service-managed StackSets need permission from both Organizations and CloudFormation, and these are activated separately.

**Organizations side.** Open the AWS Organizations console > **Services**. Find **CloudFormation StackSets** and confirm **Trusted access** is **Enabled**. If it is disabled:

```bash
aws organizations enable-aws-service-access \
  --service-principal=member.org.stacksets.cloudformation.amazonaws.com
```

**CloudFormation side.** Activate Organizations access on the CloudFormation StackSets service itself. That is a separate toggle, it is not enabled by default, and it is per-region:

```bash
aws cloudformation activate-organizations-access --region us-east-1
```

You can confirm it is on with the command below, which prints `{"Status": "ENABLED"}`:

```bash
aws cloudformation describe-organizations-access --region us-east-1
```

> **Warning**
>
> Skip the CloudFormation-side activation and the StackSet deploys with the misleading error `You must enable organizations access to operate a service managed stack set`, which points at the toggle you already enabled. The preflight script catches this for you.

### You are signed in to the management account

The Launch Stack link must be opened in the AWS Organizations management account (or in a delegated CloudFormation StackSets admin account). The top-right account selector in the AWS console must match.

### No SCP blocks IAM role creation in the target OU

If your organization uses Service Control Policies, none of the SCPs attached to the OU you will target may deny `iam:CreateRole`, `iam:AttachRolePolicy`, or `iam:PutRolePolicy` for roles named `LevelFourCrossAccountRole`. If you are not sure, [run the preflight check](#run-the-preflight-check). It cannot check SCPs directly, but a dry-run deploy against one account in the OU will surface any block.

## Manual path

These steps are the fallback for when you prefer to deploy via the AWS CLI or IaC, or cannot reach the dashboard from the management account.

### Run the preflight check

In AWS CloudShell signed in to your management account, run:

```bash
curl -fsSL https://cf-templates-1bsphth8u70q9-us-east-1.s3.amazonaws.com/onboarding/v1/levelfour-preflight.sh | bash
```

One line per check:

```text
Running LevelFour onboarding preflight...

[OK]   Organizations in all-features mode
[OK]   Organizations trusted access for StackSets enabled
[OK]   CloudFormation Organizations access activated
[OK]   Running from management account (123456789012)

Available deployment targets (pick one as TargetOUId in the next step):

  Root: r-abcd  (Root)  -> onboards EVERY account in the organization
  No OUs configured. Use the root ID above to onboard every account.

Preflight complete.
```

To read the script first:

```bash
curl -fsSL https://cf-templates-1bsphth8u70q9-us-east-1.s3.amazonaws.com/onboarding/v1/levelfour-preflight.sh -o preflight.sh
less preflight.sh
bash preflight.sh
```

Pick a target ID from the output:

* The **root ID** (e.g. `r-abcd`) onboards every account in your organization in one shot. Use this for the simplest rollout.
* An **OU ID** (e.g. `ou-abcd-12345678`) scopes the rollout to a subset (e.g. start with `Non-Production`, add `Production` later by re-running with a different OU).

### Deploy the StackSet

> **Warning**
>
> AWS Organizations excludes the **management account** from SERVICE_MANAGED StackSet targeting, so the StackSet never reaches it. The Launch Stack wrapper, which the Terraform tab also deploys, covers it with an inline role. On the StackSets console and AWS CLI paths you deploy the role there yourself, and skipping that leaves LevelFour unable to call `organizations:ListAccounts` in your management account.

**Launch Stack**

Recommended. This is the equivalent of the single-account Launch Stack link, but it deploys a StackSet, and its wrapper stack creates the role in your management account as well. Sign in to your management account, then open:

```text
https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/quickcreate?templateURL=https://cf-templates-1bsphth8u70q9-us-east-1.s3.amazonaws.com/onboarding/v2/onboarding-levelfour-stackset-wrapper.template.json&stackName=LevelFour-Onboarding&param_LevelFourHandshakeID=&param_TargetOUId=
```

Enter the two parameters:

* **LevelFourHandshakeID**: the value LevelFour provided
* **TargetOUId**: the root ID or OU ID from the preflight output

At the bottom of the page, tick:

> I acknowledge that AWS CloudFormation might create IAM resources with custom names.

Click **Create stack**. CloudFormation provisions the StackSet, which deploys the role to every account under the target. Status reaches `CREATE_COMPLETE` once all per-account stacks succeed, typically 2 to 5 minutes for a small target and longer for larger ones.

**StackSets console**

Use this if you want to see and confirm every StackSet option before clicking Create. Creating the StackSet from the console rather than through the Launch Stack wrapper template deploys the role only to accounts under your target OU or root, and this path has no inline role for the management account. Item 9 covers it. The **Launch Stack** tab does both in one deploy.

1. Console > **CloudFormation** > **StackSets** > **Create StackSet**
2. **Permissions** > **Permission model:** Service-managed permissions
3. **Prerequisite - Prepare template** > **Prepare template:** Template is ready
4. **Specify template** > **Template source:** Amazon S3 URL > paste:
   ```text
   https://cf-templates-1bsphth8u70q9-us-east-1.s3.amazonaws.com/onboarding/v2/onboarding-levelfour-cloudformation-template.json
   ```
   Click **Next**.
5. **Specify StackSet details:**

   * **StackSet name:** `LevelFour-Onboarding`
   * **Parameters > `LevelFourHandshakeID`:** your handshake value

   Click **Next**.
6. **Configure StackSet options:**

   * **Tags:** leave empty (optional)
   * **Execution configuration > Managed execution:** leave **Inactive** (the default, and fine for a one-shot onboarding deploy; "Active" only matters if you will run concurrent StackSet operations)
   * **Capabilities:** tick **I acknowledge that AWS CloudFormation might create IAM resources with custom names**

   Click **Next**.
7. **Set deployment options:**

   * **Add stacks to stack set:** Deploy new stacks (default)
   * **Deployment targets:**
     * If you are onboarding the whole organization, pick **Deploy to organization**. No OU ID input needed, because AWS targets every member account under the root.
     * If you are scoping to a specific OU, pick **Deploy to organizational units (OUs)** and paste the OU ID from the preflight.
   * **Auto-deployment options:**
     * **Automatic deployment:** Activated
     * **Account removal behavior:** Delete stacks
     * **Stack set dependencies:** leave empty
   * **Specify Regions:** from the dropdown, add `US East (N. Virginia) us-east-1` only. IAM is global, so one region is enough.
   * **Deployment options:** leave the defaults (Maximum concurrent accounts = 1, Failure tolerance = 0, Region concurrency = Sequential, Concurrency mode = Strict failure tolerance). For orgs with 100+ accounts where the rollout takes long, you can raise concurrency here. The defaults are safest.

   Click **Next**.
8. **Review**, then click **Submit**.
9. **Deploy the role to the management account.** Go through the [single-account flow](/connectors/aws/single-account) once in the management account with the same handshake ID. Skip this only if you do not need LevelFour to call `organizations:ListAccounts` from your management account (rare).

**AWS CLI**

For IaC-first teams. The first two commands create the StackSet and its stack instances, which reach member accounts only. The third deploys the same per-account template into the management account with the same handshake, which is what the [single-account flow](/connectors/aws/single-account) does from the console. The **Launch Stack** tab handles both in one deploy.

```bash
aws cloudformation create-stack-set \
  --stack-set-name LevelFour-Onboarding \
  --template-url https://cf-templates-1bsphth8u70q9-us-east-1.s3.amazonaws.com/onboarding/v2/onboarding-levelfour-cloudformation-template.json \
  --permission-model SERVICE_MANAGED \
  --auto-deployment Enabled=true,RetainStacksOnAccountRemoval=false \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameters ParameterKey=LevelFourHandshakeID,ParameterValue=<YOUR_HANDSHAKE_ID>

aws cloudformation create-stack-instances \
  --stack-set-name LevelFour-Onboarding \
  --deployment-targets OrganizationalUnitIds=<YOUR_ROOT_OR_OU_ID> \
  --regions us-east-1

aws cloudformation create-stack \
  --stack-name LevelFour-ManagementAccount \
  --template-url https://cf-templates-1bsphth8u70q9-us-east-1.s3.amazonaws.com/onboarding/v2/onboarding-levelfour-cloudformation-template.json \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameters ParameterKey=LevelFourHandshakeID,ParameterValue=<YOUR_HANDSHAKE_ID> \
  --region us-east-1
```

**Terraform**

Deploys the same wrapper template as the **Launch Stack** tab through an `aws_cloudformation_stack` resource, so one apply creates the StackSet and the role in your management account. Run it with credentials for the management account.

```hcl title="levelfour.tf"
provider "aws" {
  region              = "us-east-1"
  allowed_account_ids = ["<management-account-id>"]
}

variable "levelfour_handshake_id" {
  description = "The handshake ID LevelFour gave you"
  type        = string
  sensitive   = true
}

variable "levelfour_target_id" {
  description = "Root ID (r-...) or OU ID (ou-...) from the preflight output"
  type        = string
}

resource "aws_cloudformation_stack" "levelfour" {
  name         = "LevelFour-Onboarding"
  template_url = "https://cf-templates-1bsphth8u70q9-us-east-1.s3.amazonaws.com/onboarding/v2/onboarding-levelfour-stackset-wrapper.template.json"
  capabilities = ["CAPABILITY_NAMED_IAM"]

  parameters = {
    LevelFourHandshakeID = var.levelfour_handshake_id
    TargetOUId           = var.levelfour_target_id
  }

  timeouts {
    create = "2h"
    delete = "2h"
  }
}

output "levelfour_management_account_id" {
  value = aws_cloudformation_stack.levelfour.outputs["ManagementAccountId"]
}
```

* Keep the stack name `LevelFour-Onboarding`. The handoff script in the next step looks for a stack with that name.
* `CAPABILITY_NAMED_IAM` is the IAM acknowledgement the console asks for.
* `allowed_account_ids` stops Terraform before it changes anything outside your management account. If your configuration already has a provider for that account, keep yours and leave this one out.
* The StackSet deploys to member accounts one at a time, so a large organization can outlast Terraform's default 30-minute wait. The `timeouts` block raises it to two hours.

Apply it with the handshake ID and the target ID from the preflight:

```bash
export TF_VAR_levelfour_handshake_id='<your-handshake-id>'
export TF_VAR_levelfour_target_id='<root-or-ou-id>'
terraform init
terraform apply
```

`terraform apply` returns once the wrapper stack reaches `CREATE_COMPLETE`, which happens after every per-account stack succeeds. `terraform output` then prints the management account ID you send LevelFour in the next step.

### Tell LevelFour you are done

Send your LevelFour contact your **management account ID**. LevelFour already has your handshake. It uses that to assume the role in your account, verify the role works in every active account, and populate your organization in LevelFour. You do not need to copy ARNs back to LevelFour.

**Handoff script**

Recommended. In AWS CloudShell signed in to your management account:

```bash
curl -fsSL https://cf-templates-1bsphth8u70q9-us-east-1.s3.amazonaws.com/onboarding/v1/levelfour-handoff.sh | bash
```

It auto-detects your wrapper stack and prints the stack outputs, then one combined table of **every active organization account** with its LevelFour role status. Copy the whole picture into your reply.

```text
Wrapper stack outputs:
-----------------------------------------------------------
| Output                | Value                           |
|-----------------------|---------------------------------|
| ManagementAccountId   | 123456789012                    |
| DeploymentTarget      | r-abcd                          |
| StackSetName          | LevelFour-Onboarding            |
| RoleNameInEachAccount | LevelFourCrossAccountRole       |
-----------------------------------------------------------

Active organization accounts and their LevelFour role status:

  Account ID      Name                              Role Status
  --------------  --------------------------------  ---------------
  123456789012    Org (management)                  CURRENT
  234567890123    Prod                              CURRENT
  345678901234    Staging                           CURRENT
  456789012345    Dev                               CURRENT

================ Send this to LevelFour ================
  ManagementAccountId : 123456789012
  Active accounts     : 4
  Role deployed to    : 4 of 4
========================================================
```

> **Success**
>
> Every row `CURRENT`, and a summary whose two account counts match, means the role is live in every active account in your organization. That is the whole check.

If any account is not `CURRENT`, the script flags it and explains the common causes: the [management account missing on older deploys](#upgrading-an-older-wrapper), or an [SCP block](#troubleshooting).

**CloudFormation console**

The console does not surface the full account list in one place. CloudFormation outputs are stack-level only, and aggregating AWS Organizations data would need a custom Lambda resource, which the template does not include. You will need three short stops.

**Stop 1. Wrapper stack outputs.** Open the wrapper stack (`LevelFour-Onboarding`) > **Outputs** tab:

| Output                  | What it is                                                                         |
| ----------------------- | ---------------------------------------------------------------------------------- |
| `ManagementAccountId`   | Your AWS Organizations management account ID, the value to send LevelFour          |
| `DeploymentTarget`      | The root ID or OU ID you deployed to (root = every account)                        |
| `StackSetName`          | `LevelFour-Onboarding`, useful if you ever need to manage the StackSet later       |
| `RoleNameInEachAccount` | `LevelFourCrossAccountRole`, the deterministic role name in every targeted account |

**Stop 2. Member account rollout status.** CloudFormation > **StackSets** > `LevelFour-Onboarding` > **Stack instances** tab. One row per member account. Every row should show `Status: CURRENT`. The management account is not in this table. It is covered by the inline `LevelFourCrossAccountRole` resource on the wrapper stack itself, which is already in `CREATE_COMPLETE` if you got this far.

**Stop 3. All organization accounts.** AWS Organizations console > **Accounts**. Cross-reference these with the StackSet's Stack instances table. Every active account should be either a row in Stop 2 (member, rolled out via StackSet) or the management account (covered by the wrapper).

The **Handoff script** tab does all three stops in one command, and prints an explicit "Send this to LevelFour" summary.

**AWS CLI**

The same data the handoff script consolidates, raw:

```bash
aws cloudformation describe-stacks \
  --stack-name LevelFour-Onboarding \
  --region us-east-1 \
  --query 'Stacks[0].Outputs[].[OutputKey,OutputValue]' \
  --output table

aws cloudformation list-stack-instances \
  --stack-set-name LevelFour-Onboarding \
  --region us-east-1 \
  --query 'Summaries[].[Account,Region,Status]' \
  --output table

aws organizations list-accounts \
  --query 'Accounts[?Status==`ACTIVE`].[Id,Name]' \
  --output table
```

* The first command prints the wrapper stack outputs (your `ManagementAccountId` lives there).
* The second prints per-member-account rollout status from the StackSet. Every row should show `Status: CURRENT`. Any account in a `FAILED` or `INOPERABLE` state needs a per-account look, usually an SCP block. See [Troubleshooting](#troubleshooting).
* The third prints every active account in your organization, **including the management account**, which is never in the StackSet's stack-instance list. It is covered by the inline `LevelFourCrossAccountRole` resource on the wrapper stack itself, which is already in `CREATE_COMPLETE`.

For the unified view the handoff script prints on its own, cross-reference the second and third tables. Every active account ID from the third should appear in the second with `Status: CURRENT`, except the management account.

## Verifying a specific account

Each member account's CloudFormation console shows its own stack, with the same `Outputs.RoleArn` you would see on the single-account path. To confirm by hand that an account was reached, sign into that account, open CloudFormation > **Stacks**, find the stack named `StackSet-LevelFour-Onboarding-...`, and check its Outputs.

## What happens when new accounts join your organization

Because `AutoDeployment` is enabled, CloudFormation automatically deploys the role to any new account that joins your target. LevelFour re-syncs periodically, usually daily, and adds those new accounts to your organization in LevelFour.

## Upgrading an older wrapper

Wrapper templates published before May 2026 did not create the LevelFour role in your AWS Organizations management account. They only covered member accounts via the StackSet. If your handoff script shows the management account row as `NOT_DEPLOYED` and every other row is `CURRENT`, you are on an older wrapper.

To upgrade in place:

1. Open the CloudFormation console > **Stacks** > click your wrapper stack (default name `LevelFour-Onboarding`)
2. **Stack actions** > **Update stack**
3. **Replace current template** > **Amazon S3 URL**, paste:
   ```text
   https://cf-templates-1bsphth8u70q9-us-east-1.s3.amazonaws.com/onboarding/v2/onboarding-levelfour-stackset-wrapper.template.json
   ```
4. Click through. Your existing parameters carry over, so leave them as is.
5. Tick the IAM acknowledgement > **Update stack**

The update is non-destructive for member accounts, because the StackSet is untouched. It just adds the inline IAM role for the management account. After `UPDATE_COMPLETE`, re-run the handoff script and the management account row should show `CURRENT`.

## Removing access

To revoke LevelFour's access across all accounts, delete the wrapper stack from the management account. CloudFormation will tear down the StackSet, which removes the role from every member account.

```bash
aws cloudformation delete-stack --stack-name LevelFour-Onboarding
```

If you deployed with Terraform, remove the `aws_cloudformation_stack.levelfour` resource and its output from your configuration, then run `terraform apply`. Do not delete the wrapper stack with the AWS CLI instead: the resource is still in your configuration, so the next `terraform apply` deploys it again.

To remove access from a single account, move that account out of the targeted OU. CloudFormation auto-removes the role when the account leaves.

## Troubleshooting

### StackSet OPERATION_FAILED for one account, others succeeded

Open the StackSet > **Operations** > click the failed operation > review the per-instance error. Most common causes:

* An SCP on that account's OU denies `iam:CreateRole`
* The account is suspended (`Status != ACTIVE` in Organizations)
* A role named `LevelFourCrossAccountRole` already exists in that account from a previous single-account deploy. Delete the old role, then retry

### Deploy fails with 'You must enable organizations access to operate a service managed stack set'

You enabled Organizations-side trusted access but not the CloudFormation-side toggle. These are separate per-region settings. Run `aws cloudformation activate-organizations-access --region us-east-1` and retry the StackSet deployment. Re-running the preflight script will confirm both sides are on.

### The management account shows NOT_DEPLOYED

You are on a wrapper published before May 2026. See [Upgrading an older wrapper](#upgrading-an-older-wrapper).

### Trusted access keeps showing as disabled even after I enabled it

Wait 30 seconds for the change to propagate and refresh the page. If it still shows disabled, you may have enabled it in a different organization. Confirm the account selector matches your management account.

### The Launch Stack link opens but the parameters are blank

That is expected on the manual path. The Launch Stack URL leaves `LevelFourHandshakeID` and `TargetOUId` blank for you to fill in. Paste the handshake LevelFour provided and the target ID (root or OU) from the preflight output. The dashboard pre-fills both for you.

### New accounts are not getting the role

Confirm the new account is in the OU you targeted (not the root, unless you targeted the root). It can take a few minutes for AWS to propagate. If still missing after 30 minutes, check the StackSet's **Stack instances** tab for the account ID.

### LevelFour cannot find an account that was onboarded

The account is likely suspended in Organizations, which causes `organizations:ListAccounts` to skip it. Re-activate the account and let LevelFour's re-sync pick it up, typically within 24 hours. Or ask your LevelFour contact to trigger a manual sync.

## Next

* [Detailed cost data](/connectors/aws/detailed-cost-data) turns on the Cost and Usage Report in your management account, which is what gives you resource-level and tag-level breakdowns
* [Automated Savings](/connectors/aws/automated-savings) covers the `LevelFourSavingsExec` role across an organization, including the management account the StackSet does not reach
