Skip to content
English
  • There are no suggestions because the search field is empty.

Automating Arpio StackSets Adoption at Scale

This guide describes how to automate StackSets deployment using the Arpio API and AWS CloudFormation CLI.

The docs here illustrate how to Deploy Access with AWS StackSets through the Arpio console.

Jump to:

Prerequisites

  • StackSets capability enabled on your Arpio tenant (contact Arpio support)
    • StackSets is enabled as a capability on your Arpio tenant—there is no per-app flag. The backend detects StackSet management by reading the ArpioStackSet tag from the deployed Stack and exposes this information to the Arpio UI and API.
  • Arpio API credentials with appropriate permissions


Management Account Topology

Before you begin, decide which topology matches your AWS setup:

  • Single management account: one AWS management account owns both the Primary and the RecoveryStackSets. Use this if the same account administers deployments into your primary-region member accounts and your recovery-region member accounts.
  • Separate management accounts (recommended): two AWS management accounts, one owning each StackSet. Use this if your Primary-side member accounts are administered from one account and your Recovery-side member accounts from another (common in larger AWS Organizations).

In the steps below, PRIMARY_MANAGEMENT_ACCOUNT_ID and RECOVERY_MANAGEMENT_ACCOUNT_ID may be the same value (single-management-account topology) or different values (separate management accounts).

"Member account" refers to the AWS account where a StackSet deploys a stack instance: your primary-region or recovery-region AWS account. We use "member" rather than "target" to avoid confusion with Arpio's "target endpoint" terminology, which refers to the recovery side of a sync pair.


Summary

Step

Frequency

Where

1. Create Administration Role

Once per management account

Each management account in AWS

2. Create Execution Roles

Once per member account

Each primary/recovery member account in AWS

3. Create Arpio Application

Per app

Arpio API

4. Fetch Access Templates

Per app

Arpio API

5. Create StackSets

Once per management account (skip per side if exists)

Primary management account (Primary StackSet) in AWS / Recovery management account (Recovery StackSet) in AWS

6. Create Stack Instances

Per app (2 calls)

Primary management account in AWS / Recovery management account in AWS

 

Variables

Replace these placeholders throughout the guide:

Placeholder

Description

PRIMARY_MANAGEMENT_ACCOUNT_ID

AWS account ID of the management account that owns the Primary StackSet

RECOVERY_MANAGEMENT_ACCOUNT_ID

AWS account ID of the management account that owns the Recovery StackSet (same as PRIMARY_MANAGEMENT_ACCOUNT_ID in the single-management-account topology)

PRIMARY_ACCOUNT_ID

AWS account ID of your primary (source) member account

RECOVERY_ACCOUNT_ID

AWS account ID of your recovery member account

PRIMARY_REGION

e.g. us-east-1

RECOVERY_REGION

e.g. us-west-2

PRIMARY_STACKSET_NAME

StackSet name for primary access, e.g. ArpioPrimaryAccess

RECOVERY_STACKSET_NAME

StackSet name for recovery access, e.g. ArpioRecoveryAccess

ARPIO_ACCOUNT_ID

Your Arpio account ID

TOKEN

Your Arpio API bearer token

For ease of running commands, you can also export these variables to your shell and reference them in the commands.

 

 


Step 1 — Create Administration Role (once per management account)

Run the command below in your Primary management account. If you use separate management accounts for Primary and Recovery, run it again in your Recovery management account.

aws cloudformation create-stack \
 --stack-name ArpioStackSetAdministrationRole \
 --capabilities CAPABILITY_NAMED_IAM \
  --template-body file://admin-role.yml

Save the following as admin-role.yml:

AWSTemplateFormatVersion: '2010-09-09'
Description: StackSet Administration Role for Arpio
Parameters:
  ExecutionRoleName:
    Type: String
    Default: ArpioStackSetExecutionRole
Resources:
  AdministrationRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ArpioStackSetAdministrationRole
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: cloudformation.amazonaws.com
            Action: sts:AssumeRole
        Policies:
          - PolicyName: AssumeExecutionRole
            PolicyDocument:
              Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action: sts:AssumeRole
                Resource: !Sub 'arn:aws:iam::*:role/${ExecutionRoleName}'

Wait for completion:

aws cloudformation wait stack-create-complete \
  --stack-name ArpioStackSetAdministrationRole

 



Step 2 — Create Execution Roles (once per member account)

Run in each AWS account that participates as a primary or recovery member.

The Execution Role's trust policy must point at the management account that owns the StackSet for that side:

  • A Primary member account's Execution Role must trust the Primary management account.
  • A Recovery member account's Execution Role must trust the Recovery management account.

