Skip to main content
  1. All Posts/

org-formation-cli

Tools TypeScript

AWS Organization Formation

AWS Organization Formation is an Infrastructure as Code (IaC) tool for AWS Organizations.

Features

AWS Organization Formation (also: org-formation) has 3 main features:

  1. Infrastructure as Code for AWS Organizations:

    Organization resources reference | Example organization file | CLI Reference

  <p>
     
  </p>
  
  <ol start="2" dir="auto">
    <li>
      CloudFormation annotations to provision resources cross account: <p>
        Annotated CloudFormation reference | Examples | CLI Reference </li> </ol> 
        
        <p>
           
        </p>
        
        <ol start="3" dir="auto">
          <li>
            Automation of account creation and resource provisioning: <p>
              Automation task file reference | Example tasks file | CLI Reference </li> </ol> 
              
              <p>
                Want more? here a list of 50+ features 😎😎😎
              </p>
              
              <h2 dir="auto">
                <a rel="nofollow noopener" target="_blank" id="user-content-installation" class="anchor" aria-hidden="true" href="#installation"></a>Installation
              </h2>
              
              <p>
                With <a rel="nofollow noopener" target="_blank" href="https://npmjs.org/">npm</a> installed, run
              </p>
              
              <pre class="notranslate"><code>&gt; npm install -g aws-organization-formation

              <p>
                You can now execute the command line program <code>org-formation</code>. try:
              </p>
              
              <pre class="notranslate"><code>&gt; org-formation --help

              <h3 dir="auto">
                <a rel="nofollow noopener" target="_blank" id="user-content-docker" class="anchor" aria-hidden="true" href="#docker"></a>Docker
              </h3>
              
              <p>
                If you choose, you can run org-formation in a docker container:
              </p>
              
              <pre># Set the AWS_PROFILE environment variable and pass it to the container

> AWS_PROFILE=example

Run the container>

Run the container #

> docker run –rm -it -v $HOME/.aws:/root/.aws:ro -v $PWD:/workdir -w /workdir -e AWS_PROFILE orgformation/org-formation-cli

              <p>
                Optional: create an alias for the container:
              </p>
              
              <pre>&gt; alias org-formation='docker run --rm -it -v $HOME/.aws:/root/.aws:ro -v $PWD:/workdir -w /workdir -e AWS_PROFILE orgformation/org-formation-cli'</pre>
              
              <h2 dir="auto">
                <a rel="nofollow noopener" target="_blank" id="user-content-getting-started" class="anchor" aria-hidden="true" href="#getting-started"></a>Getting started
              </h2>
              
              <p>
                💡Need help getting started? <a rel="nofollow noopener" target="_blank" href="https://join.slack.com/t/org-formation/shared_invite/enQtOTA5NjM3Mzc4ODUwLTMxZjYxYzljZTE5YWUzODE2MTNmYjM5NTY5Nzc3MzljNjVlZGQ1ODEzZDgyMWVkMDg3Mzk1ZjQ1ZjM4MDhlOGM">Get some on slack!</a><br /> 📖How to set up AWS Organizations? Off to a great start<br /> 🎧 Hear about org-formation in <a rel="nofollow noopener" target="_blank" href="https://open.spotify.com/episode/0VPwObFeQ68oImfqW3lIge?si=VNluO9ZaTc-p3cpps6IBQg">Real-World Serverless podcast #5</a><br /> 📺 See org-formation in <a rel="nofollow noopener" target="_blank" href="https://www.youtube.com/watch?v=mLAGHzidHJ0">Mastering AWS Organizations with Infrastructure-As-Code</a><br /> To get started you first need an <code>org-formation</code> template that describes all your Organization resources such as Accounts, OUs and SCPs.<br /> After <a rel="nofollow noopener" target="_blank" href="#installation">Installation</a> you can generate this file using the following command:
              </p>
              
              <pre class="notranslate"><code>&gt; org-formation init organization.yml  --region us-east-1 [--profile org-master-account]

              <p>
                example output organization.yml file
              </p>
              
              <pre>AWSTemplateFormatVersion: '2010-09-09-OC'

Organization: Root: Type: OC::ORG::MasterAccount Properties: AccountName: My Organization Root AccountId: ‘123123123123’ Tags: budget-alarm-threshold: ‘2500’ account-owner-email: my@email.com

OrganizationRoot: Type: OC::ORG::OrganizationRoot Properties: ServiceControlPolicies: - !Ref RestrictUnusedRegionsSCP

