{"id":14155684,"url":"https://github.com/cdklabs/cdk-stacksets","last_synced_at":"2025-12-29T23:48:12.048Z","repository":{"id":65335807,"uuid":"585308402","full_name":"cdklabs/cdk-stacksets","owner":"cdklabs","description":null,"archived":false,"fork":false,"pushed_at":"2024-08-23T00:18:43.000Z","size":17376,"stargazers_count":81,"open_issues_count":19,"forks_count":13,"subscribers_count":13,"default_branch":"main","last_synced_at":"2024-08-23T11:00:32.374Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cdklabs.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-04T21:00:43.000Z","updated_at":"2024-08-25T01:29:34.682Z","dependencies_parsed_at":"2023-11-20T23:32:45.040Z","dependency_job_id":"da5e03aa-8238-407c-8970-52127ab1fcd4","html_url":"https://github.com/cdklabs/cdk-stacksets","commit_stats":null,"previous_names":[],"tags_count":151,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdklabs%2Fcdk-stacksets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdklabs%2Fcdk-stacksets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdklabs%2Fcdk-stacksets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdklabs%2Fcdk-stacksets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cdklabs","download_url":"https://codeload.github.com/cdklabs/cdk-stacksets/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228821409,"owners_count":17977168,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-17T08:04:57.189Z","updated_at":"2025-12-29T23:48:12.007Z","avatar_url":"https://github.com/cdklabs.png","language":"TypeScript","funding_links":[],"categories":["others"],"sub_categories":[],"readme":"# CDK StackSets Construct Library\n\u003c!--BEGIN STABILITY BANNER--\u003e\n\n---\n\n![cdk-constructs: Experimental](https://img.shields.io/badge/cdk--constructs-experimental-important.svg?style=for-the-badge)\n\n\u003e The APIs of higher level constructs in this module are experimental and under active development.\n\u003e They are subject to non-backward compatible changes or removal in any future version. These are\n\u003e not subject to the [Semantic Versioning](https://semver.org/) model and breaking changes will be\n\u003e announced in the release notes. This means that while you may use them, you may need to update\n\u003e your source code when upgrading to a newer version of this package.\n\n---\n\n\u003c!--END STABILITY BANNER--\u003e\n\nThis construct library allows you to define AWS CloudFormation StackSets.\n\n```ts\nconst stack = new Stack();\nconst stackSetStack = new StackSetStack(stack, 'MyStackSet');\n\nnew StackSet(stack, 'StackSet', {\n  target: StackSetTarget.fromAccounts({\n    regions: ['us-east-1'],\n    accounts: ['11111111111'],\n    parameterOverrides: {\n      SomeParam: 'overrideValue',\n    },\n  }),\n  template: StackSetTemplate.fromStackSetStack(stackSetStack),\n});\n```\n\n## Installing\n\n### TypeScript/JavaScript\n\n```bash\nnpm install cdk-stacksets\n```\n\n### Python\n\n```bash\npip install cdk-stacksets\n```\n\n### Java\n\n```xml\n// add this to your pom.xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.cdklabs\u003c/groupId\u003e\n    \u003cartifactId\u003ecdk-stacksets\u003c/artifactId\u003e\n    \u003cversion\u003e0.0.0\u003c/version\u003e // replace with version\n\u003c/dependency\u003e\n```\n\n### .NET\n\n```bash\ndotnet add package CdklabsCdkStacksets --version X.X.X\n```\n\n### Go\n\n```bash\ngo get cdk-stacksets-go\n```\n\n## Creating a StackSet Stack\n\nStackSets allow you to deploy a single CloudFormation template across multiple AWS accounts and regions.\nTypically when creating a CDK Stack that will be deployed across multiple environments, the CDK will\nsynthesize separate Stack templates for each environment (account/region combination). Because of the\nway that StackSets work, StackSet Stacks behave differently. For Stacks that will be deployed via StackSets\na single Stack is defined and synthesized. Any environmental differences must be encoded using Parameters.\n\nA special class was created to handle the uniqueness of the StackSet Stack.\nYou declare a `StackSetStack` the same way that you declare a normal `Stack`, but there\nare a couple of differences. `StackSetStack`s have a couple of special requirements/limitations when\ncompared to Stacks.\n\n*Requirements*\n- Must be created in the scope of a `Stack`\n- Must be environment agnostic\n\n*Limitations*\n- Does not support Docker container assets\n\nOnce you create a `StackSetStack` you can create resources within the stack.\n```ts\nconst stack = new Stack();\nconst stackSetStack = new StackSetStack(stack, 'StackSet');\n\nnew iam.Role(stackSetStack, 'MyRole', {\n  assumedBy: new iam.ServicePrincipal('myservice.amazonaws.com'),\n});\n```\n\nOr\n```ts\nclass MyStackSet extends StackSetStack {\n  constructor(scope: Construct, id: string) {\n    super(scope, id);\n\n    new iam.Role(this, 'MyRole', {\n      assumedBy: new iam.ServicePrincipal('myservice.amazonaws.com'),\n    });\n  }\n}\n```\n\n## Creating a StackSet\n\nAWS CloudFormation StackSets enable you to create, update, or delete stacks across multiple accounts and AWS Regions\nwith a single operation. Using an administrator account, you define and manage an AWS CloudFormation template, and use\nthe template as the basis for provisioning stacks into selected target accounts across specific AWS Regions.\n\nThere are two methods for defining _where_ the StackSet should be deployed. You can either define individual accounts, or\nyou can define AWS Organizations organizational units.\n\n### Deploying to individual accounts\n\nDeploying to individual accounts requires you to specify the account ids. If you want to later deploy to additional accounts,\nor remove the stackset from accounts, this has to be done by adding/removing the account id from the list.\n\n```ts\nconst stack = new Stack();\nconst stackSetStack = new StackSetStack(stack, 'MyStackSet');\n\nnew StackSet(stack, 'StackSet', {\n  target: StackSetTarget.fromAccounts({\n    regions: ['us-east-1'],\n    accounts: ['11111111111'],\n  }),\n  template: StackSetTemplate.fromStackSetStack(stackSetStack),\n});\n```\n\n### Deploying to organizational units\n\nAWS Organizations is an AWS service that enables you to centrally manage and govern multiple accounts.\nAWS Organizations allows you to define organizational units (OUs) which are logical groupings of AWS accounts.\nOUs enable you to organize your accounts into a hierarchy and make it easier for you to apply management controls.\nFor a deep dive on OU best practices you can read the [Best Practices for Organizational Units with AWS Organizations](https://aws.amazon.com/blogs/mt/best-practices-for-organizational-units-with-aws-organizations/) blog post.\n\nYou can either specify the organization itself, or individual OUs. By default the StackSet will be deployed\nto all AWS accounts that are part of the OU. If the OU is nested it will also deploy to all accounts\nthat are part of any nested OUs.\n\nFor example, given the following org hierarchy\n\n```mermaid\ngraph TD\n  root--\u003eou-1;\n  root--\u003eou-2;\n  ou-1--\u003eou-3;\n  ou-1--\u003eou-4;\n  ou-3--\u003eaccount-1;\n  ou-3--\u003eaccount-2;\n  ou-4--\u003eaccount-4;\n  ou-2--\u003eaccount-3;\n  ou-2--\u003eaccount-5;\n```\n\nYou could deploy to all AWS accounts under OUs `ou-1`, `ou-3`, `ou-4` by specifying the following:\n\n```ts\nconst stack = new Stack();\nconst stackSetStack = new StackSetStack(stack, 'MyStackSet');\n\nnew StackSet(stack, 'StackSet', {\n  target: StackSetTarget.fromOrganizationalUnits({\n    regions: ['us-east-1'],\n    organizationalUnits: ['ou-1'],\n  }),\n  template: StackSetTemplate.fromStackSetStack(stackSetStack),\n});\n```\n\nThis would deploy the StackSet to `account-1`, `account-2`, `account-4`.\n\nIf there are specific AWS accounts that are part of the specified OU hierarchy that you would like\nto exclude, this can be done by specifying `excludeAccounts`.\n\n```ts\nconst stack = new Stack();\nconst stackSetStack = new StackSetStack(stack, 'MyStackSet');\n\nnew StackSet(stack, 'StackSet', {\n  target: StackSetTarget.fromOrganizationalUnits({\n    regions: ['us-east-1'],\n    organizationalUnits: ['ou-1'],\n\texcludeAccounts: ['account-2'],\n  }),\n  template: StackSetTemplate.fromStackSetStack(stackSetStack),\n});\n```\n\nThis would deploy only to `account-1` \u0026 `account-4`, and would exclude `account-2`.\n\nSometimes you might have individual accounts that you would like to deploy the StackSet to, but\nyou do not want to include the entire OU. To do that you can specify `additionalAccounts`.\n\n```ts\nconst stack = new Stack();\nconst stackSetStack = new StackSetStack(stack, 'MyStackSet');\n\nnew StackSet(stack, 'StackSet', {\n  target: StackSetTarget.fromOrganizationalUnits({\n    regions: ['us-east-1'],\n    organizationalUnits: ['ou-1'],\n\tadditionalAccounts: ['account-5'],\n  }),\n  template: StackSetTemplate.fromStackSetStack(stackSetStack),\n});\n```\n\nThis would deploy the StackSet to `account-1`, `account-2`, `account-4` \u0026 `account-5`.\n\n### StackSet permissions\n\nThere are two modes for managing StackSet permissions (i.e. _where_ StackSets can deploy \u0026 _what_ resources they can create).\nA StackSet can either be `Service Managed` or `Self Managed`.\n\nYou can control this through the `deploymentType` parameter.\n\n#### Service Managed\n\nWhen a StackSet is service managed, the permissions are managed by AWS Organizations. This allows the StackSet to deploy the Stack to _any_\naccount within the organization. In addition, the StackSet will be able to create _any_ type of resource.\n\n```ts\nconst stack = new Stack();\nconst stackSetStack = new StackSetStack(stack, 'MyStackSet');\n\nnew StackSet(stack, 'StackSet', {\n  target: StackSetTarget.fromOrganizationalUnits({\n    regions: ['us-east-1'],\n    organizationalUnits: ['ou-1'],\n  }),\n  deploymentType: DeploymentType.serviceManaged(),\n  template: StackSetTemplate.fromStackSetStack(stackSetStack),\n});\n```\n\nWhen you specify `serviceManaged` deployment type, automatic deployments are enabled by default.\nAutomatic deployments allow the StackSet to be automatically deployed to or deleted from\nAWS accounts when they are added or removed from the specified organizational units.\n\n### Using File Assets\n\nYou can use the StackSet's parent stack to facilitate file assets. Behind the scenes,\nthis is accomplished using the `BucketDeployment` construct from the\n`aws_s3_deployment` module. You need to provide a list of buckets outside the scope of the CDK\nmanaged asset buckets and ensure you have permissions for the target accounts to pull\nthe artifacts from the supplied bucket(s).\n\nAs a basic example, if using a `serviceManaged` deployment, you just need to give read\naccess to the Organization. You can create the asset bucket in the parent stack, or another\nstack in the same app and pass the object as a prop. Or, import an existing bucket as needed.\n\nIf creating in the parent or sibling stack you could create and export similar to this:\n\n```ts\nconst bucket = new s3.Bucket(this, \"Assets\", {\n  bucketName: \"prefix-us-east-1\",\n});\n\nbucket.addToResourcePolicy(\n  new iam.PolicyStatement({\n    actions: [\"s3:Get*\", \"s3:List*\"],\n    resources: [bucket.arnForObjects(\"*\"), bucket.bucketArn],\n    principals: [new iam.OrganizationPrincipal(\"o-xyz\")],\n  })\n);\n```\n\nThen pass as a prop to the StackSet stack:\n\n```ts\ndeclare const bucket: s3.Bucket;\nconst stack = new Stack();\nconst stackSetStack = new StackSetStack(stack, 'MyStackSet', {\n  assetBuckets: [bucket],\n  assetBucketPrefix: \"prefix\",\n});\n```\n\nTo faciliate multi region deployments, there is an assetBucketPrefix property. This \ngets added to the region the Stack Set is deployed to. The stack synthesis for \nthe Stack Set would look for a bucket named `prefix-{Region}` in the example \nabove. `{Region}` is whatever region you are deploying the Stack Set to as \ndefined in your target property of the StackSet. You will need to ensure the \nbucket name is correct based on what was previously created and then passed in.\n\nYou can use self-managed StackSet deployments with file assets too but will\nneed to ensure all target accounts roles will have access to the central asset\nbucket you pass as the property.\n\n## Deploying StackSets using CDK Pipelines\n\nYou can also deploy StackSets using [CDK Pipelines](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html)\n\nBelow is an example of a Pipeline that deploys from a central account. It also\ndefines separate stages for each \"environment\" so that you can first test out\nthe stackset in pre-prod environments.\n\nThis would be an automated way of deploying the bootstrap stack described in\n[this blog\npost](https://aws.amazon.com/blogs/mt/bootstrapping-multiple-aws-accounts-for-aws-cdk-using-cloudformation-stacksets/).\n\n```ts\ndeclare const app: App;\ninterface BootstrapStageProps extends StageProps {\n  readonly initialBootstrapTarget: StackSetTarget;\n  readonly stacksetName?: string;\n}\n\nclass BootstrapStage extends Stage {\n  constructor(scope: Construct, id: string, props: BootstrapStageProps) {\n    super(scope, id, props);\n\n    const stack = new Stack(this, 'BootstrapStackSet');\n\n    const bootstrap = new Bootstrap(stack, 'CDKToolkit');\n\n    const stackSet = new StackSet(stack, 'StackSet', {\n      template: StackSetTemplate.fromStackSetStack(bootstrap),\n      target: props.initialBootstrapTarget,\n      capabilities: [Capability.NAMED_IAM],\n      managedExecution: true,\n      stackSetName: props.stacksetName,\n      deploymentType: DeploymentType.serviceManaged({\n        delegatedAdmin: true,\n        autoDeployEnabled: true,\n        autoDeployRetainStacks: false,\n      }),\n      operationPreferences: {\n        regionConcurrencyType: RegionConcurrencyType.PARALLEL,\n        maxConcurrentPercentage: 100,\n        failureTolerancePercentage: 99,\n      },\n    });\n  }\n}\n\n\nconst pipeline = new pipelines.CodePipeline(this, 'BootstrapPipeline', {\n  synth: new pipelines.ShellStep('Synth', {\n    commands: [\n      'yarn install --frozen-lockfile',\n      'npx cdk synth',\n    ],\n    input: pipelines.CodePipelineSource.connection('myorg/myrepo', 'main', {\n      connectionArn: 'arn:aws:codestar-connections:us-east-2:111111111111:connection/ca65d487-ca6e-41cc-aab2-645db37fdb2b',\n    }),\n  }),\n  selfMutation: true,\n});\n\nconst regions = [\n  'us-east-1',\n  'us-east-2',\n  'us-west-2',\n  'eu-west-2',\n  'eu-west-1',\n  'ap-south-1',\n  'ap-southeast-1',\n];\n\npipeline.addStage(\n  new BootstrapStage(app, 'DevBootstrap', {\n    env: {\n      region: 'us-east-1',\n      account: '111111111111',\n    },\n    stacksetName: 'CDKToolkit-dev',\n    initialBootstrapTarget: StackSetTarget.fromOrganizationalUnits({\n      regions,\n      organizationalUnits: ['ou-hrza-ar333427'],\n    }),\n  }),\n);\n\npipeline.addStage(\n  new BootstrapStage(app, 'ProdBootstrap', {\n    env: {\n      region: 'us-east-1',\n      account: '111111111111',\n    },\n    stacksetName: 'CDKToolkit-prd',\n    initialBootstrapTarget: StackSetTarget.fromOrganizationalUnits({\n      regions,\n      organizationalUnits: ['ou-hrza-bb999427', 'ou-hraa-ar111127'],\n    }),\n  }),\n);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdklabs%2Fcdk-stacksets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcdklabs%2Fcdk-stacksets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdklabs%2Fcdk-stacksets/lists"}