Home

Awesome

PRs Welcome GitHub npm (scoped) PyPI Nuget Sonatype Nexus (Releases) GitHub Workflow Status (branch) GitHub release (latest SemVer) Gitpod ready-to-code

CDK Organizations Mentioned in Awesome CDK

Manage AWS organizations, organizational units (OU), accounts and service control policies (SCP).

Features:

View on Construct Hub

Install

TypeScript

npm install @pepperize/cdk-organizations

or

yarn add @pepperize/cdk-organizations

Python

pip install pepperize.cdk-organizations

C# / .Net

dotnet add package Pepperize.CDK.Organizations

Java

<dependency>
  <groupId>com.pepperize</groupId>
  <artifactId>cdk-organizations</artifactId>
  <version>${cdkOrganizations.version}</version>
</dependency>

Contributing

Contributions of all kinds are welcome :rocket: Check out our contributor's guide.

For a quick start, check out a development environment:

git clone git@github.com:pepperize/cdk-organizations
cd cdk-organizations
# install dependencies
yarn
# build with projen
yarn build

Getting Started

  1. Create a new account

    Signup for AWS

  2. Prepare an IAM User with AdministratorAccess

    To deploy your new organization, you have to create an Administrator with an AccessKey

  3. Create a new CDK TypeScript App project with projen

    mkdir my-project
    cd my-project
    git init -b main
    npx projen new awscdk-app-ts
    
  4. Add @pepperize/cdk-organizations to your dependencies in .projenrc.js

    const project = new awscdk.AwsCdkTypeScriptApp({
      //...
      deps: ["@pepperize/cdk-organizations"],
    });
    
  5. Install the dependency

    npx projen
    
  6. Create a stack

    import { Account, Organization, OrganizationalUnit } from "@pepperize/cdk-organizations";
    import { Stack } from "aws-cdk-lib";
    
    export class OrganizationStack extends Stack {
      constructor(scope: Construct, id: string, props: StackProps = {}) {
        super(scope, id, props);
    
        // Create your organization
        const organization = new Organization(stack, "Organization", {});
    
        // Create an organizational unit (OU)
        const organizationUnit = new OrganizationalUnit(stack, "OrganizationalUnit", {
          organizationalUnitName: "MyFirstOU",
          parent: organization.root,
        });
    
        // Create an account
        const account = new Account(stack, "Account", {
          accountName: "MyFirstAccount",
          email: "<your email for the member account>",
          parent: organizationUnit,
        });
      }
    }
    
  7. Configure your AWS CLI to deploy

    The easiest is to export your access key

    export AWS_ACCESS_KEY_ID=<your created access key id>
    export AWS_SECRET_ACCESS_KEY=<your created secret access key>
    
  8. Deploy your first AWS organization

    export CDK_DEFAULT_REGION=<your AWS region>
    export CDK_DEFAULT_ACCOUNT=<your AWS account id>
    
    yarn deploy
    

Usage

Organization

To create a new organization or import an existing organization, add the following construct to your stack:

const organization = new Organization(stack, "Organization", {
  featureSet: FeatureSet.ALL, // (default) required later on to enable SCPs, enable AWS services or delegate an administrator account
});
organization.root; // The organization's root is automatically created

See IOrganization

Organization Principal

To retrieve the AWS IAM organization principal in a member account, add the following to any construct:

const organization = Organization.of(scope, "Organization");
organization.principal; // The AWS IAM organization principal

See AWS Organization API Reference - DescribeOrganization

Organizational Unit (OU)

To create a new organizational unit (OU), add the following construct to your stack:

const organizationUnit = new OrganizationalUnit(stack, "Organization", {
  organizationalUnitName: "Project2",
  parent: organization.root,
});

See IOrganizationalUnit

Organizational Unit (OU) Properties

See OrganizationalUnitProps

Account

To create a new account, add the following construct to your stack:

new Account(stack, "Account", {
  accountName: "MyAccount",
  email: "info@pepperize.com",
  parent: organization.root,
});

See IAccount

Account Properties

See AccountProps

Delegated Administrator

A compatible AWS service (trusted service) can register an AWS member account in the organization as an administrator in the organization on your behalf. To enable an AWS account as administrator of that trusted in your organization call delegateAdministrator on your account:

const account = new Account(stack, "Account", {
  accountName: "StackSetsDelegatedAdministrator",
  email: "info@pepperize.com",
});
account.delegateAdministrator("stacksets.amazonaws.com");

See DelegatedAdministrator

Enable an AWS Service (trusted service)

To enable trusted access for a supported AWS service (trusted service), which performs tasks in your organization and its accounts on your behalf, call enableAwsService on your organization:

const organization = new Organization(stack, "Organization", {
  featureSet: FeatureSet.ALL, // (default) the organization must be created with all features enabled
});
organization.enableAwsServiceAccess("ssm.amazonaws.com");

See EnableAwsServiceAccess

Enable a Policy Type

To enable a policy type call enablePolicyType on your organization.

const organization = new Organization(stack, "Organization", {
  featureSet: FeatureSet.ALL, // (default) the organization must be created with all features enabled
});
organization.enablePolicyType(PolicyType.SERVICE_CONTROL_POLICY);
organization.enablePolicyType(PolicyType.TAG_POLICY);
organization.enablePolicyType(PolicyType.BACKUP_POLICY);
organization.enablePolicyType(PolicyType.AISERVICES_OPT_OUT_POLICY);

