disallow organization deletion when accounts are members, allow removal of accounts from organization (#4773)

This commit is contained in:
Daniel Fangl 2022-01-25 11:25:40 +01:00 committed by GitHub
parent 3f534119f4
commit ebe74d2eb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 1 deletions

View File

@ -71,7 +71,7 @@ organizations
- [X] list_targets_for_policy
- [X] move_account
- [X] register_delegated_administrator
- [ ] remove_account_from_organization
- [X] remove_account_from_organization
- [X] tag_resource
- [X] untag_resource
- [X] update_organizational_unit

View File

@ -381,6 +381,11 @@ class OrganizationsBackend(BaseBackend):
return self.org.describe()
def delete_organization(self, **kwargs):
if [account for account in self.accounts if account.name != "master"]:
raise RESTError(
"OrganizationNotEmptyException",
"To delete an organization you must first remove all member accounts (except the master).",
)
self._reset()
return {}
@ -885,5 +890,11 @@ class OrganizationsBackend(BaseBackend):
else:
raise InvalidInputException("You specified an invalid value.")
def remove_account_from_organization(self, **kwargs):
account = self.get_account_by_id(kwargs["AccountId"])
for policy in account.attached_policies:
policy.attachments.remove(account)
self.accounts.remove(account)
organizations_backend = OrganizationsBackend()

View File

@ -215,3 +215,10 @@ class OrganizationsResponse(BaseResponse):
return json.dumps(
self.organizations_backend.detach_policy(**self.request_params)
)
def remove_account_from_organization(self):
return json.dumps(
self.organizations_backend.remove_account_from_organization(
**self.request_params
)
)

View File

@ -420,6 +420,49 @@ def test_get_paginated_list_create_account_status():
validate_create_account_status(createAccountStatus)
@mock_organizations
def test_remove_account_from_organization():
client = boto3.client("organizations", region_name="us-east-1")
client.create_organization(FeatureSet="ALL")["Organization"]
create_account_status = client.create_account(
AccountName=mockname, Email=mockemail
)["CreateAccountStatus"]
account_id = create_account_status["AccountId"]
def created_account_exists(accounts):
return any(
account
for account in accounts
if account["Name"] == mockname and account["Email"] == mockemail
)
accounts = client.list_accounts()["Accounts"]
assert len(accounts) == 2
assert created_account_exists(accounts)
client.remove_account_from_organization(AccountId=account_id)
accounts = client.list_accounts()["Accounts"]
assert len(accounts) == 1
assert not created_account_exists(accounts)
@mock_organizations
def test_delete_organization_with_existing_account():
client = boto3.client("organizations", region_name="us-east-1")
client.create_organization(FeatureSet="ALL")
create_account_status = client.create_account(
Email=mockemail, AccountName=mockname
)["CreateAccountStatus"]
account_id = create_account_status["AccountId"]
with pytest.raises(ClientError) as e:
client.delete_organization()
e.match("OrganizationNotEmptyException")
client.remove_account_from_organization(AccountId=account_id)
client.delete_organization()
with pytest.raises(ClientError) as e:
client.describe_organization()
e.match("AWSOrganizationsNotInUseException")
# Service Control Policies
policy_doc01 = dict(
Version="2012-10-17",