Skip to content
Get Started for Free

Organizations

Amazon Web Services Organizations is an account management service that allows you to consolidate multiple different AWS accounts into an organization. It allows you to manage different accounts in a single organization and consolidate billing. With Organizations, you can also attach different policies to your organizational units (OUs) or individual accounts in your organization.

Organizations is available over LocalStack for AWS and the supported APIs are available over our configuration page.

In this getting started guide, you’ll learn how to create your local AWS Organization and configure it with member accounts. This guide is intended for users who wish to get more acquainted with Organizations, and assumes you have basic knowledge of the AWS CLI (and our awslocal wrapper script). To get started, start your LocalStack instance using your preferred method:

  1. Create a new local AWS Organization with the feature set flag set to ALL:

    Terminal window
    awslocal organizations create-organization --feature-set ALL
  2. You can now run the describe-organization command to see the details of your organization:

    Terminal window
    awslocal organizations describe-organization
  3. You can now create an AWS account that would be a member of your organization:

    Terminal window
    awslocal organizations create-account \
    --email example@example.com \
    --account-name "Test Account"

    Since LocalStack essentially mocks AWS, the account creation is instantaneous. You can now run the list-accounts command to see the details of your organization:

    Terminal window
    awslocal organizations list-accounts
  4. You can also remove a member account from your organization:

    Terminal window
    awslocal organizations remove-account-from-organization --account-id <ACCOUNT_ID>
  5. To close an account in your organization, you can run the close-account command:

    Terminal window
    awslocal organizations close-account --account-id 000000000000
  6. You can use organizational units (OUs) to group accounts together to administer as a single unit. To create an OU, you can run:

    Terminal window
    awslocal organizations list-roots
    awslocal organizations list-children \
    --parent-id <PARENT-ID> \
    --child-type ORGANIZATIONAL_UNIT
    awslocal organizations create-organizational-unit \
    --parent-id <PARENT-ID> \
    --name New-Child-OU
  7. Before you can create and attach a policy to your organization, you must enable a policy type. To enable a policy type, you can run:

    Terminal window
    awslocal organizations enable-policy-type \
    --root-id <ROOT-ID> \
    --policy-type SERVICE_CONTROL_POLICY

    To disable a policy type, you can run:

    Terminal window
    awslocal organizations disable-policy-type \
    --root-id <ROOT-ID> \
    --policy-type SERVICE_CONTROL_POLICY
  8. To view the policies that are attached to your organization, you can run:

    Terminal window
    awslocal organizations list-policies --filter SERVICE_CONTROL_POLICY
  9. To delete an organization, you can run:

    Terminal window
    awslocal organizations delete-organization

Service Control Policies (SCPs) set the maximum permissions for accounts in your organization. When IAM enforcement is enabled, LocalStack checks SCPs together with other applicable policies. A request goes through only if both the principal’s policies, resource’s policies and the SCPs covering its account allow the action on the resource.

To turn on SCP enforcement, start LocalStack with ENFORCE_IAM=1 and enable the SERVICE_CONTROL_POLICY policy type on your organization root (see the getting started steps above).

LocalStack evaluates SCPs at each level of the organization hierarchy: root, organizational unit, and account. An action must be allowed by an SCP at every level between the root and the account. If any level lacks an Allow, the result is an implicit deny, and an explicit Deny overrides any Allow.

LocalStack enforces SCPs for cross-account access, where a principal in one account uses a resource owned by another account.

For a cross-account request, LocalStack checks the SCPs of the source account (the account making the request). A deny in those SCPs blocks the request even when the target resource’s policy grants access.

Consider a member account that lists the objects of an S3 bucket in another account of the same organization, with a bucket policy that grants the member account access:

Terminal window
# Run as the member (source) account
awslocal s3api list-objects-v2 --bucket cross-account-bucket

The default FullAWSAccess SCP lets the request succeed on the bucket policy. Attach an SCP that denies s3:ListBucket to the member account, and the request fails:

Output
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: User: arn:aws:iam::111111111111:user/test is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::cross-account-bucket" with an explicit deny in a service control policy

An SCP that allows only unrelated actions (for example, an ec2:*-only SCP) produces an implicit deny, since no SCP allows s3:ListBucket:

Output
An error occurred (AccessDenied) when calling the ListObjectsV2 operation: User: arn:aws:iam::111111111111:user/test is not authorized to perform: s3:ListBucket on resource: "arn:aws:s3:::cross-account-bucket" because no service control policy allows the s3:ListBucket action

The management account stays exempt from SCPs for cross-account requests too.

Testing SCPs with the IAM Policy Simulator

Section titled “Testing SCPs with the IAM Policy Simulator”

You can use the IAM Policy Simulator to check whether a principal’s request would be allowed or denied without running it against your resources. LocalStack evaluates SCPs during policy simulation, so you can validate SCP behavior with SimulatePrincipalPolicy before making live requests.

Terminal window
awslocal iam simulate-principal-policy \
--policy-source-arn arn:aws:iam::111111111111:user/test \
--action-names s3:ListBucket \
--resource-arns arn:aws:s3:::cross-account-bucket

When SCPs affect the decision, LocalStack populates the OrganizationsDecisionDetail field of the EvaluationResult, so you can see whether an SCP allowed the action.

When you create or update a Service Control Policy (SCP) with CreatePolicy or UpdatePolicy, LocalStack validates the policy document against the syntax rules that SCPs must follow. A policy that violates any of these rules is rejected with a MalformedPolicyDocumentException or a ConstraintViolationException, matching the behavior you would see on AWS.

The following constraints are enforced for SCPs:

  • No Principal or NotPrincipal elements: unlike identity-based or resource-based IAM policies, SCPs cannot specify a Principal or NotPrincipal key inside a Statement. A policy that includes either key is rejected with a MalformedPolicyDocumentException.
  • Maximum policy size of 10,240 characters: a policy document larger than 10,240 characters is rejected with a ConstraintViolationException (reason POLICY_CONTENT_LIMIT_EXCEEDED). This matches the limit enforced by AWS in practice.
  • A single policy object: the document must be a single JSON object. Passing a JSON array of policy objects is rejected.
  • A single Statement key: the document may contain only one Statement key. Duplicate Statement keys (or any other duplicate keys) cause the policy to be rejected as malformed.
  • Resources must be present: each statement must contain a Resource element. Specific resource ARNs (not just the * wildcard) are accepted.

For example, the following policy is rejected because it includes a Principal element, which is not permitted in an SCP:

Terminal window
awslocal organizations create-policy \
--name "InvalidSCP" \
--description "SCP with a Principal element" \
--type SERVICE_CONTROL_POLICY \
--content '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "*"
}
]
}'
OperationImplementedVerified on Kubernetes
Page 1 of 0
Was this page helpful?