Today, AWS launched AWS Organizations: a new way for you to centrally manage all the AWS accounts your organization owns. Now you can arrange your AWS accounts into groups called organizational units (OUs) and apply policies to OUs or directly to accounts. For example, you can organize your accounts by application, environment, team, or any other grouping that makes sense for your business.

Organizations removes the need to manage security policies through separate AWS accounts. Before Organizations, if you had a set of AWS accounts, you had to ensure that users in those AWS accounts had the right level of access to AWS services. You had to either configure security settings on each account individually or write a custom script to iterate through each account. However, any user with administrative permissions in those AWS accounts could have bypassed the defined permissions. Organizations includes the launch of service control policies (SCPs), which give you the ability to configure one policy and have it apply to your entire organization, an OU, or an individual account. In this blog post, I walk through an example of how to use Organizations.

Create an organization

Let’s say you own software regulated by the healthcare or financial industry, and you want to deploy and run your software on AWS. In order to process, store, or transmit any protected health information on AWS, regulations such as ISO and SOC limit your software to using only designated AWS services. With Organizations, you can limit your software to access only the AWS services allowed by such regulations. SCPs can limit access to AWS services across all accounts in your organization such that the enforced policy cannot be overridden by any user in the AWS accounts on whom the SCP is enforced.

When creating a new organization, you want to start in the account that will become the master account. The master account is the account that will own the organization and all of the administrative actions applied to accounts by the organization. The master account can set up the SCPs, account groupings, and payment method of the other AWS accounts in the organization called member accounts. Like Consolidated Billing, the master account is also the account that pays the bills for the AWS activity of the member accounts, so choose it wisely.

For all my examples in this post, I use the AWS CLI. Organizations is also available through the AWS Management Console and AWS SDK.

In the following case, I use the create-organization API to create a new organization in Full_Control mode:

server:~$ aws organizations create-organization --mode FULL_CONTROL

returns:

{ "organization": { "availablePolicyTypes": [ { "status": "ENABLED", "type": "service_control_policy" } ], "masterAccountId": "000000000001", "masterAccountArn": "arn:aws:organizations::000000000001:account/o-1234567890/000000000001", "mode": "FULL_CONTROL", "masterAccountEmail": "master.account@example.corp", "id": "o-1234567890", "arn": "arn:aws:organizations::000000000001:organization/o-1234567890" } }

In this example, I want to set security policies on the organization, so I create it in Full_Control mode. You can create organizations in two different modes: Full_Control or Billing. Full_Control has all of the benefits of Billing mode but adds the additional ability to apply service control policies.

Note: If you currently use Consolidated Billing, your Consolidated Billing family is migrated automatically to AWS Organizations in Billing mode, which is equivalent to Consolidated Billing. All account activity charges accrued by member accounts are billed to the master account.

Add members to the organization

To populate the organization you’ve just created, you can either create new AWS accounts in the organization or invite existing accounts.

Create new AWS accounts

Organizations gives you APIs to programmatically create new AWS accounts in your organization. All you have to specify is the email address and account name. The rest of the account information (address, etc.) is inherited from the master account.

To create a new account by using the AWS CLI, you call create-account with the email address to assign to the new account and what you want to set the account name to be:

server:~$ aws organizations create-account --account-name DataIngestion --email data.ingestion.prod@example.corp

Creating an AWS account is an asynchronous process, so create-account returns a createAccountStatus response:

{ "createAccountStatus": { "requestedTimestamp": 1479783743.401, "state": "IN_PROGRESS", "id": "car-12345555555555555555555555556789", "accountName": "DataIngestion" } }

You can use describe-create-account-status with the createAccountStatus id to see when the AWS account is ready to use. Accounts are generally ready within minutes.

Invite existing AWS accounts

You can also invite existing AWS accounts to your organization. To invite an AWS account to your organization, you either need to know the AWS account ID or email address.

The command through the AWS CLI is invite-account-to-organization:

server:~$ aws organizations invite-account-to-organization --target id=data.processing.prod@example.corp,type=EMAIL

That command returns a handshake object, which contains all information about the request sent. In this instance, this was a request sent to the account at data.processing.prod@example.corp to join the organization with the id 1234567890:

{ "handshake": { "id": "h-77888888888888888888888888888777", "state": "OPEN", "resources": [ { "type": "ORGANIZATION", "resources": [ { "type": "MASTER_EMAIL", "value": "master.account@example.corp" }, { "type": "MASTER_NAME", "value": "Example Corp" }, { "type": "ORGANIZATION_MODE", "value": "FULL" } ], "value": "o-1234567890" }, { "type": "EMAIL", "value": "data.processing.prod@example.corp" } ], "parties": [ { "type": "EMAIL", "id": "data.processing.prod@example.corp" }, { "type": "ORGANIZATION", "id": "1234567890" } ], "action": "invite", "requestedTimestamp": 1479784006.008, "expirationTimestamp": 1481080006.008, "arn": "arn:aws:organizations::000000000001:handshake/o-1234567890/invite/h-77888888888888888888888888888777" } }

