@beesolve/aws-accounts
v1.4.0
Published
AWS Organizations and IAM Identity Center management CLI
Downloads
2,005
Readme
@beesolve/aws-accounts
Config-driven management for AWS Organizations and IAM Identity Center. Define your org structure, accounts, permission sets, and access assignments in a single TypeScript file — then plan and apply changes like Terraform.
Installation
npm install @beesolve/aws-accountsPrerequisites
- Node.js 24+
- AWS Organization with all features enabled
- IAM Identity Center enabled in the organization's management account (or delegated admin account)
- AWS credentials with access to the management account (via environment, profile, or SSO)
Quick Start
# 1. Create a project directory
mkdir my-org && cd my-org
npm init -y
npm pkg set type=module
npm install @beesolve/aws-accounts typescript
# 2. Initialize git and add a .gitignore
git init
echo -e "node_modules/\n.remote-state-cache.json" > .gitignore
# 3. Deploy remote infrastructure (S3 bucket, IAM role, Lambda)
npx aws-accounts bootstrap --region us-east-1
# 4. Scan your AWS org and generate aws.config.ts
npx aws-accounts init
# 5. Edit aws.config.ts to model your desired state
# 6. Preview and apply changes
npx aws-accounts plan
npx aws-accounts applyAfter init, aws.config.ts is your source of truth. Edit it to add accounts, move OUs, manage permission sets, and control access — then sync with plan / apply.
.gitignorerecommendation: Addnode_modules/and.remote-state-cache.jsonto your.gitignore. The cache file is a local copy of remote state that varies per environment and should not be committed.
Commands
| Command | Description |
|---------|-------------|
| bootstrap | One-time setup: deploys S3 bucket, IAM role, and Lambda to your AWS account |
| init | Scans live AWS state and generates aws.config.ts + aws.config.types.ts |
| regenerate | Refreshes aws.config.types.ts (picklists, autocomplete) from current config |
| plan | Computes diff between desired config and actual AWS state |
| apply | Executes planned operations via Lambda |
| upgrade | Updates the deployed Lambda function code |
| scan | Refreshes remote state in S3 (advanced/recovery use) |
| validate | Validates aws.config.ts locally without hitting AWS |
| graveyard | Lists accounts parked in the Graveyard OU |
| profile | Generates an AWS CLI SSO profile block from local state |
Workflow
The tool has four phases:
- Bootstrap (one-time) —
bootstrapdeploys the remote infrastructure. Run once per AWS organization. - Init (one-time) —
initscans your org and generates the config files. After this,aws.config.tsis your editable source of truth. - Edit (steady state) — modify
aws.config.tsto model your desired org structure. Runregenerateto refresh IDE autocomplete after edits. - Sync —
planshows what will change;applyexecutes it.
Configuration
After init, your project contains:
aws.config.ts— your desired state: OUs, accounts, users, groups, permission sets, assignmentsaws.config.types.ts— generated types and helpers for IDE autocomplete
Permission Sets
permissionSets: [
{
name: "AdminAccess",
description: "Full administrator access",
sessionDuration: "PT8H", // ISO-8601 duration; omit to use the AWS default of 1h (max 12h)
awsManagedPolicies: ["arn:aws:iam::aws:policy/AdministratorAccess"],
customerManagedPolicies: [],
},
],IAM Policy Helpers
aws.config.types.ts exports iam helpers with service-scoped action autocomplete:
import { awsConfigSchema, iam, type AwsConfig } from "./aws.config.types.js";
// Full autocomplete for IAM actions
Action: [iam.s3("GetObject"), iam.identitystore("CreateGroupMembership")]When init generates your config, recognized IAM actions in inline policies are emitted as helper calls rather than raw strings.
Supported Mutations
AWS Organizations
- Create, rename, and delete OUs (delete requires
--allow-destructive) - Move accounts between OUs
- Create and rename member accounts
- Reconcile account resource tags
- Park removed accounts in a
GraveyardOU (--allow-destructive)
IAM Identity Center
- Create and delete users and groups
- Update user display name and email
- Update group descriptions
- Manage group memberships
- Create, update, and delete permission sets
- Set permission set session duration (ISO-8601, e.g.
"PT8H"— default 1h, max 12h) - Manage inline policies, AWS managed policies, and customer-managed policy references
- Grant and revoke account assignments
- Reprovision changed permission sets
Validating your config
Run validate before plan to catch mistakes locally without making any AWS API calls:
npx aws-accounts validateIt checks two layers:
Schema and reference errors — caught by compiling aws.config.ts against the generated types in aws.config.types.ts:
- Type mismatches and missing required fields
- References to unknown OUs, accounts, groups, users, or permission sets (enforced by the generated picklist types)
Semantic errors — additional checks run after the schema passes:
- Circular OU parent references (e.g. OU A has
parentName: "B"and B hasparentName: "A") - Assignments with no principal or with both
groupanduserset - Permission set inline policies exceeding the 10,240 character limit
Exits with code 1 if any errors are found, making it safe to use in CI before running plan.
Plan/Apply Safety
planfetches current remote state from S3 before computing the diff.applyrecomputes the plan before executing — no stale operations.- Destructive operations (OU deletion, entity removal) require
--allow-destructive. --ignore-unsupportedproceeds only for non-destructive unsupported diffs.- Destructive unsupported diffs always block
apply(no override). - Human-readable previews mark destructive operations explicitly.
Example: destructive apply
npx aws-accounts plan
npx aws-accounts apply --allow-destructivePlan: 3 operation(s), 0 unsupported diff(s)
Destructive operations detected: 1. Apply requires --allow-destructive.
remove user "alice" from IdC group "Admins"
revoke IdC assignment "AdminAccess" from group "Admins" on "AppAccount"
[destructive] delete IdC group "Admins"Recovery after failed apply
If apply fails mid-run, the Lambda persists partial state to S3. Recovery:
npx aws-accounts scan # refresh state from live AWS
npx aws-accounts plan # review remaining diff
npx aws-accounts apply # re-apply (add --allow-destructive if needed)Generating AWS CLI profiles
The profile command reads your local state cache and presents an interactive picker of every account/permission-set combination you have access to, then prints a ready-to-paste ~/.aws/config block:
npx aws-accounts profile --sso-start-url https://d-xxxxxxxxxx.awsapps.com/start[profile my-account-admin-access]
sso_session = sso
sso_account_id = 123456789012
sso_role_name = AdminAccess
[sso-session sso]
sso_start_url = https://d-xxxxxxxxxx.awsapps.com/start
sso_region = eu-central-1
sso_registration_scopes = sso:account:accessThe SSO start URL is not returned by the AWS API — set it via the flag or the AWS_SSO_START_URL environment variable to avoid typing it every time. Use --sso-session <name> to customise the session name (default: sso).
Requires a populated local state cache — run plan or scan first if the cache is empty.
CLI Options
npx aws-accounts <command> [options]
Options:
--profile <name> AWS profile (fallback: AWS_PROFILE)
--region <region> AWS region (fallback: AWS_REGION, AWS_DEFAULT_REGION)
--yes Skip interactive confirmations
--json Output plan as JSON (plan command)
--allow-destructive Allow destructive operations (apply command)
--ignore-unsupported Proceed with non-destructive unsupported diffs (apply command)
--refresh Force state refresh before planning (plan command)
--sso-start-url <url> IAM Identity Center access portal URL (fallback: AWS_SSO_START_URL)
--sso-session <name> SSO session name for profile output (default: sso)
--help Show helpIAM Permissions
The CLI delegates all AWS operations to a deployed Lambda. Day-to-day usage requires only Lambda invoke permission:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:*:*:function:beesolve-aws-accounts"
}]
}bootstrap and upgrade require broader permissions for deploying infrastructure (S3, IAM, Lambda, SSO). See the full policy in the docs.
Commands that need no AWS permissions: regenerate (local codegen only), validate (local config checks only), graveyard (reads local cache only).
FAQ
I moved an account manually in the AWS Console. How do I fix my config?
Run npx aws-accounts init (or npx aws-accounts init --yes for non-interactive). This rewrites aws.config.ts from live AWS state.
scan alone won't help — it refreshes remote state in S3 but doesn't touch your config file.
What happens if I run scan + regenerate?
regenerate refreshes only aws.config.types.ts from the current aws.config.ts. It doesn't rewrite config, so stale config stays stale. Use init to reset config to live state.
Multiple Identity Center instances?
If multiple instances exist, the CLI will fail and require --instance-arn.