In the single-management-account topology, both sides tryst the same account.

Option A: Deploy via CloudFormation CLI

Run this command from the member account (or use cross-account role assumption). Set AdministrationAccountId to the management account ID for the side this member belongs to:

aws cloudformation create-stack \
 --stack-name ArpioStackSetExecutionRole \
 --capabilities CAPABILITY_NAMED_IAM \
 --parameters ParameterKey=AdministrationAccountId,ParameterValue=PRIMARY_MANAGEMENT_ACCOUNT_ID \
  --template-body file://execution-role.yml

# For a Recovery member account, replace PRIMARY_MANAGEMENT_ACCOUNT_ID with RECOVERY_MANAGEMENT_ACCOUNT_ID.

 

Save the following as execution-role.yml:

AWSTemplateFormatVersion: '2010-09-09'
Description: StackSet Execution Role for Arpio
Parameters:
  AdministrationAccountId:
    Type: String
    Description: AWS Account ID of the Administration Account
  AdministrationRoleName:
    Type: String
    Default: ArpioStackSetAdministrationRole
Resources:
  ExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ArpioStackSetExecutionRole
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              AWS: !Sub 'arn:aws:iam::${AdministrationAccountId}:role/${AdministrationRoleName}'
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AdministratorAccess

Wait for completion:

aws cloudformation wait stack-create-complete \
  --stack-name ArpioStackSetExecutionRole


Option B: Deploy via CloudShell in Target Account

The Arpio console provides a ready-to-run command. Copy it from the UI and paste into CloudShell:

# From Arpio Console: App Settings > AWS Access > Step 1b
# Copy the provided command and run in CloudShell

aws cloudformation create-stack \
 --stack-name ArpioStackSetExecutionRole \
 --template-url <url-from-arpio-console> \
 --capabilities CAPABILITY_NAMED_IAM \
 --parameters ParameterKey=AdministrationAccountId,ParameterValue=<mgmt-acct-id>


Option C: Batch Deployment via Automation

For bulk onboarding of multiple accounts, you can script the deployment using cross-account role assumption:

This will require the API key created earlier 

#!/bin/bash
# deploy_execution_roles.sh
# Deploys Execution Role to multiple member accounts.
# Primary members trust the Primary management account.
# Recovery members trust the Recovery management account.

PRIMARY_MGMT_ACCOUNT_ID="123456789012"
RECOVERY_MGMT_ACCOUNT_ID="123456789012"   # same as primary if single-management-account topology

PRIMARY_MEMBER_ACCOUNTS=("111111111111" "222222222222")
RECOVERY_MEMBER_ACCOUNTS=("333333333333" "444444444444")

CROSS_ACCOUNT_ROLE="OrganizationAccountAccessRole"  # or your role name
  TEMPLATE_URL="https://arpio-cloudformation-templates.s3.amazonaws.com/stacksets/ArpioStackSetExecutionRole.yml"

deploy_for_side() {
  local ADMIN_ACCT_ID=$1
  shift
  local ACCOUNTS=("$@")

  for ACCOUNT_ID in "${ACCOUNTS[@]}"; do
    echo "Deploying to member account: $ACCOUNT_ID (trusting $ADMIN_ACCT_ID)"

    CREDS=$(aws sts assume-role \
      --role-arn arn:aws:iam::${ACCOUNT_ID}:role/${CROSS_ACCOUNT_ROLE} \
      --role-session-name ArpioExecRoleDeploy \
      --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
      --output text)
    export AWS_ACCESS_KEY_ID=$(echo "$CREDS" | awk '{print $1}')
    export AWS_SECRET_ACCESS_KEY=$(echo "$CREDS" | awk '{print $2}')
    export AWS_SESSION_TOKEN=$(echo "$CREDS" | awk '{print $3}')

    aws cloudformation create-stack \
      --stack-name ArpioStackSetExecutionRole \
      --template-url "$TEMPLATE_URL" \
      --capabilities CAPABILITY_NAMED_IAM \
      --parameters ParameterKey=AdministrationAccountId,ParameterValue=$ADMIN_ACCT_ID

    aws cloudformation wait stack-create-complete \
      --stack-name ArpioStackSetExecutionRole

    echo "Completed: $ACCOUNT_ID"
  done

  unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
}

deploy_for_side "$PRIMARY_MGMT_ACCOUNT_ID" "${PRIMARY_MEMBER_ACCOUNTS[@]}"
deploy_for_side "$RECOVERY_MGMT_ACCOUNT_ID" "${RECOVERY_MEMBER_ACCOUNTS[@]}"

Verify Execution Role Deployment