The preceding command sends an email to the account owner to notify them that you invited their account to join your organization. If the owner of the invited AWS account agrees to the terms of joining the organization, they can accept the request through a link in the email or by calling accept-handshake-request.

Viewing your organization

At this point, the organization is populated with two member accounts: DataIngestion and DataProcessing. The master account is master.account@example.corp. By default, accounts are placed directly under the root of your organization. The root is the base of your organizational structure—all OUs or accounts branch from it, as shown in the following illustration.

You can view all the accounts in the organization with the CLI command, list-accounts:

server:~$ aws organizations list-accounts

The list-accounts command returns a list of accounts and the details of how they joined the organization. Note that the master account is the organization along with the member accounts:

{ "accounts": [ { "status": "ACTIVE", "name": "DataIngestion", "joinedMethod": "CREATED", "joinedTimestamp": 1479784102.074, "id": "200000000001", "arn": "arn:aws:organizations::000000000001:account/o-1234567890/200000000001" }, { "status": "ACTIVE", "name": " DataProcessing ", "joinedMethod": "INVITED", "joinedTimestamp": 1479784102.074, "id": "200000000002", "arn": "arn:aws:organizations::000000000001:account/o-1234567890/200000000002" }, { "status": "ACTIVE", "name": "Example Corp", "joinedMethod": "INVITED", "joinedTimestamp": 1479783034.579, "id": "000000000001", "arn": "arn:aws:organizations::000000000001:account/o-1234567890/000000000001" } ] }

Service control policies

Service control policies (SCPs) let you apply controls on which AWS services and APIs are accessible to an AWS account. The SCPs apply to all entities within an account: the root user, AWS Identity and Access Management (IAM) users, and IAM roles. For this example, we’re going to set up an SCP to only allow access to seven AWS services.

Note that SCPs work in conjunction with IAM policies. Our SCP allows access to a set of services, but it is possible to set up an IAM policy to further restrict access for a user. AWS will enforce the most restrictive combination of the policies.

SCPs affect the master account differently than other accounts. To ensure you do not lock yourself out of your organization, SCPs applied to your organization do not apply to the master account.

Creating a policy

In this example, I want to make sure that only the given set of services is accessible in our AWS account, so I will create an Allow policy to grant access only to listed services. The following policy allows access to Amazon DynamoDB, Amazon RDS, Amazon EC2, Amazon S3, Amazon EMR, Amazon Glacier, and Elastic Load Balancing.

server:~$ aws organizations create-policy --name example-prod-policy --type service_control_policy --description "All services allowed by regulation policy." --content file://./Regulation-Policy.json

and inside Regulation-Policy.json:

{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:*","rds:*","ec2:*","s3:*","elasticmapreduce:*", "glacier:*","elasticloadbalancing:*" ], "Effect": "Allow", "Resource": "*" } ] }

SCPs follow the same structure as IAM policies. This example is an Allow policy, but SCPs also offer the ability to write Deny policies, restricting access to specific services and APIs.

To create an SCP in organizations through the CLI, you can store the earlier SCP in file Regulation-Policy.json and call create-policy:

server:~$ aws organizations create-policy --name example-prod-policy --type service_control_policy --description "All services allowed for regulation policy." --content file://./Regulation-Policy.json

The create-policy command returns the policy just created. Save the policy id for later when you want to apply it to an element in organizations:

{ "policy": { "content": "{

\"Version\": \"2012-10-17\",

\"Statement\": [

{

\"Action\": [

\"dynamodb: *\",\"rds: *\",\"ec2: *\",\"s3: *\",\"elasticmapreduce: *\",\"glacier: *\",\"elasticloadbalancing: *\"

],

\"Effect\": \"Allow\",

\"Resource\": \"*\"

}

]

}

", "policySummary": { "description": "All services allowed for regulation policy.", "type": "service_control_policy", "id": " p-yyy12346 ", "arn": "arn:aws:organizations:: 000000000001:policy/o-1234567890/service_control_policy/p-yyy12346", "name": "example-prod-policy" } } }

Attaching a policy

After you create your policy, you can attach it to entities in your organization. You can attach policies to the root account, an OU, or an individual account. Accounts inherit all policies above them in the organizational tree. To keep this example simple, attach the Example Corp. Prod SCP (as defined in the example-prod-policy) to your entire organization and attach the policy to the root. Because the root is the top element of an organization’s tree, policies applied to the tree apply to every member account in the organization.

Using the CLI, you first need to call list-roots to get the root id. Once you have the root id, you can call attach-policy, passing it in the example-prod-policy id (collected from the create-policy response) and the root id.

server:~$ aws organizations list-roots { "roots": [ { "policyTypes": [ { "status": "ENABLED", "type": "service_control_policy" } ], "id": " r-4444 ", "arn": "arn:aws:organizations::000000000001:root/o-1234567890/r-4444", "name": "Root" } ] } server:~$ aws organizations attach-policy --target-id r-4444 --policy-id p-yyy12346

