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:
- Prerequisities
- Summary
- Variables
- Step 1 - Create Administration Role
- Step 2 - Create Execution Roles
- Step 3 - Create an Arpio Application
- Step 4 - Fetch Access Templates
- Step 5 - Create Primary and Recovery StackSets
- Step 6 - Create Stack Instances
- Automating Template Updates
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
Summary
|
Step |
Frequency |
Where |
|---|---|---|
|
1. Create Administration Role |
Once |
Management account in AWS |
|
2. Create Execution Roles |
Once per target account |
Each primary/recovery account in AWS |
|
3. Create Arpio Application |
Per app |
Arpio API |
|
4. Fetch Access Templates |
Per app |
Arpio API |
|
5. Create StackSets |
Once (skip if exists) |
Management account in AWS |
|
6. Create Stack Instances |
Per app (2 calls) |
Management account in AWS |
Variables
Replace these placeholders throughout the guide:
|
Placeholder |
Description |
|---|---|
|
|
AWS account ID of your management account |
|
|
AWS account ID of your primary (source) account |
|
|
AWS account ID of your recovery account |
|
|
e.g. us-east-1 |
|
|
e.g. us-west-2 |
|
|
Your Arpio account ID |
|
|
Your Arpio API bearer token |
Step 1 — Create Administration Role (once, in 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 target account)
Once the Administration Role can assume roles in the target account, deploy the Execution Role using one of the below methods. Run in each AWS account that participates as primary or recovery.
Option A: Deploy via CloudFormation CLI
Run this command from the target account (or use cross-account role assumption):
aws cloudformation create-stack \
--stack-name ArpioStackSetExecutionRole \
--capabilities CAPABILITY_NAMED_IAM \
--parameters ParameterKey=AdministrationAccountId,ParameterValue=MANAGEMENT_ACCOUNT_ID \
--template-body file://execution-role.yml
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>
Option C: Batch Deployment via Automation
For bulk onboarding of multiple accounts, you can script the deployment using cross-account role assumption:
#!/bin/bash
# deploy_execution_roles.sh
# Deploys Execution Role to multiple target accounts
MGMT_ACCOUNT_ID="123456789012"
TARGET_ACCOUNTS=("<aws_source_account_id>" "<aws_target_account_id>" "333333333333")
CROSS_ACCOUNT_ROLE="OrganizationAccountAccessRole" # or your role name
TEMPLATE_URL="https://arpio-cloudformation-templates.s3.amazonaws.com/\
stacksets/ArpioStackSetExecutionRole.yml"
for ACCOUNT_ID in "${TARGET_ACCOUNTS[@]}"; do
echo "Deploying to account: $ACCOUNT_ID"
# Assume role in target account
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 | cut -d' ' -f1)
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | cut -d' ' -f2)
export AWS_SESSION_TOKEN=$(echo $CREDS | cut -d' ' -f3)
# Deploy the stack
aws cloudformation create-stack \
--stack-name ArpioStackSetExecutionRole \
--template-url "$TEMPLATE_URL" \
--capabilities CAPABILITY_NAMED_IAM \
--parameters ParameterKey=AdministrationAccountId,ParameterValue=$MGMT_ACCOUNT_ID
# Wait for completion
aws cloudformation wait stack-create-complete \
--stack-name ArpioStackSetExecutionRole
echo "Completed: $ACCOUNT_ID"
done
# Clear temporary credentials
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN
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'
Step 3 — Create an Arpio Application (per app)
curl -X POST "https://app.arpio.io/api/accounts/ARPIO_ACCOUNT_ID/applications" \
-H "Authorization: Bearer TOKEN" \
-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 "Authorization: Bearer TOKEN"
From the response, extract these fields:
|
Response field |
Use in |
|---|---|
|
|
Step 5 — |
|
|
Step 5 — |
|
|
Step 6 — |
|
|
Step 6 — |
|
|
Step 6 — |
|
|
Step 6 — |
Step 5 — Create Two StackSets (once, in management account — skip if already created)
This step only needs to run once. If you already have the ArpioPrimaryAccess and ArpioRecoveryAccess StackSets, skip to Step 6.
Create the ArpioPrimaryAccess StackSet:
aws cloudformation create-stack-set \
--stack-set-name ArpioPrimaryAccess \
--template-url SOURCE_STACKSET_TEMPLATE_URL \
--permission-model SELF_MANAGED \
--administration-role-arn arn:aws:iam::MANAGEMENT_ACCOUNT_ID:role/ArpioStackSetAdministrationRole \
--execution-role-name ArpioStackSetExecutionRole \
--capabilities CAPABILITY_NAMED_IAM
Create the ArpioRecoveryAccess StackSet:
aws cloudformation create-stack-set \
--stack-set-name ArpioRecoveryAccess \
--template-url TARGET_STACKSET_TEMPLATE_URL \
--permission-model SELF_MANAGED \
--administration-role-arn arn:aws:iam::MANAGEMENT_ACCOUNT_ID:role/ArpioStackSetAdministrationRole \
--execution-role-name ArpioStackSetExecutionRole \
--capabilities CAPABILITY_NAMED_IAM
Step 6 — Create Stack Instances (per app, in management account)
The SourceAwsAccountId and TargetAwsAccountId parameters in the StackSet template are placeholders with default values set to the first application's account IDs at template generation time. Always override these with parameter overrides when creating new stack instances.
Primary Access — deploys into the primary account/region:
aws cloudformation create-stack-instances \
--stack-set-name ArpioPrimaryAccess \
--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 recovery account/region:
aws cloudformation create-stack-instances \
--stack-set-name ArpioRecoveryAccess \
--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 "Authorization: Bearer {token}"
# 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 "Authorization: Bearer {token}"
# Compare templateVersion with current application version
Apply Updates
If versions differ, run update-stack-set to propagate changes to all instances:
# Update Primary StackSet (propagates to ALL primary stack instances)
aws cloudformation update-stack-set \
--stack-set-name ArpioPrimaryAccess \
--template-url {sourceStackSetTemplateS3Url} \
--administration-role-arn arn:aws:iam::{mgmt_account}:role/ArpioStackSetAdministrationRole \
--capabilities CAPABILITY_NAMED_IAM
# Update Recovery StackSet (propagates to ALL recovery stack instances)
aws cloudformation update-stack-set \
--stack-set-name ArpioRecoveryAccess \
--template-url {targetStackSetTemplateS3Url} \
--administration-role-arn arn:aws:iam::{mgmt_account}:role/ArpioStackSetAdministrationRole \
--capabilities CAPABILITY_NAMED_IAM
Verify Update Success
After running the update, verify success using one of these methods:
- Check templateVersion: Query the application API and verify the templateVersion field matches the expected version.
- 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 "Authorization: Bearer {token}"