added organizations detach_policy response, model, and tests, issue #… (#3278)

* added organizations detach_policy response, model, and tests, issue #3239

Signed-off-by: Ben <ben.lipscomb@fmr.com>

* Created individual tests for detach_policy exceptions, updated regex statements for Root, OU, and Account Id
This commit is contained in:
Benjamin 2020-09-25 11:55:29 -04:00 committed by GitHub
parent a4701dbbe6
commit 82dbaadfc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 170 additions and 1 deletions

View File

@ -821,5 +821,36 @@ class OrganizationsBackend(BaseBackend):
return dict(Root=root.describe())
def detach_policy(self, **kwargs):
policy = self.get_policy_by_id(kwargs["PolicyId"])
root_id_regex = utils.ROOT_ID_REGEX
ou_id_regex = utils.OU_ID_REGEX
account_id_regex = utils.ACCOUNT_ID_REGEX
target_id = kwargs["TargetId"]
if re.match(root_id_regex, target_id) or re.match(ou_id_regex, target_id):
ou = next((ou for ou in self.ou if ou.id == target_id), None)
if ou is not None:
if ou in ou.attached_policies:
ou.attached_policies.remove(policy)
policy.attachments.remove(ou)
else:
raise RESTError(
"OrganizationalUnitNotFoundException",
"You specified an organizational unit that doesn't exist.",
)
elif re.match(account_id_regex, target_id):
account = next(
(account for account in self.accounts if account.id == target_id), None,
)
if account is not None:
if account in account.attached_policies:
account.attached_policies.remove(policy)
policy.attachments.remove(account)
else:
raise AccountNotFoundException
else:
raise InvalidInputException("You specified an invalid value.")
organizations_backend = OrganizationsBackend()

View File

@ -201,3 +201,8 @@ class OrganizationsResponse(BaseResponse):
return json.dumps(
self.organizations_backend.disable_policy_type(**self.request_params)
)
def detach_policy(self):
return json.dumps(
self.organizations_backend.detach_policy(**self.request_params)
)

View File

