Merge pull request #2360 from ashleygould/issue_2355

[Resolves #2355] - create_organization(): add master account, default…
This commit is contained in:
Mike Grima 2019-08-07 15:11:48 -07:00 committed by GitHub
commit fa07d4973b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 13 deletions

View File

@ -2,6 +2,7 @@ from __future__ import unicode_literals
import datetime
import re
import json
from moto.core import BaseBackend, BaseModel
from moto.core.exceptions import RESTError
@ -151,7 +152,6 @@ class FakeRoot(FakeOrganizationalUnit):
class FakeServiceControlPolicy(BaseModel):
def __init__(self, organization, **kwargs):
self.type = 'POLICY'
self.content = kwargs.get('Content')
self.description = kwargs.get('Description')
self.name = kwargs.get('Name')
@ -197,7 +197,38 @@ class OrganizationsBackend(BaseBackend):
def create_organization(self, **kwargs):
self.org = FakeOrganization(kwargs['FeatureSet'])
self.ou.append(FakeRoot(self.org))
root_ou = FakeRoot(self.org)
self.ou.append(root_ou)
master_account = FakeAccount(
self.org,
AccountName='master',
Email=self.org.master_account_email,
)
master_account.id = self.org.master_account_id
self.accounts.append(master_account)
default_policy = FakeServiceControlPolicy(
self.org,
Name='FullAWSAccess',
Description='Allows access to every operation',
Type='SERVICE_CONTROL_POLICY',
Content=json.dumps(
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "*",
"Resource": "*"
}
]
}
)
)
default_policy.id = utils.DEFAULT_POLICY_ID
default_policy.aws_managed = True
self.policies.append(default_policy)
self.attach_policy(PolicyId=default_policy.id, TargetId=root_ou.id)
self.attach_policy(PolicyId=default_policy.id, TargetId=master_account.id)
return self.org.describe()
def describe_organization(self):
@ -216,6 +247,7 @@ class OrganizationsBackend(BaseBackend):
def create_organizational_unit(self, **kwargs):
new_ou = FakeOrganizationalUnit(self.org, **kwargs)
self.ou.append(new_ou)
self.attach_policy(PolicyId=utils.DEFAULT_POLICY_ID, TargetId=new_ou.id)
return new_ou.describe()
def get_organizational_unit_by_id(self, ou_id):
@ -258,6 +290,7 @@ class OrganizationsBackend(BaseBackend):
def create_account(self, **kwargs):
new_account = FakeAccount(self.org, **kwargs)
self.accounts.append(new_account)
self.attach_policy(PolicyId=utils.DEFAULT_POLICY_ID, TargetId=new_account.id)
return new_account.create_account_status
def get_account_by_id(self, account_id):
@ -358,8 +391,7 @@ class OrganizationsBackend(BaseBackend):
def attach_policy(self, **kwargs):
policy = next((p for p in self.policies if p.id == kwargs['PolicyId']), None)
if (re.compile(utils.ROOT_ID_REGEX).match(kwargs['TargetId']) or
re.compile(utils.OU_ID_REGEX).match(kwargs['TargetId'])):
if (re.compile(utils.ROOT_ID_REGEX).match(kwargs['TargetId']) or re.compile(utils.OU_ID_REGEX).match(kwargs['TargetId'])):
ou = next((ou for ou in self.ou if ou.id == kwargs['TargetId']), None)
if ou is not None:
if ou not in ou.attached_policies:

View File

