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.
Don't have an AWS account? Create one here.
mkdir my-org && cd my-org
npm init -y && npm pkg set type=module
npm install @beesolve/aws-accounts typescript
git init && echo -e "node_modules/\n.remote-state-cache.json" > .gitignore
# Bootstrap handles everything: creates the Organization,
# guides you through enabling Identity Center, deploys infrastructure
npx aws-accounts bootstrap --region us-east-1
# Scan your org and generate the config file
npx aws-accounts init
# Edit aws.config.ts, then sync
npx aws-accounts plan
npx aws-accounts applyThe CLI will:
- Detect no Organization exists and offer to create one (all features enabled)
- Detect Identity Center is not enabled and provide Console instructions
- Deploy the remote infrastructure (S3 bucket, IAM role, Lambda)
Prerequisites:
- AWS Organization with all features enabled
- IAM Identity Center enabled in the management account
- AWS credentials with management account access
mkdir my-org && cd my-org
npm init -y && npm pkg set type=module
npm install @beesolve/aws-accounts typescript
git init && echo -e "node_modules/\n.remote-state-cache.json" > .gitignore
npx aws-accounts bootstrap --region us-east-1
npx aws-accounts init
# aws.config.ts is now your source of truth
npx aws-accounts plan
npx aws-accounts applyDetailed walkthrough: See Getting Started Guide for step-by-step instructions.
Want to remove this tool? See Uninstalling — the tool deploys minimal infrastructure and is easy to clean up.
- Bootstrap (one-time) — deploys S3 bucket, IAM role, and Lambda to your AWS account
- Init (one-time) — scans your org, generates
aws.config.ts(your source of truth) - Edit — modify
aws.config.tsto model your desired org structure - Sync —
planshows what will change;applyexecutes it
Requires Node.js 24+.
| Command | Description |
|---|---|
bootstrap |
One-time setup: creates Organization (if needed), guides Identity Center enablement, deploys infrastructure |
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) |
drift |
Shows what changed in AWS since last scan |
validate |
Validates aws.config.ts locally without hitting AWS |
config reveal |
Copies default CloudFormation templates to your project for customization |
graveyard |
Lists accounts parked in the Graveyard OU |
profile |
Generates an AWS CLI SSO profile block from local state |
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
permissionSets: [
{
name: "AdminAccess",
description: "Full administrator access",
sessionDuration: "PT8H",
awsManagedPolicies: ["arn:aws:iam::aws:policy/AdministratorAccess"],
customerManagedPolicies: [],
},
],aws.config.types.ts exports iam helpers with service-scoped action autocomplete:
import { awsConfigSchema, iam, type AwsConfig } from "./aws.config.types.js";
Action: [iam.s3("GetObject"), iam.identitystore("CreateGroupMembership")];- 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)
- 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
planfetches current remote state before computing the diffapplyrecomputes the plan before executing — no stale operations- Destructive operations require
--allow-destructive - Human-readable previews mark destructive operations explicitly
npx aws-accounts scan # refresh state from live AWS
npx aws-accounts plan # review remaining diff
npx aws-accounts apply # re-applynpx 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)
--redeploy-stacksets Force re-deployment of security baseline StackSets (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 (fallback: AWS_SSO_SESSION; default: sso)
--help Show help
The CLI delegates all AWS operations to a deployed Lambda. Day-to-day usage requires only:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:*:*:function:beesolve-aws-accounts"
}
]
}bootstrap and upgrade require broader permissions (S3, IAM, Lambda, SSO).
Commands needing no AWS permissions: regenerate, validate, graveyard.
The generated aws.config.types.ts exports reusable policy builders:
import { policies } from "./aws.config.types.js";
policies: {
serviceControlPolicies: [
policies.scp.blockExpensiveResources({
allowedEc2InstanceTypes: ["t3.micro", "t3.small", "t4g.medium"],
targets: ["root"],
}),
],
}See Security Baseline for CloudTrail, AWS Config, GuardDuty, and root access management.
Run npx aws-accounts init (delete aws.config.ts first). This rewrites config from live AWS state.
regenerate refreshes only types, not config. Use init to reset config to live state.
The CLI will fail and require --instance-arn.