@ -467,6 +467,139 @@ def test_attach_policy():
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
@mock_organizations
def test_detach_policy():
client = boto3.client("organizations", region_name="us-east-1")
org = client.create_organization(FeatureSet="ALL")["Organization"]
root_id = client.list_roots()["Roots"][0]["Id"]
ou_id = client.create_organizational_unit(ParentId=root_id, Name="ou01")[
"OrganizationalUnit"
]["Id"]
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
"CreateAccountStatus"
]["AccountId"]
policy_id = client.create_policy(
Content=json.dumps(policy_doc01),
Description="A dummy service control policy",
Name="MockServiceControlPolicy",
Type="SERVICE_CONTROL_POLICY",
)["Policy"]["PolicySummary"]["Id"]
client.attach_policy(PolicyId=policy_id, TargetId=ou_id)
client.attach_policy(PolicyId=policy_id, TargetId=root_id)
client.attach_policy(PolicyId=policy_id, TargetId=account_id)
response = client.detach_policy(PolicyId=policy_id, TargetId=ou_id)
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
response = client.detach_policy(PolicyId=policy_id, TargetId=root_id)
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
response = client.detach_policy(PolicyId=policy_id, TargetId=account_id)
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
@mock_organizations
def test_detach_policy_root_ou_not_found_exception():
client = boto3.client("organizations", region_name="us-east-1")
org = client.create_organization(FeatureSet="ALL")["Organization"]
root_id = client.list_roots()["Roots"][0]["Id"]
ou_id = client.create_organizational_unit(ParentId=root_id, Name="ou01")[
"OrganizationalUnit"
]["Id"]
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
"CreateAccountStatus"
]["AccountId"]
policy_id = client.create_policy(
Content=json.dumps(policy_doc01),
Description="A dummy service control policy",
Name="MockServiceControlPolicy",
Type="SERVICE_CONTROL_POLICY",
)["Policy"]["PolicySummary"]["Id"]
client.attach_policy(PolicyId=policy_id, TargetId=root_id)
client.attach_policy(PolicyId=policy_id, TargetId=account_id)
with assert_raises(ClientError) as e:
response = client.detach_policy(PolicyId=policy_id, TargetId="r-xy85")
ex = e.exception
ex.operation_name.should.equal("DetachPolicy")
ex.response["Error"]["Code"].should.equal("400")
ex.response["Error"]["Message"].should.contain(
"OrganizationalUnitNotFoundException"
)
@mock_organizations
def test_detach_policy_ou_not_found_exception():
client = boto3.client("organizations", region_name="us-east-1")
org = client.create_organization(FeatureSet="ALL")["Organization"]
root_id = client.list_roots()["Roots"][0]["Id"]
ou_id = client.create_organizational_unit(ParentId=root_id, Name="ou01")[
"OrganizationalUnit"
]["Id"]
policy_id = client.create_policy(
Content=json.dumps(policy_doc01),
Description="A dummy service control policy",
Name="MockServiceControlPolicy",
Type="SERVICE_CONTROL_POLICY",
)["Policy"]["PolicySummary"]["Id"]
client.attach_policy(PolicyId=policy_id, TargetId=ou_id)
with assert_raises(ClientError) as e:
response = client.detach_policy(
PolicyId=policy_id, TargetId="ou-zx86-z3x4yr2t7"
)
ex = e.exception
ex.operation_name.should.equal("DetachPolicy")
ex.response["Error"]["Code"].should.equal("400")
ex.response["Error"]["Message"].should.contain(
"OrganizationalUnitNotFoundException"
)
@mock_organizations
def test_detach_policy_account_id_not_found_exception():
client = boto3.client("organizations", region_name="us-east-1")
org = client.create_organization(FeatureSet="ALL")["Organization"]
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
"CreateAccountStatus"
]["AccountId"]
policy_id = client.create_policy(
Content=json.dumps(policy_doc01),
Description="A dummy service control policy",
Name="MockServiceControlPolicy",
Type="SERVICE_CONTROL_POLICY",
)["Policy"]["PolicySummary"]["Id"]
client.attach_policy(PolicyId=policy_id, TargetId=account_id)
with assert_raises(ClientError) as e:
response = client.detach_policy(PolicyId=policy_id, TargetId="111619863336")
ex = e.exception
ex.operation_name.should.equal("DetachPolicy")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.response["Error"]["Code"].should.contain("AccountNotFoundException")
ex.response["Error"]["Message"].should.equal(
"You specified an account that doesn't exist."
)
@mock_organizations
def test_detach_policy_invalid_target_exception():
client = boto3.client("organizations", region_name="us-east-1")
org = client.create_organization(FeatureSet="ALL")["Organization"]
root_id = client.list_roots()["Roots"][0]["Id"]
ou_id = client.create_organizational_unit(ParentId=root_id, Name="ou01")[
"OrganizationalUnit"
]["Id"]
policy_id = client.create_policy(
Content=json.dumps(policy_doc01),
Description="A dummy service control policy",
Name="MockServiceControlPolicy",
Type="SERVICE_CONTROL_POLICY",
)["Policy"]["PolicySummary"]["Id"]
client.attach_policy(PolicyId=policy_id, TargetId=ou_id)
with assert_raises(ClientError) as e:
response = client.detach_policy(PolicyId=policy_id, TargetId="invalidtargetid")
ex = e.exception
ex.operation_name.should.equal("DetachPolicy")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.response["Error"]["Code"].should.contain("InvalidInputException")
ex.response["Error"]["Message"].should.equal("You specified an invalid value.")
@mock_organizations
def test_delete_policy():
client = boto3.client("organizations", region_name="us-east-1")
@ -798,7 +931,7 @@ def test_tag_resource_errors():
with assert_raises(ClientError) as e:
client.tag_resource(
ResourceId="000000000000", Tags=[{"Key": "key", "Value": "value"},]
ResourceId="000000000000", Tags=[{"Key": "key", "Value": "value"},],
)
ex = e.exception
ex.operation_name.should.equal("TagResource")