AWS Organization Formation (org-formation)

repository·master·Indexed 23 days ago

https://github.com/org-formation/org-formation-cli

An Infrastructure as Code (IaC) tool for managing AWS Organizations. It allows developers to define accounts, Organizational Units (OUs), and Service Control Policies (SCPs) using YAML. The tool provides a CLI (available via npm as aws-organization-formation or via Docker) to automate provisioning, updates, and the creation of cross-account resources such as IAM roles, S3 buckets, and Secrets Manager secrets.

Tokens
40.4K
Snippets
80
Records
178
Agent score
78%

What's inside org-formation-cli

  1. Iterate over accounts using Foreach

    master

    The Foreach attribute allows you to create a resource for every account in a specific selection. The account being iterated over is accessible via the CurrentAccount pseudo-resource.

    Note: Foreach supports the same expressiveness as OrganizationBinding but does not support the Region attribute.

    Example: Creating a GuardDuty Member in the Master account for every account in the organization:

    Resources:
      Member:
        Type: AWS::GuardDuty::Member
        OrganizationBinding:
          IncludeMasterAccount: true
        Foreach:
          Account: '*'
        Properties:
          DetectorId: !Ref Detector
          Email: !GetAtt CurrentAccount.RootEmail
          MemberId: !Ref CurrentAccount
          Status: Invited
          DisableEmailNotification: true
  2. Use Nunjucks templating for CloudFormation generation

    master

    Org-formation uses the nunjucks template engine to generate CloudFormation templates from .njk files. This allows you to use loops, conditionals, and variables within your templates.

    To enable templating in a task, you must provide a TemplatingContext. If you want to use templating without passing specific data, you must explicitly set TemplatingContext: {} to trigger the engine.

    Example of a Nunjucks template (security-group.njk):

    Description: Nunjucks Security group template
    AWSTemplateFormatVersion: 2010-09-09
    Resources:
      SecurityGroup:
        Type: 'AWS::EC2::SecurityGroup'
        Properties:
          GroupDescription: "Open ports for incoming traffic"
          VpcId: "vpc-1234ABC"
          SecurityGroupIngress:
    {% for port in ports %}
            - CidrIp: "0.0.0.0/0"
              FromPort: {{ port }}
              ToPort: {{ port }}
              IpProtocol: tcp
    {% endfor %}
    SecurityGroupExample:
      Type: update-stacks
      Template: ./security-group.njk
      StackName: SecurityGroupExample
      TemplatingContext:
        ports:
          - 22
          - 80
      DefaultOrganizationBinding:
        Account: "*"
        Region: us-east-1
  3. Use cross-account references between resources

    master

    Org-formation enables resources in different accounts to reference each other (e.g., a CloudTrail in all accounts referencing an S3 bucket in a central Compliance account).

    When a resource in one account (Target A) uses !Ref or !GetAtt on a resource bound to a different account (Target B), org-formation automatically handles the plumbing:

    1. It creates a CloudFormation Export in the template deployed to Target B.
    2. It creates a CloudFormation Parameter in the template deployed to Target A.
    3. It maps the Export value to the Parameter during deployment.

    Example Workflow

    If you have a CloudTrail resource bound to all accounts (Account: "*") and an S3Bucket bound to a ComplianceAccount:

    Resources:
      S3Bucket:
        OrganizationBinding: !Ref CloudTrailBucketBinding
        Type: AWS::S3::Bucket
        # ...
    
      CloudTrail:
        OrganizationBinding: !Ref CloudTrailBinding
        Type: AWS::CloudTrail::Trail
        Properties:
          S3BucketName: !Ref S3Bucket # This cross-account reference is handled by org-formation
  4. Use Fn::EnumTargetAccounts to create arrays for cross-account permissions

    master

    The Fn::EnumTargetAccounts function generates an array of values (such as IAM ARNs) for every account included in a specified binding. This is primarily used to implement the principle of least-privilege when setting up cross-account IAM policies or resource policies.

    To avoid errors when a binding is empty, you should use the Fn::TargetCount function within a CloudFormation Condition to ensure the resource (like a BucketPolicy) is only created if the binding contains one or more accounts.

    # Example: Creating a policy that grants access to all accounts in a binding
    Resources:
      BucketReadPolicy:
        Type: AWS::S3::BucketPolicy
        Condition: CreateReadBucketPolicy
        Properties:
          Bucket: !Ref Bucket
          PolicyDocument:
            Statement:
              - Sid: "Read operations on bucket"
                Action:
                  - s3:Get*
                  - s3:List*
                Effect: "Allow"
                Resource:
                  - !Sub "${Bucket.Arn}"
                  - !Sub "${Bucket.Arn}/*"
                Principal:
                  AWS: Fn::EnumTargetAccounts ReadAccessAccountBinding arn:aws:iam::${account}:root
  5. Create a new AWS Account via OC::ORG::Account

    master

    You can provision new AWS accounts by adding an OC::ORG::Account resource to your organization.yml file.

    Key behaviors:

    • Identification: Since the AccountId is unknown at creation time, use RootEmail as the unique identifier. The AccountId will be generated and stored in the S3 state file; you can add it to your YAML later if desired.
    • Placement: Accounts not assigned to an Organizational Unit (OU) are added to the Organization Root. To add an account to an OU, use the Accounts attribute with a !Ref to the OU's logical name.
    • Root Access: The root user will not have a password initially. You must reset the password using the configured RootEmail.
    • Automation: You can trigger post-creation workflows (like notifications) by subscribing to the AccountCreated event from the oc.org-formation event source in AWS EventBridge.
    MyNewAccount:
      Type: OC::ORG::Account
      Properties:
        AccountName: My New Account
        RootEmail: aws-accounts+new@myorg.com
  6. Use the annotate-organization task

    master

    The annotate-organization task allows you to use an external account factory (such as AWS Control Tower) while still using org-formation to provision resources across the organization.

    Important: If you use annotate-organization, you must use it instead of update-organization.

    AnnotateOrganization:
      Type: annotate-organization
      DefaultOrganizationAccessRoleName: OrganizationAccountAccessRole
      ExcludeAccounts: ["123123123123", "123123123124"]
      AccountMapping:
        AccountA: "234234234234"
        AccountB: "234234234235"
  7. Understand AWS Organization Formation core features

    master

    AWS Organization Formation (org-formation) provides three primary capabilities for managing AWS Organizations via IaC:

    1. Resource Management: Managing AWS Organizations resources such as AWS Accounts, Organizational Units (OUs), and Service Control Policies (SCPs) as code.
    2. CloudFormation Annotations: Annotating CloudFormation templates with Organization Bindings to define where resources should be deployed and how they relate to the organization structure.
    3. Automated Deployment: Automating the deployment of changes to AWS Organizations resources, annotated CloudFormation templates, and other projects like CDK or Serverless.com.
  8. Use OrganizationBinding to control resource deployment

    master

    An OrganizationBinding defines the mapping of where specific resources should be created. Bindings allow you to specify target accounts and regions for your resources.

    • The value for a binding can be either a single string or a list.
    • Bindings are used to determine the deployment context for resources defined in the Resources section.
  9. Handle account removal from organization.yml

    master

    Removing an account from your organization.yml file does not delete the AWS account itself (as AWS does not support account deletion via API). The behavior depends on which command you run:

    • update: The account will be detached from organizational units and will no longer participate in organization bindings.
    • update-stacks: Any stacks deployed to that account via org-formation will be deleted from the target account. Stacks created by other means are untouched.

    To re-add an account, simply add it back to organization.yml and run update and update-stacks (or perform-tasks). org-formation identifies accounts via the RootEmail or AccountId attribute.

  10. Understand Organization Annotated CloudFormation

    master

    Organization Annotated CloudFormation is a pattern used to describe an entire AWS Organization's infrastructure within a single template structure. It uses an Organization section to define the topology (Accounts, Organizational Units, etc.) and a Bindings section to determine where specific resources are deployed.

    Key components include:

    • Organization Section: Describes the structure of the organization (Accounts, OUs, etc.).
    • Bindings: A named set of mappings that determine which resources are deployed to which accounts and regions. Any binding that does not explicitly specify a region will default to the organization's default.
    • Resource Section: Contains the actual AWS resources, which can use !Ref to access bindings to determine their deployment target.
  11. How OrganizationBinding works

    master

    The OrganizationBinding attribute determines where a CloudFormation resource is deployed within your AWS Organization. You can specify bindings at the resource level, within an OrganizationBindings section, or as a top-level DefaultOrganizationBinding.

    Bindings can be combined and are additive (except for ExcludeAccount).

    Binding Attributes Reference

    AttributeValueRemarks
    RegionString or list of StringResource will be created in all specified regions.
    Accountliteral '*'Resource will be created in all accounts except for the master account.
    Account!Ref or list of !RefResource will be created in the referred accounts.
    OrganizationalUnit!Ref or list of !RefResource will be created in all accounts in the referred OUs (including nested OUs).
    ExcludeAccount!Ref or list of !RefResource will not be created in the referred accounts.
    ExcludeOrganizationalUnit!Ref or list of !RefResource will not be created in the referred OUs (including nested OUs).
    IncludeMasterAccounttrue or falseIf true, resource will be created in the organizational master account.
    AccountsWithTagtag-nameResource will be created in all accounts having the specified tag.
    Resources:
      Bucket:
        OrganizationBinding:
          Region: eu-west-1
          Account:
           - !Ref Account1
           - !Ref Account2
        Type: AWS::S3::Bucket
  12. How Organization Bindings work

    master

    An Organization Binding is a core concept that allows you to specify target accounts and regions for resource deployment. When an Annotated CloudFormation template uses a binding, it creates deployment targets for every possible combination of the specified regions and accounts.

    Key behaviors:

    • A binding with 2 regions and 3 accounts results in 6 targets.
    • A binding with 0 regions and 6 accounts results in 0 targets.
    • To prevent deployment failures due to missing region specifications, you can use DefaultOrganizationBindingRegion to set a fallback region.

    Binding Attributes:

    • Region: Specifies the region(s) for the targets.
    • Account: Specifies a specific account, a list of accounts, or "*" to include all accounts except the master account.
    • IncludeMasterAccount: If true, includes the Master Account in the targets.
    • OrganizationalUnit: Includes accounts from one or more Organizational Units.
    • AccountsWithTag: Includes accounts that declare a specific tag in the organization.yml file.
    • ExcludeOrganizationalUnit: Excludes accounts from specific Organizational Units.
    • ExcludeAccount: Excludes specific accounts from the targets.

    All references (like !Ref Account1) must use the logical names declared in your organization.yml file.

    OrganizationBinding:
      Region: eu-west-1
      Account:
        - !Ref Account1
        - !Ref Account2