ProductionAccount: Type: OC::ORG::Account Properties: RootEmail: production@myorg.com AccountName: Production Account Tags: budget-alarm-threshold: ‘2500’ account-owner-email: my@email.com

DevelopmentAccount: Type: OC::ORG::Account Properties: RootEmail: development@myorg.com AccountName: Development Account Tags: budget-alarm-threshold: ‘2500’ account-owner-email: my@email.com

DevelopmentOU: Type: OC::ORG::OrganizationalUnit Properties: OrganizationalUnitName: development Accounts: - !Ref DevelopmentAccount

ProductionOU: Type: OC::ORG::OrganizationalUnit Properties: OrganizationalUnitName: production Accounts: - !Ref ProductionAccount

RestrictUnusedRegionsSCP: Type: OC::ORG::ServiceControlPolicy Properties: PolicyName: RestrictUnusedRegions Description: Restrict Unused regions PolicyDocument: Version: ‘2012-10-17’ Statement: - Sid: DenyUnsupportedRegions Effect: Deny NotAction: - ‘cloudfront:’ - ‘iam:’ - ‘route53:’ - ‘support:’ Resource: ‘*’ Condition: StringNotEquals: ‘aws:RequestedRegion’: - eu-west-1 - us-east-1 - eu-central-1

              <p>
                <strong>Note</strong>: If you prefer to set up CI/CD run <code>org-formation init-pipeline</code> instead. It will create a CodeCommit repository and CodePipeline that will update your organization upon every commit!<br /> You can make changes to the file you generated and update your organization using the <code>update</code> command. Alternatively, you can run <code>create-change-set</code> and <code>update-change-set</code>. Read more in the cli reference<br /> Once you got the hang of managing organization resources, use these organization resources to write smarter CloudFormation that allows you to provision resources across your organization. Read more about managing resources across accounts.
              </p>
              
              <h2 dir="auto">
                <a rel="nofollow noopener" target="_blank" id="user-content-why-is-this-important" class="anchor" aria-hidden="true" href="#why-is-this-important"></a>Why is this important?
              </h2>
              
              <p>
                Just like with the resources within your AWS Account, managing AWS Organization resources <strong>as code</strong> allows you to apply changes automatically, reducing manual work, inconsistencies and mistakes.<br /> If you are considering to use an account vending machine (e.g. <a rel="nofollow noopener" target="_blank" href="https://aws.amazon.com/controltower/">AWS Control Tower</a>) to create and manage new accounts within your organization: Do realize that the account vending machine allows you to quickly create organization resources but only has limited facilities when it comes to updating and maintaining these resources.
              </p>
              
              <h2 dir="auto">
                <a rel="nofollow noopener" target="_blank" id="user-content-questions-and-answers" class="anchor" aria-hidden="true" href="#questions-and-answers"></a>Questions and Answers
              </h2>
              
              <p>
                My operation takes a long time to complete / is slow.
              </p>
              
              <p>
                 <br /> Especially if you have a lot of accounts this can happen.<br /> An easy way to speed things up is by specifying the command-line argument <code>--max-concurrent-stacks 10</code> where 10 is the number of stacks to run in concurrently.<br /> Another way to speed things up is to run tasks in parallel this can be done with the argument <code>--max-concurrent-tasks 10</code>. This, however, has the side-effect that the logging might be somewhat harder to relate to a specific task (as it might be out of order).<br />  
              </p>
              
              <p>
                Is there a way around having to create new email accounts per account?
              </p>
              
              <p>
                 <br /> Every AWS account needs a unique root email address, there is no way around this&#8230;<br /> What you <strong>can do</strong> is to check whether your mail server allows you to append a &#8216;+&#8217; (plus sign) and another secondary name to your account to create new unique email addresses.<br /> Email to there addresses will end up in the mailbox assigned to the alias before the plus sign and this will still be considered a valid and unique email address when creating a new AWS Account.<br /> <strong>Example:</strong><br /> If your email address is <code>name@gmail.com</code> you will receive email send to <code>name+awsaccount1@gmail.com</code> and <code>name+awsaccount2@gmail.com</code> to your inbox.<br /> Mail servers that support this are gmail, aws workmail and hotmail.<br />  
              </p>
              
              <p>
                How do i set up MFA for the account used by org-formation?
              </p>
              
              <p>
                 <br /> <code>Org-formation</code> needs high privilege access to your master account. If you run <code>org-formation</code> manually it is wise to set up MFA.<br /> I assume you have credentials set up in <code>~/.aws/credentials</code> and this looks like (might well be called <code>default</code>):
              </p>
              
              <pre>[org-formation]