Confirm the role exists in the target account:

# Verify the role was created (run in target account)
aws iam get-role --role-name ArpioStackSetExecutionRole


# Check the trust policy allows the Administration Role
aws iam get-role --role-name ArpioStackSetExecutionRole \
  --query 'Role.AssumeRolePolicyDocument'

 

Expected trust:

  • In a Primary member account the Principal.AWS should be arn:aws:iam::PRIMARY_MANAGEMENT_ACCOUNT_ID:role/ArpioStackSetAdministrationRole.

  • In a Recovery member account the Principal.AWS should be arn:aws:iam::RECOVERY_MANAGEMENT_ACCOUNT_ID:role/ArpioStackSetAdministrationRole.


Step 3 — Create an Arpio Application (per app)

curl -X POST "https://app.arpio.io/api/accounts/ARPIO_ACCOUNT_ID/applications" \
 -H "X-Api-Key: <apiKeyID>:<secret>" \
 -H "Content-Type: application/json" \
 -d '{
   "accountId": "ARPIO_ACCOUNT_ID",
   "name": "APP_NAME",
   "type": "aws",
   "rpo": RPO_SECONDS,
   "notificationEmails": ["team@example.com"],
   "sourceEndpointUri": "aws:PRIMARY_ACCOUNT_ID:PRIMARY_REGION",
   "targetEndpointUri": "aws:RECOVERY_ACCOUNT_ID:RECOVERY_REGION",
   "selectionRules": [
     { "type": "tag", "tagKey": "TAG_KEY", "tagValue": "TAG_VALUE" }
   ],
   "syncPhase": "STANDBY"
  }'

Save the appId from the response.

 


Step 4 — Fetch Access Templates (per app)

Template S3 URLs are stable and remain constant even when Arpio releases updates. The template content is refreshed in place at the same URL. This means you can store the URL in your automation scripts and CI/CD pipelines without needing to re-query for each update.

curl -s "https://app.arpio.io/api/accounts/ARPIO_ACCOUNT_ID/syncPairs/aws:PRIMARY_ACCOUNT_ID:PRIMARY_REGION/aws:RECOVERY_ACCOUNT_ID:RECOVERY_REGION/accessTemplates" \
 -H "X-Api-Key: <apiKeyID>:<secret>"

From the response, extract these fields:

Response field

Use in

stackSetsTemplate.sourceStackSetTemplateS3Url

Step 5 — SOURCE_STACKSET_TEMPLATE_URL (first app only)

stackSetsTemplate.targetStackSetTemplateS3Url

Step 5 — TARGET_STACKSET_TEMPLATE_URL (first app only)

stackSetsTemplate.sourceTemplate.bucket

Step 6 — SOURCE_TEMPLATE_BUCKET

stackSetsTemplate.sourceTemplate.key

Step 6 — SOURCE_TEMPLATE_KEY

stackSetsTemplate.targetTemplate.bucket

Step 6 — TARGET_TEMPLATE_BUCKET

stackSetsTemplate.targetTemplate.key

Step 6 — TARGET_TEMPLATE_KEY

 


Step 5 — Create Two StackSets (once per management account — skip per side if exists)

This step only needs to run once per management account. If you already have the StackSet that owns access for a given side, skip that side and go to Step 6.

PRIMARY_STACKSET_NAME and RECOVERY_STACKSET_NAME default to ArpioPrimaryAccess and ArpioRecoveryAccess. Choose your own names if you prefer, just be consistent across steps.

Create Primary Access StackSet:

# Location: Primary management account in AWS.

aws cloudformation create-stack-set \
  --stack-set-name PRIMARY_STACKSET_NAME \
  --template-url SOURCE_STACKSET_TEMPLATE_URL \
  --permission-model SELF_MANAGED \
  --administration-role-arn arn:aws:iam::PRIMARY_MANAGEMENT_ACCOUNT_ID:role/ArpioStackSetAdministrationRole \
  --execution-role-name ArpioStackSetExecutionRole \
--capabilities CAPABILITY_NAMED_IAM

Create Recovery Access StackSet:

# Location: Recovery management account in AWS.

aws cloudformation create-stack-set \
  --stack-set-name RECOVERY_STACKSET_NAME \
  --template-url TARGET_STACKSET_TEMPLATE_URL \
  --permission-model SELF_MANAGED \
  --administration-role-arn arn:aws:iam::RECOVERY_MANAGEMENT_ACCOUNT_ID:role/ArpioStackSetAdministrationRole \
  --execution-role-name ArpioStackSetExecutionRole \
  --capabilities CAPABILITY_NAMED_IAM