@ -4,7 +4,8 @@ import random
import string
MASTER_ACCOUNT_ID = '123456789012'
MASTER_ACCOUNT_EMAIL = 'fakeorg@moto-example.com'
MASTER_ACCOUNT_EMAIL = 'master@example.com'
DEFAULT_POLICY_ID = 'p-FullAWSAccess'
ORGANIZATION_ARN_FORMAT = 'arn:aws:organizations::{0}:organization/{1}'
MASTER_ACCOUNT_ARN_FORMAT = 'arn:aws:organizations::{0}:account/{1}/{0}'
ACCOUNT_ARN_FORMAT = 'arn:aws:organizations::{0}:account/{1}/{2}'
@ -26,7 +27,7 @@ ROOT_ID_REGEX = r'r-[a-z0-9]{%s}' % ROOT_ID_SIZE
OU_ID_REGEX = r'ou-[a-z0-9]{%s}-[a-z0-9]{%s}' % (ROOT_ID_SIZE, OU_ID_SUFFIX_SIZE)
ACCOUNT_ID_REGEX = r'[0-9]{%s}' % ACCOUNT_ID_SIZE
CREATE_ACCOUNT_STATUS_ID_REGEX = r'car-[a-z0-9]{%s}' % CREATE_ACCOUNT_STATUS_ID_SIZE
SCP_ID_REGEX = r'p-[a-z0-9]{%s}' % SCP_ID_SIZE
SCP_ID_REGEX = r'%s|p-[a-z0-9]{%s}' % (DEFAULT_POLICY_ID, SCP_ID_SIZE)
def make_random_org_id():

View File

@ -1,7 +1,6 @@
from __future__ import unicode_literals
import six
import sure # noqa
import datetime
from moto.organizations import utils

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
import boto3
import json
import six
import sure # noqa
from botocore.exceptions import ClientError
from nose.tools import assert_raises
@ -27,6 +26,25 @@ def test_create_organization():
validate_organization(response)
response['Organization']['FeatureSet'].should.equal('ALL')
response = client.list_accounts()
len(response['Accounts']).should.equal(1)
response['Accounts'][0]['Name'].should.equal('master')
response['Accounts'][0]['Id'].should.equal(utils.MASTER_ACCOUNT_ID)
response['Accounts'][0]['Email'].should.equal(utils.MASTER_ACCOUNT_EMAIL)
response = client.list_policies(Filter='SERVICE_CONTROL_POLICY')
len(response['Policies']).should.equal(1)
response['Policies'][0]['Name'].should.equal('FullAWSAccess')
response['Policies'][0]['Id'].should.equal(utils.DEFAULT_POLICY_ID)
response['Policies'][0]['AwsManaged'].should.equal(True)
response = client.list_targets_for_policy(PolicyId=utils.DEFAULT_POLICY_ID)
len(response['Targets']).should.equal(2)
root_ou = [t for t in response['Targets'] if t['Type'] == 'ROOT'][0]
root_ou['Name'].should.equal('Root')
master_account = [t for t in response['Targets'] if t['Type'] == 'ACCOUNT'][0]
master_account['Name'].should.equal('master')
@mock_organizations
def test_describe_organization():
@ -177,11 +195,11 @@ def test_list_accounts():
response = client.list_accounts()
response.should.have.key('Accounts')
accounts = response['Accounts']
len(accounts).should.equal(5)
len(accounts).should.equal(6)
for account in accounts:
validate_account(org, account)
accounts[3]['Name'].should.equal(mockname + '3')
accounts[2]['Email'].should.equal(mockname + '2' + '@' + mockdomain)
accounts[4]['Name'].should.equal(mockname + '3')
accounts[3]['Email'].should.equal(mockname + '2' + '@' + mockdomain)
@mock_organizations
@ -291,8 +309,10 @@ def test_list_children():
response02 = client.list_children(ParentId=root_id, ChildType='ORGANIZATIONAL_UNIT')
response03 = client.list_children(ParentId=ou01_id, ChildType='ACCOUNT')
response04 = client.list_children(ParentId=ou01_id, ChildType='ORGANIZATIONAL_UNIT')
response01['Children'][0]['Id'].should.equal(account01_id)
response01['Children'][0]['Id'].should.equal(utils.MASTER_ACCOUNT_ID)
response01['Children'][0]['Type'].should.equal('ACCOUNT')
response01['Children'][1]['Id'].should.equal(account01_id)
response01['Children'][1]['Type'].should.equal('ACCOUNT')
response02['Children'][0]['Id'].should.equal(ou01_id)
response02['Children'][0]['Type'].should.equal('ORGANIZATIONAL_UNIT')
response03['Children'][0]['Id'].should.equal(account02_id)
@ -591,4 +611,3 @@ def test_list_targets_for_policy_exception():
ex.operation_name.should.equal('ListTargetsForPolicy')
ex.response['Error']['Code'].should.equal('400')
ex.response['Error']['Message'].should.contain('InvalidInputException')