See EnablePolicyType, PolicyType.

Policy

To create a new policy add the following construct to your stack:

new Policy(stack, "Policy", {
  content: '{\n"Version":"2012-10-17","Statement":{\n"Effect":"Allow","Action":"s3:*"\n}\n}',
  description: "Enables admins of attached accounts to delegate all S3 permissions",
  policyName: "AllowAllS3Actions",
  policyType: PolicyType.SERVICE_CONTROL_POLICY,
});

See Policy

PolicyAttachment

To attach a policy to a root, an organizational unit (OU), or an individual account call attachPolicy with the policy to attach:

organization.enablePolicyType(PolicyType.TAG_POLICY);

const policy = new Policy(stack, "Policy", {
  content: '{\n"tags":{\n"CostCenter":{\n"tag_key":{\n"@@assign":"CostCenter"\n}\n}\n}\n}',
  description: "Defines the CostCenter tag key",
  policyName: "CostCenterTag",
  policyType: PolicyType.TAG_POLICY,
});

organization.attachPolicy(policy);
organizationalUnit.attachPolicy(policy);
account.attachPolicy(policy);

Tagging resources

To tag a resource you may follow the AWS CDK Developer Guide - Tagging:

You can add one or more tags to the following resources in AWS Organizations.

See Tagging AWS Organizations resources, ITaggableResource

Tagging an organization's root

import { Tags } from "aws-cdk-lib";

const organization = new Organization();
Tags.of(organization.root).add("key", "value");

Tagging an organizational unit (OU)

import { Tags } from "aws-cdk-lib";

const organizationalUnit = new OrganizationalUnit();
Tags.of(organizationalUnit).add("key", "value");

Tagging an account

import { Tags } from "aws-cdk-lib";

const account = new Account();
Tags.of(account).add("key", "value");

Tagging a policy

import { Tags } from "aws-cdk-lib";

const policy = new Policy();
Tags.of(policy).add("key", "value");

Limitations

AWS Organizations has some limitations:

AWS Organizations is a global service with service endpoints in us-east-1, us-gov-west-1 and cn-northwest-1. Read also Endpoint to call When using the AWS CLI or the AWS SDK. Currently all custom resources of this library are hard set to use us-east-1.

Example

See example

import { App, Stack } from "aws-cdk-lib/core";
import {
  Account,
  DelegatedAdministrator,
  EnableAwsServiceAccess,
  EnablePolicyType,
  FeatureSet,
  IamUserAccessToBilling,
  Organization,
  OrganizationalUnit,
  Policy,
  PolicyAttachment,
  PolicyType,
} from "@pepperize/cdk-organizations";

const app = new App();
const stack = new Stack(app);

// Create an organization
const organization = new Organization(stack, "Organization", {
  featureSet: FeatureSet.ALL,
});
// Enable AWS Service Access (requires FeatureSet: ALL)
organization.enableAwsServiceAccess("service-abbreviation.amazonaws.com");

// Create an account
const account1 = new Account(stack, "SharedAccount", {
  accountName: "SharedAccount",
  email: "info+shared-account@pepperize.com",
  roleName: "OrganizationAccountAccessRole",
  iamUserAccessToBilling: IamUserAccessToBilling.ALLOW,
  parent: organization.root,
});
// Enable a delegated admin account
account1.delegateAdministrator("service-abbreviation.amazonaws.com");

// Create an OU in the current organizations root
const projects = new OrganizationalUnit(stack, "ProjectsOU", {
  organizationalUnitName: "Projects",
  parent: organization.root,
});
const account2 = new Account(stack, "Project1Account", {
  accountName: "SharedAccount",
  email: "info+project1@pepperize.com",
  parent: projects,
});
account2.node.addDependency(account1);

// Create a nested OU and attach two accounts
const project2 = new OrganizationalUnit(stack, "Project2OU", {
  organizationalUnitName: "Project2",
  parent: projects,
});
const account3 = new Account(stack, "Project2DevAccount", {
  accountName: "Project 2 Dev",
  email: "info+project2-dev@pepperize.com",
  parent: project2,
});
account3.node.addDependency(account2);
const account4 = new Account(stack, "Project2ProdAccount", {
  accountName: "Project 2 Prod",
  email: "info+project2-prod@pepperize.com",
  parent: project2,
});
account4.node.addDependency(account3);

// Enable the service control policy (SCP) type within the organization
organization.enablePolicyType(PolicyType.SERVICE_CONTROL_POLICY);
// Create and attach and Service Control Policy (SCP)
const policy = new Policy(stack, "Policy", {
  content: '{\n"Version":"2012-10-17","Statement":{\n"Effect":"Allow","Action":"s3:*"\n}\n}',
  description: "Enables admins of attached accounts to delegate all S3 permissions",
  policyName: "AllowAllS3Actions",
  policyType: PolicyType.SERVICE_CONTROL_POLICY,
});
organization.attachPolicy(policy);

// Tagging AWS organization resources of this stack
Tags.of(stack).add("tagKey", "tagValue");

References

Alternatives