If you use a single management account, PRIMARY_MANAGEMENT_ACCOUNT_ID and RECOVERY_MANAGEMENT_ACCOUNT_ID are the same value, and both commands run from that same account.


Step 6 — Create Stack Instances (per app)

Run each command from its matching management account:

Primary Access — deploys into the primary member account/region:

aws cloudformation create-stack-instances \
 --stack-set-name PRIMARY_STACKSET_NAME \
 --accounts PRIMARY_ACCOUNT_ID \
 --regions PRIMARY_REGION \
 --parameter-overrides \
   ParameterKey=SourceAwsAccountId,ParameterValue=PRIMARY_ACCOUNT_ID \
   ParameterKey=SourceRegion,ParameterValue=PRIMARY_REGION \
   ParameterKey=TargetAwsAccountId,ParameterValue=RECOVERY_ACCOUNT_ID \
   ParameterKey=TargetRegion,ParameterValue=RECOVERY_REGION \
   ParameterKey=TemplateS3Bucket,ParameterValue=SOURCE_TEMPLATE_BUCKET \
    ParameterKey=TemplateS3Key,ParameterValue=SOURCE_TEMPLATE_KEY

Recovery Access — deploys into the member recovery account/region:

Location: Recovery management account in AWS.

aws cloudformation create-stack-instances \
 --stack-set-name RECOVERY_STACKSET_NAME \
 --accounts RECOVERY_ACCOUNT_ID \
 --regions RECOVERY_REGION \
 --parameter-overrides \
   ParameterKey=SourceAwsAccountId,ParameterValue=PRIMARY_ACCOUNT_ID \
   ParameterKey=SourceRegion,ParameterValue=PRIMARY_REGION \
   ParameterKey=TargetAwsAccountId,ParameterValue=RECOVERY_ACCOUNT_ID \
   ParameterKey=TargetRegion,ParameterValue=RECOVERY_REGION \
   ParameterKey=TemplateS3Bucket,ParameterValue=TARGET_TEMPLATE_BUCKET \
    ParameterKey=TemplateS3Key,ParameterValue=TARGET_TEMPLATE_KEY

 


Automating Template Updates

Key Benefit: Single Command Updates

When Arpio releases new template versions, you can automate the update process by comparing template versions and running update-stack-set.

Running update-stack-set once per StackSet automatically propagates the update to ALL stack instances. For 50 applications, you run 2 commands instead of 100.


Compare Current vs. Latest Template Version

Query the application to get the current templateVersion:

# Get current template version

curl -X GET "https://api.arpio.io/api/accounts/{account_id}/applications/{app_id}" \
 -H "X-Api-Key: <apiKeyID>:<secret>"

# Parse the templateVersion field from the response

Query the access templates endpoint to get the latest template version:

# Get latest template version from accessTemplates endpoint

curl -X GET "https://api.arpio.io/api/accounts/{account_id}/syncPairs/\
 {src_account}/{src_region}/{tgt_account}/{tgt_region}/accessTemplates" \
 -H "X-Api-Key: <apiKeyID>:<secret>"

# Compare templateVersion with current application version


Apply Updates

If versions differ, run update-stack-set on each StackSet from its matching management account:

# Update Primary StackSet (run from Primary management account; propagates to ALL primary stack instances)

aws cloudformation update-stack-set \
 --stack-set-name PRIMARY_STACKSET_NAME \
 --template-url {sourceStackSetTemplateS3Url} \
--administration-role-arn arn:aws:iam::PRIMARY_MANAGEMENT_ACCOUNT_ID:role/ArpioStackSetAdministrationRole \
 --capabilities CAPABILITY_NAMED_IAM


# Update Recovery StackSet (run from Recovery management account; propagates to ALL recovery stack instances)

aws cloudformation update-stack-set \
 --stack-set-name RECOVERY_STACKSET_NAME \
 --template-url {targetStackSetTemplateS3Url} \
--administration-role-arn arn:aws:iam::RECOVERY_MANAGEMENT_ACCOUNT_ID:role/ArpioStackSetAdministrationRole \
 --capabilities CAPABILITY_NAMED_IAM

 

Verify Update Success

After running the update, verify success using one of these methods:

  1. Check templateVersion: Query the application API and verify the templateVersion field matches the expected version.
  2. Check Sync Access: Call the access endpoint to confirm Arpio can reach the sync endpoint.
# Verify access after update

curl -X GET "https://api.arpio.io/api/accounts/{account_id}/syncPairs/\
 {src_account}/{src_region}/{tgt_account}/{tgt_region}/access" \
-H "X-Api-Key: <apiKeyID>:<secret>"