aws_access_key_id = AKIAxxxxxxxxx aws_secret_access_key = xxxxxxxxxxxxxxxxx

              <p>
                This allows org-formation to assume the IAM User that corresponds to the access key and secret using the option <code>--profile org-formation</code>.<br /> To enforce MFA you need to do the following:
              </p>
              
              <ol dir="auto">
                <li>
                  Assign an MFA device to the IAM User in the console.
                </li>
                <li>
                  Create a role in your master account that has high privileged access and enforces the use of MFA. We call this <code>MyOrgFormationRole</code>.
                </li>
                <li>
                  Create a profile that refers to the MyOrgFormation. We call this profile <code>org-formation-mfa</code>.
                </li>
                <li>
                  Test whether MFA has been setup correctly by running <code>org-formation describe-stacks --profile org-formation-mfa</code>.
                </li>
                <li>
                  If step #4 was successful you can strip the IAM user you use from permissions other than the once it needs to assume <code>MyOrgFormationRole</code>.
                </li>
              </ol>
              
              <p>
                Code snippets below:
              </p>
              
              <ol dir="auto">
                <li>
                  Creating the <code>MyOrgFormationRole</code> Role (step #2) &#8211; execute with CloudFormation
                </li>
              </ol>
              
              <pre>AWSTemplateFormatVersion: '2010-09-09'

Resources: MyOrgFormationRole: Type: AWS::IAM::Role Properties: RoleName: MyOrgFormationRole ManagedPolicyArns: - ‘arn:aws:iam::aws:policy/AdministratorAccess’ AssumeRolePolicyDocument: Version: ‘2012-10-17’ Statement: - Effect: Allow Principal: AWS: !Sub ‘arn:aws:iam::${AWS::AccountId}:root’ Action: sts:AssumeRole Condition: Bool: aws:MultiFactorAuthPresent: ’true’

              <ol start="2" dir="auto">
                <li>
                  Creating the profile <code>org-formation-mfa</code> (step #3) put in your <code>~/.aws/config</code> file.<br /> Replace <code>000000000000</code> with your master account id.<br /> The value for <code>mfa_serial</code> needs to be the value you got when setting up MFA for your user
                </li>
              </ol>
              
              <pre>[profile org-formation-mfa]

role_arn = arn:aws:iam::000000000000:role/MyOrgFormationRole source_profile = org-formation mfa_serial = arn:aws:iam::000000000000:mfa/my-user

              <ol start="3" dir="auto">
                <li>
                  Expected output when executing a command that requires MFA (step 4):
                </li>
              </ol>
              
              <pre>&gt; org-formation describe-stacks --profile org-formation-mfa

👋 Enter MFA code for arn:aws:iam::000000000000:mfa/my-user: XXXXXX # here you type in the put the MFA code { …regular output } # if successful the command will execute

              <ol start="4" dir="auto">
                <li>
                  The minimum set of permissions for your user<br /> Replace <code>000000000000</code> with your master account id (or the complete ARN for your Role )
                </li>
              </ol>
              
              <pre>Sid: 'AssumeMFARole'

Action: ‘sts:AssumeRole’ Effect: ‘Allow’ Resource: ‘arn:aws:iam::000000000000:role/MyOrgFormationRole’

              <p>
                Hope this helps<br />  
              </p>
              
              <p>
                What is the password of the root user for newly created accounts?
              </p>
              
              <p>
                 <br /> Accounts that are created have a root user but <strong>no password</strong>.<br /> You can create a password using the &#8216;Forgot password&#8217; process using the root email.<br /> <strong>Note:</strong> Once you have created a password and used it consider throwing the password away. You are not supposed to log in using root anyway and storing your password somewhere could only lead to losing it. As we just figured out above you didn&#8217;t need it in the first place.<br /> <strong>Do bind</strong> an MFA on your root user! Find info under the <a rel="nofollow noopener" target="_blank" href="https://console.aws.amazon.com/iam/home?/security_credentials#/home">IAM service section of the console</a><br /> <strong>Needless to add?</strong> don&#8217;t use a virtual MFA on the same device that has access to the email account used as RootEmail&#8230; this reduces your &#8216;multi-factor&#8217; authentication to a single factor 🤔🤣<br />  
              </p>
              
              <p>
                What happens when I remove an account from the organization.yml?
              </p>
              
              <p>
                 <br /> If you remove an account from the organization it will not be deleted. Deleting accounts using API calls is not supported by AWS.<br /> After running&#8230;</code>
              </p>