Let’s now verify the policies on the root. Calling list-policies-for-target on the root will display all policies attached to the root of the organization.

server:~$ aws organizations list-policies-for-target --target-id r-4444 --filter service_control_policy { "policies": [ { "awsManaged": false, "description": "All services allowed by regulation policy.", "type": "service_control_policy", "id": " p-yyy12346", "arn": "arn:aws:organizations::000000000001:policy/o-1234567890/service_control_policy/p-yyy12346", "name": " example-prod-policy " }, { "awsManaged": true, "description": "Allows access to every operation", "type": "service_control_policy", "id": "p-FullAWSAccess", "arn": "arn:aws:organizations::aws:policy/service_control_policy/p-FullAWSAccess", "name": " FullAWSAccess " } ] }

Two policies are returned from list-policies-for-target on the root: the example-prod-policy, and the FullAWSAccess policy. FullAWSAccess is an AWS managed policy that is applied to every element in the organization by default. When you create your organization, every root, OU, and account has the FullAWSAccess policy, which allows your organization to have access to everything in AWS (*:*).

If you want to limit your organization’s access to only the services specific to the Example Corp. Prod SCP, you must remove the FullAWSAccess policy. In this case, Organizations will allow the root account to have access to the services allowed in the FullAWSAccess policy and the Example Corp. Prod SCP, which is all AWS services. To have the restrictions intended by the Example Corp. Prod SCP, you have to remove the FullAWSAccess policy. To do this with the CLI:

aws organizations detach-policy --policy-id p-FullAWSAccess --target-id r-4444

And one final list to verify only the example-prod-policy is attached to the root:

aws organizations list-policies-for-target --target-id r-4444 --filter service_control_policy { "policies": [ { "awsManaged": false, "description": "All services allowed by regulation policy.", "type": "service_control_policy", "id": "p-yyy12346", "arn": "arn:aws:organizations:: 000000000001:policy/o-1234567890/service_control_policy/p-yyy12346", "name": "example-prod-policy" } ] }

Now, you have an extra layer of protection, limiting all accounts in your organization to only those AWS services that are compliant with Example Corp’s regulations.

More advanced structure

If you want to break down your organization further, you can add OUs and apply policies. For example, some of your AWS accounts might not be used for protected health information and therefore have no need for such a restrictive SCP.

For example, you may have a development team that needs to use and experiment with different AWS services to do their job. In this case, you want to set the controls on these accounts to be lighter than the controls on the accounts that have access to regulated customer information. With Organizations, you can, for example, create an OU to represent the medical software you run in production, and a different OU to hold the accounts developers use. You can then apply different security restrictions to each OU.

The following illustration shows three developer accounts that are part of a Developer Research OU. The original two accounts that require regulation protections are in a Production OU. We also detached our Example Corp. Prod Policy from the root and instead attached it to the Production OU. Finally, any restrictions not related to regulations are kept at the root level by placing them in a new Company policy.

In the preceding illustration, the accounts in the Developer Research OU have the Company policy applied to them because their OU is still under the root with that policy. The accounts in the Production OU have both SCPs (Company policy and Example Corp. Prod Policy) applied to them. As is true with IAM policies, SCPs apply the more restrictive intersection of the two policies to the account. If the Company Policy SCP allowed Glacier, EMR, S3, EC2, RDS, Dynamo, Amazon Kinesis, AWS Lambda, and Amazon Redshift, the policy application for accounts in the Production OU would be the intersection, as shown in the following chart.

The accounts in the Production OU have both the Company policy SCP and the Example Corp. Prod Policy SCP applied to them. The intersection of the two policies applies, so these accounts have access to DynamoDB, Glacier, EMR, RDS, EC2, and S3. Because Redshift, Lambda, and Kinesis are not in the Example Corp. Prod Policy SCP, the accounts in the Production OU are not allowed to access them.

To summarize policy application: all elements (root account, OUs, accounts) have FullAWSAccess (*:*) by default. If you have multiple SCPs on the same element, Organizations takes the union. When policies are inherited across multiple elements in the organizational tree, Organizations takes the intersection of the SCPs. And finally, the master account has unique protections on it; only SCPs attached directly to it will change its access.

Conclusion

AWS Organizations makes it easy to manage multiple AWS accounts from a single master account. You can use Organizations to group accounts into organizational units and manage your accounts by application, environment, team, or any other grouping that makes sense for your business. SCPs give you the ability to apply policies to multiple accounts at once.

To learn more, see the AWS Organizations home page and sign up for the AWS Organizations Preview today. If you are at AWS re:Invent 2016, you can also attend session SAC323 – NEW SERVICE: Centrally Manage Multiple AWS Accounts with AWS Organizations on Wednesday, November 30, at 11:00 A.M.

– Caitlyn

Want more AWS Security how-to content, news, and feature announcements? Follow us on Twitter.