2018-07-14 18:35:37 +00:00
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
2020-07-14 09:27:39 +00:00
|
|
|
from datetime import datetime
|
|
|
|
|
2021-06-05 14:12:17 +00:00
|
|
|
from moto.organizations.exceptions import InvalidInputException, TargetNotFoundException
|
|
|
|
from moto.organizations.models import (
|
|
|
|
FakeAccount,
|
|
|
|
FakeOrganization,
|
|
|
|
FakeOrganizationalUnit,
|
|
|
|
FakePolicy,
|
|
|
|
FakeRoot,
|
|
|
|
OrganizationsBackend,
|
|
|
|
)
|
|
|
|
|
2018-07-14 18:35:37 +00:00
|
|
|
import boto3
|
2019-05-25 09:20:19 +00:00
|
|
|
import json
|
|
|
|
import six
|
2019-11-17 13:52:57 +00:00
|
|
|
import sure # noqa
|
2018-07-20 20:54:53 +00:00
|
|
|
from botocore.exceptions import ClientError
|
2020-10-06 05:54:49 +00:00
|
|
|
import pytest
|
2018-07-14 18:35:37 +00:00
|
|
|
|
|
|
|
from moto import mock_organizations
|
2020-07-31 15:32:57 +00:00
|
|
|
from moto.core import ACCOUNT_ID
|
2018-07-20 20:54:53 +00:00
|
|
|
from moto.organizations import utils
|
2018-07-19 18:50:24 +00:00
|
|
|
from .organizations_test_utils import (
|
|
|
|
validate_organization,
|
|
|
|
validate_roots,
|
|
|
|
validate_organizational_unit,
|
|
|
|
validate_account,
|
|
|
|
validate_create_account_status,
|
2019-05-25 09:20:19 +00:00
|
|
|
validate_service_control_policy,
|
|
|
|
validate_policy_summary,
|
2018-07-14 18:35:37 +00:00
|
|
|
)
|
2018-07-14 20:23:15 +00:00
|
|
|
|
2018-07-14 18:35:37 +00:00
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_create_organization():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
response = client.create_organization(FeatureSet="ALL")
|
2018-07-14 18:35:37 +00:00
|
|
|
validate_organization(response)
|
2019-10-31 15:44:26 +00:00
|
|
|
response["Organization"]["FeatureSet"].should.equal("ALL")
|
2018-07-14 18:35:37 +00:00
|
|
|
|
2019-08-06 22:44:49 +00:00
|
|
|
response = client.list_accounts()
|
2019-10-31 15:44:26 +00:00
|
|
|
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)
|
2019-08-06 22:44:49 +00:00
|
|
|
|
2019-10-31 15:44:26 +00:00
|
|
|
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)
|
2019-08-06 22:44:49 +00:00
|
|
|
|
|
|
|
response = client.list_targets_for_policy(PolicyId=utils.DEFAULT_POLICY_ID)
|
2019-10-31 15:44:26 +00:00
|
|
|
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")
|
2019-08-06 22:44:49 +00:00
|
|
|
|
2018-07-14 20:23:15 +00:00
|
|
|
|
2018-07-14 18:35:37 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_describe_organization():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
2018-07-14 18:35:37 +00:00
|
|
|
response = client.describe_organization()
|
|
|
|
validate_organization(response)
|
|
|
|
|
|
|
|
|
2018-10-08 22:27:19 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_describe_organization_exception():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2018-10-08 22:27:19 +00:00
|
|
|
response = client.describe_organization()
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("DescribeOrganization")
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("AWSOrganizationsNotInUseException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"Your account is not a member of an organization."
|
|
|
|
)
|
2018-10-08 22:27:19 +00:00
|
|
|
|
|
|
|
|
2018-07-15 18:49:26 +00:00
|
|
|
# Organizational Units
|
|
|
|
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2018-07-15 17:31:16 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_list_roots():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
2018-07-15 17:31:16 +00:00
|
|
|
response = client.list_roots()
|
2018-07-19 18:50:24 +00:00
|
|
|
validate_roots(org, response)
|
2018-07-15 17:31:16 +00:00
|
|
|
|
|
|
|
|
2018-07-15 18:49:26 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_create_organizational_unit():
|
2019-10-31 15:44:26 +00:00
|
|
|
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_name = "ou01"
|
|
|
|
response = client.create_organizational_unit(ParentId=root_id, Name=ou_name)
|
2018-07-15 20:58:27 +00:00
|
|
|
validate_organizational_unit(org, response)
|
2019-10-31 15:44:26 +00:00
|
|
|
response["OrganizationalUnit"]["Name"].should.equal(ou_name)
|
2018-07-15 18:49:26 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_describe_organizational_unit():
|
2019-10-31 15:44:26 +00:00
|
|
|
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"]
|
2018-07-15 20:58:27 +00:00
|
|
|
response = client.describe_organizational_unit(OrganizationalUnitId=ou_id)
|
|
|
|
validate_organizational_unit(org, response)
|
|
|
|
|
|
|
|
|
2018-07-20 20:54:53 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_describe_organizational_unit_exception():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2018-07-20 20:54:53 +00:00
|
|
|
response = client.describe_organizational_unit(
|
|
|
|
OrganizationalUnitId=utils.make_random_root_id()
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("DescribeOrganizationalUnit")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain(
|
|
|
|
"OrganizationalUnitNotFoundException"
|
|
|
|
)
|
2018-07-20 20:54:53 +00:00
|
|
|
|
|
|
|
|
2018-07-15 20:58:27 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_list_organizational_units_for_parent():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
client.create_organizational_unit(ParentId=root_id, Name="ou01")
|
|
|
|
client.create_organizational_unit(ParentId=root_id, Name="ou02")
|
|
|
|
client.create_organizational_unit(ParentId=root_id, Name="ou03")
|
2018-07-15 20:58:27 +00:00
|
|
|
response = client.list_organizational_units_for_parent(ParentId=root_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
response.should.have.key("OrganizationalUnits").should.be.a(list)
|
|
|
|
for ou in response["OrganizationalUnits"]:
|
2018-07-15 20:58:27 +00:00
|
|
|
validate_organizational_unit(org, dict(OrganizationalUnit=ou))
|
|
|
|
|
|
|
|
|
2018-07-20 20:54:53 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_list_organizational_units_for_parent_exception():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2018-07-20 20:54:53 +00:00
|
|
|
response = client.list_organizational_units_for_parent(
|
|
|
|
ParentId=utils.make_random_root_id()
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("ListOrganizationalUnitsForParent")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain("ParentNotFoundException")
|
2018-07-20 20:54:53 +00:00
|
|
|
|
|
|
|
|
2018-07-15 18:49:26 +00:00
|
|
|
# Accounts
|
2019-10-31 15:44:26 +00:00
|
|
|
mockname = "mock-account"
|
|
|
|
mockdomain = "moto-example.org"
|
|
|
|
mockemail = "@".join([mockname, mockdomain])
|
2018-07-14 18:35:37 +00:00
|
|
|
|
2018-07-14 20:23:15 +00:00
|
|
|
|
2018-07-14 18:35:37 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_create_account():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
create_status = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]
|
2018-07-14 18:35:37 +00:00
|
|
|
validate_create_account_status(create_status)
|
2019-10-31 15:44:26 +00:00
|
|
|
create_status["AccountName"].should.equal(mockname)
|
2018-07-14 18:35:37 +00:00
|
|
|
|
2018-07-14 20:23:15 +00:00
|
|
|
|
2019-11-06 09:43:21 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_describe_create_account_status():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
request_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["Id"]
|
|
|
|
response = client.describe_create_account_status(CreateAccountRequestId=request_id)
|
|
|
|
validate_create_account_status(response["CreateAccountStatus"])
|
|
|
|
|
|
|
|
|
2018-07-14 18:35:37 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_describe_account():
|
2019-10-31 15:44:26 +00:00
|
|
|
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"]
|
2018-07-14 18:35:37 +00:00
|
|
|
response = client.describe_account(AccountId=account_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
validate_account(org, response["Account"])
|
|
|
|
response["Account"]["Name"].should.equal(mockname)
|
|
|
|
response["Account"]["Email"].should.equal(mockemail)
|
2018-07-14 18:35:37 +00:00
|
|
|
|
2018-07-14 20:23:15 +00:00
|
|
|
|
2018-07-20 20:54:53 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_describe_account_exception():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2018-07-20 20:54:53 +00:00
|
|
|
response = client.describe_account(AccountId=utils.make_random_account_id())
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("DescribeAccount")
|
2020-07-31 15:32:57 +00:00
|
|
|
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."
|
|
|
|
)
|
2018-07-20 20:54:53 +00:00
|
|
|
|
|
|
|
|
2018-07-14 18:35:37 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_list_accounts():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
2018-07-14 18:35:37 +00:00
|
|
|
for i in range(5):
|
|
|
|
name = mockname + str(i)
|
2019-10-31 15:44:26 +00:00
|
|
|
email = name + "@" + mockdomain
|
2018-07-14 18:35:37 +00:00
|
|
|
client.create_account(AccountName=name, Email=email)
|
|
|
|
response = client.list_accounts()
|
2019-10-31 15:44:26 +00:00
|
|
|
response.should.have.key("Accounts")
|
|
|
|
accounts = response["Accounts"]
|
2019-08-06 22:44:49 +00:00
|
|
|
len(accounts).should.equal(6)
|
2018-07-14 18:35:37 +00:00
|
|
|
for account in accounts:
|
|
|
|
validate_account(org, account)
|
2019-10-31 15:44:26 +00:00
|
|
|
accounts[4]["Name"].should.equal(mockname + "3")
|
|
|
|
accounts[3]["Email"].should.equal(mockname + "2" + "@" + mockdomain)
|
2018-07-15 22:25:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_accounts_for_parent():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
2018-07-15 22:25:34 +00:00
|
|
|
response = client.list_accounts_for_parent(ParentId=root_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
account_id.should.be.within([account["Id"] for account in response["Accounts"]])
|
2018-07-15 22:25:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_move_account():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
ou01 = client.create_organizational_unit(ParentId=root_id, Name="ou01")
|
|
|
|
ou01_id = ou01["OrganizationalUnit"]["Id"]
|
2018-07-15 22:25:34 +00:00
|
|
|
client.move_account(
|
2019-10-31 15:44:26 +00:00
|
|
|
AccountId=account_id, SourceParentId=root_id, DestinationParentId=ou01_id
|
2018-07-15 22:25:34 +00:00
|
|
|
)
|
|
|
|
response = client.list_accounts_for_parent(ParentId=ou01_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
account_id.should.be.within([account["Id"] for account in response["Accounts"]])
|
2018-07-16 03:39:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_parents_for_ou():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
ou01 = client.create_organizational_unit(ParentId=root_id, Name="ou01")
|
|
|
|
ou01_id = ou01["OrganizationalUnit"]["Id"]
|
2018-07-16 03:39:13 +00:00
|
|
|
response01 = client.list_parents(ChildId=ou01_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
response01.should.have.key("Parents").should.be.a(list)
|
|
|
|
response01["Parents"][0].should.have.key("Id").should.equal(root_id)
|
|
|
|
response01["Parents"][0].should.have.key("Type").should.equal("ROOT")
|
|
|
|
ou02 = client.create_organizational_unit(ParentId=ou01_id, Name="ou02")
|
|
|
|
ou02_id = ou02["OrganizationalUnit"]["Id"]
|
2018-07-16 03:39:13 +00:00
|
|
|
response02 = client.list_parents(ChildId=ou02_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
response02.should.have.key("Parents").should.be.a(list)
|
|
|
|
response02["Parents"][0].should.have.key("Id").should.equal(ou01_id)
|
|
|
|
response02["Parents"][0].should.have.key("Type").should.equal("ORGANIZATIONAL_UNIT")
|
2018-07-16 03:39:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_parents_for_accounts():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
ou01 = client.create_organizational_unit(ParentId=root_id, Name="ou01")
|
|
|
|
ou01_id = ou01["OrganizationalUnit"]["Id"]
|
2018-07-16 03:39:13 +00:00
|
|
|
account01_id = client.create_account(
|
2019-10-31 15:44:26 +00:00
|
|
|
AccountName="account01", Email="account01@moto-example.org"
|
|
|
|
)["CreateAccountStatus"]["AccountId"]
|
2018-07-16 03:39:13 +00:00
|
|
|
account02_id = client.create_account(
|
2019-10-31 15:44:26 +00:00
|
|
|
AccountName="account02", Email="account02@moto-example.org"
|
|
|
|
)["CreateAccountStatus"]["AccountId"]
|
2018-07-16 03:39:13 +00:00
|
|
|
client.move_account(
|
2019-10-31 15:44:26 +00:00
|
|
|
AccountId=account02_id, SourceParentId=root_id, DestinationParentId=ou01_id
|
2018-07-16 03:39:13 +00:00
|
|
|
)
|
|
|
|
response01 = client.list_parents(ChildId=account01_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
response01.should.have.key("Parents").should.be.a(list)
|
|
|
|
response01["Parents"][0].should.have.key("Id").should.equal(root_id)
|
|
|
|
response01["Parents"][0].should.have.key("Type").should.equal("ROOT")
|
2018-07-16 03:39:13 +00:00
|
|
|
response02 = client.list_parents(ChildId=account02_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
response02.should.have.key("Parents").should.be.a(list)
|
|
|
|
response02["Parents"][0].should.have.key("Id").should.equal(ou01_id)
|
|
|
|
response02["Parents"][0].should.have.key("Type").should.equal("ORGANIZATIONAL_UNIT")
|
2018-07-16 05:19:42 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
2018-07-20 20:54:53 +00:00
|
|
|
def test_list_children():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
ou01 = client.create_organizational_unit(ParentId=root_id, Name="ou01")
|
|
|
|
ou01_id = ou01["OrganizationalUnit"]["Id"]
|
|
|
|
ou02 = client.create_organizational_unit(ParentId=ou01_id, Name="ou02")
|
|
|
|
ou02_id = ou02["OrganizationalUnit"]["Id"]
|
2018-07-16 05:19:42 +00:00
|
|
|
account01_id = client.create_account(
|
2019-10-31 15:44:26 +00:00
|
|
|
AccountName="account01", Email="account01@moto-example.org"
|
|
|
|
)["CreateAccountStatus"]["AccountId"]
|
2018-07-16 05:19:42 +00:00
|
|
|
account02_id = client.create_account(
|
2019-10-31 15:44:26 +00:00
|
|
|
AccountName="account02", Email="account02@moto-example.org"
|
|
|
|
)["CreateAccountStatus"]["AccountId"]
|
2018-07-16 05:19:42 +00:00
|
|
|
client.move_account(
|
2019-10-31 15:44:26 +00:00
|
|
|
AccountId=account02_id, SourceParentId=root_id, DestinationParentId=ou01_id
|
2018-07-16 05:19:42 +00:00
|
|
|
)
|
2019-10-31 15:44:26 +00:00
|
|
|
response01 = client.list_children(ParentId=root_id, ChildType="ACCOUNT")
|
|
|
|
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(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)
|
|
|
|
response03["Children"][0]["Type"].should.equal("ACCOUNT")
|
|
|
|
response04["Children"][0]["Id"].should.equal(ou02_id)
|
|
|
|
response04["Children"][0]["Type"].should.equal("ORGANIZATIONAL_UNIT")
|
2018-07-20 20:54:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_children_exception():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2018-07-20 20:54:53 +00:00
|
|
|
response = client.list_children(
|
2019-10-31 15:44:26 +00:00
|
|
|
ParentId=utils.make_random_root_id(), ChildType="ACCOUNT"
|
2018-07-20 20:54:53 +00:00
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("ListChildren")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain("ParentNotFoundException")
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-10-31 15:44:26 +00:00
|
|
|
response = client.list_children(ParentId=root_id, ChildType="BLEE")
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("ListChildren")
|
2020-07-31 15:32:57 +00:00
|
|
|
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.")
|
2019-05-25 09:20:19 +00:00
|
|
|
|
|
|
|
|
2021-02-15 11:39:23 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_list_create_account_status():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
response = client.list_create_account_status()
|
|
|
|
createAccountStatuses = response["CreateAccountStatuses"]
|
|
|
|
createAccountStatuses.should.have.length_of(1)
|
|
|
|
validate_create_account_status(createAccountStatuses[0])
|
|
|
|
|
|
|
|
request_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["Id"]
|
|
|
|
response = client.list_create_account_status()
|
|
|
|
createAccountStatuses = response["CreateAccountStatuses"]
|
|
|
|
createAccountStatuses.should.have.length_of(2)
|
|
|
|
for createAccountStatus in createAccountStatuses:
|
|
|
|
validate_create_account_status(createAccountStatus)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_create_account_status_succeeded():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
requiredStates = ["SUCCEEDED"]
|
|
|
|
response = client.list_create_account_status(States=requiredStates)
|
|
|
|
createAccountStatuses = response["CreateAccountStatuses"]
|
|
|
|
createAccountStatuses.should.have.length_of(1)
|
|
|
|
validate_create_account_status(createAccountStatuses[0])
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_create_account_status_in_progress():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
requiredStates = ["IN_PROGRESS"]
|
|
|
|
response = client.list_create_account_status(States=requiredStates)
|
|
|
|
createAccountStatuses = response["CreateAccountStatuses"]
|
|
|
|
createAccountStatuses.should.have.length_of(0)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_get_paginated_list_create_account_status():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
for i in range(5):
|
|
|
|
request_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["Id"]
|
|
|
|
response = client.list_create_account_status(MaxResults=2)
|
|
|
|
createAccountStatuses = response["CreateAccountStatuses"]
|
|
|
|
createAccountStatuses.should.have.length_of(2)
|
|
|
|
for createAccountStatus in createAccountStatuses:
|
|
|
|
validate_create_account_status(createAccountStatus)
|
|
|
|
next_token = response["NextToken"]
|
|
|
|
next_token.should_not.be.none
|
|
|
|
response2 = client.list_create_account_status(NextToken=next_token)
|
|
|
|
createAccountStatuses.extend(response2["CreateAccountStatuses"])
|
|
|
|
createAccountStatuses.should.have.length_of(6)
|
|
|
|
assert "NextToken" not in response2.keys()
|
|
|
|
for createAccountStatus in createAccountStatuses:
|
|
|
|
validate_create_account_status(createAccountStatus)
|
|
|
|
|
|
|
|
|
2019-05-25 09:20:19 +00:00
|
|
|
# Service Control Policies
|
|
|
|
policy_doc01 = dict(
|
2019-10-31 15:44:26 +00:00
|
|
|
Version="2012-10-17",
|
|
|
|
Statement=[
|
|
|
|
dict(Sid="MockPolicyStatement", Effect="Allow", Action="s3:*", Resource="*")
|
|
|
|
],
|
2019-05-25 09:20:19 +00:00
|
|
|
)
|
|
|
|
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2019-05-25 09:20:19 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_create_policy():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
2019-05-25 09:20:19 +00:00
|
|
|
policy = client.create_policy(
|
|
|
|
Content=json.dumps(policy_doc01),
|
2019-10-31 15:44:26 +00:00
|
|
|
Description="A dummy service control policy",
|
|
|
|
Name="MockServiceControlPolicy",
|
|
|
|
Type="SERVICE_CONTROL_POLICY",
|
|
|
|
)["Policy"]
|
2019-05-25 09:20:19 +00:00
|
|
|
validate_service_control_policy(org, policy)
|
2019-10-31 15:44:26 +00:00
|
|
|
policy["PolicySummary"]["Name"].should.equal("MockServiceControlPolicy")
|
|
|
|
policy["PolicySummary"]["Description"].should.equal(
|
|
|
|
"A dummy service control policy"
|
|
|
|
)
|
|
|
|
policy["Content"].should.equal(json.dumps(policy_doc01))
|
2019-05-25 09:20:19 +00:00
|
|
|
|
|
|
|
|
2020-08-02 09:56:19 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_create_policy_errors():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
|
|
|
# invalid policy type
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-08-02 09:56:19 +00:00
|
|
|
client.create_policy(
|
|
|
|
Content=json.dumps(policy_doc01),
|
|
|
|
Description="moto",
|
|
|
|
Name="moto",
|
|
|
|
Type="MOTO",
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-08-02 09:56:19 +00:00
|
|
|
ex.operation_name.should.equal("CreatePolicy")
|
|
|
|
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.")
|
|
|
|
|
|
|
|
|
2019-05-25 09:20:19 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_describe_policy():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
2019-05-25 09:20:19 +00:00
|
|
|
policy_id = client.create_policy(
|
|
|
|
Content=json.dumps(policy_doc01),
|
2019-10-31 15:44:26 +00:00
|
|
|
Description="A dummy service control policy",
|
|
|
|
Name="MockServiceControlPolicy",
|
|
|
|
Type="SERVICE_CONTROL_POLICY",
|
|
|
|
)["Policy"]["PolicySummary"]["Id"]
|
|
|
|
policy = client.describe_policy(PolicyId=policy_id)["Policy"]
|
2019-05-25 09:20:19 +00:00
|
|
|
validate_service_control_policy(org, policy)
|
2019-10-31 15:44:26 +00:00
|
|
|
policy["PolicySummary"]["Name"].should.equal("MockServiceControlPolicy")
|
|
|
|
policy["PolicySummary"]["Description"].should.equal(
|
|
|
|
"A dummy service control policy"
|
|
|
|
)
|
|
|
|
policy["Content"].should.equal(json.dumps(policy_doc01))
|
2019-05-25 09:20:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_describe_policy_exception():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
policy_id = "p-47fhe9s3"
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-05-25 09:20:19 +00:00
|
|
|
response = client.describe_policy(PolicyId=policy_id)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("DescribePolicy")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain("PolicyNotFoundException")
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-10-31 15:44:26 +00:00
|
|
|
response = client.describe_policy(PolicyId="meaninglessstring")
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("DescribePolicy")
|
2020-07-31 15:32:57 +00:00
|
|
|
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.")
|
2019-05-25 09:20:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_attach_policy():
|
2019-10-31 15:44:26 +00:00
|
|
|
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"]
|
2020-07-27 11:36:31 +00:00
|
|
|
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"]
|
|
|
|
response = client.attach_policy(PolicyId=policy_id, TargetId=root_id)
|
|
|
|
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
|
|
|
response = client.attach_policy(PolicyId=policy_id, TargetId=ou_id)
|
|
|
|
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
|
|
|
response = client.attach_policy(PolicyId=policy_id, TargetId=account_id)
|
|
|
|
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
2020-07-27 11:32:11 +00:00
|
|
|
|
|
|
|
|
2020-09-25 15:55:29 +00:00
|
|
|
@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)
|
2020-10-06 06:04:09 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-09-25 15:55:29 +00:00
|
|
|
response = client.detach_policy(PolicyId=policy_id, TargetId="r-xy85")
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-09-25 15:55:29 +00:00
|
|
|
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)
|
2020-10-06 06:04:09 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-09-25 15:55:29 +00:00
|
|
|
response = client.detach_policy(
|
|
|
|
PolicyId=policy_id, TargetId="ou-zx86-z3x4yr2t7"
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-09-25 15:55:29 +00:00
|
|
|
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)
|
2020-10-06 06:04:09 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-09-25 15:55:29 +00:00
|
|
|
response = client.detach_policy(PolicyId=policy_id, TargetId="111619863336")
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-09-25 15:55:29 +00:00
|
|
|
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)
|
2020-10-06 06:04:09 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-09-25 15:55:29 +00:00
|
|
|
response = client.detach_policy(PolicyId=policy_id, TargetId="invalidtargetid")
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-09-25 15:55:29 +00:00
|
|
|
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.")
|
|
|
|
|
|
|
|
|
2020-07-27 11:32:11 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_delete_policy():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
base_policies = client.list_policies(Filter="SERVICE_CONTROL_POLICY")["Policies"]
|
|
|
|
base_policies.should.have.length_of(1)
|
2019-05-25 09:20:19 +00:00
|
|
|
policy_id = client.create_policy(
|
|
|
|
Content=json.dumps(policy_doc01),
|
2019-10-31 15:44:26 +00:00
|
|
|
Description="A dummy service control policy",
|
|
|
|
Name="MockServiceControlPolicy",
|
|
|
|
Type="SERVICE_CONTROL_POLICY",
|
|
|
|
)["Policy"]["PolicySummary"]["Id"]
|
2020-07-27 11:32:11 +00:00
|
|
|
new_policies = client.list_policies(Filter="SERVICE_CONTROL_POLICY")["Policies"]
|
|
|
|
new_policies.should.have.length_of(2)
|
|
|
|
response = client.delete_policy(PolicyId=policy_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
response["ResponseMetadata"]["HTTPStatusCode"].should.equal(200)
|
2020-07-27 11:32:11 +00:00
|
|
|
new_policies = client.list_policies(Filter="SERVICE_CONTROL_POLICY")["Policies"]
|
|
|
|
new_policies.should.equal(base_policies)
|
|
|
|
new_policies.should.have.length_of(1)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_delete_policy_exception():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
2020-08-02 09:56:19 +00:00
|
|
|
non_existent_policy_id = utils.make_random_policy_id()
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-27 11:32:11 +00:00
|
|
|
response = client.delete_policy(PolicyId=non_existent_policy_id)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-27 11:32:11 +00:00
|
|
|
ex.operation_name.should.equal("DeletePolicy")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain("PolicyNotFoundException")
|
|
|
|
|
|
|
|
# Attempt to delete an attached policy
|
|
|
|
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"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
client.attach_policy(PolicyId=policy_id, TargetId=root_id)
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-27 11:32:11 +00:00
|
|
|
response = client.delete_policy(PolicyId=policy_id)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-27 11:32:11 +00:00
|
|
|
ex.operation_name.should.equal("DeletePolicy")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain("PolicyInUseException")
|
2019-05-25 09:20:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_attach_policy_exception():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = "r-dj873"
|
|
|
|
ou_id = "ou-gi99-i7r8eh2i2"
|
|
|
|
account_id = "126644886543"
|
2019-05-25 09:20:19 +00:00
|
|
|
policy_id = client.create_policy(
|
|
|
|
Content=json.dumps(policy_doc01),
|
2019-10-31 15:44:26 +00:00
|
|
|
Description="A dummy service control policy",
|
|
|
|
Name="MockServiceControlPolicy",
|
|
|
|
Type="SERVICE_CONTROL_POLICY",
|
|
|
|
)["Policy"]["PolicySummary"]["Id"]
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-05-25 09:20:19 +00:00
|
|
|
response = client.attach_policy(PolicyId=policy_id, TargetId=root_id)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("AttachPolicy")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain(
|
|
|
|
"OrganizationalUnitNotFoundException"
|
|
|
|
)
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-05-25 09:20:19 +00:00
|
|
|
response = client.attach_policy(PolicyId=policy_id, TargetId=ou_id)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("AttachPolicy")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain(
|
|
|
|
"OrganizationalUnitNotFoundException"
|
|
|
|
)
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-05-25 09:20:19 +00:00
|
|
|
response = client.attach_policy(PolicyId=policy_id, TargetId=account_id)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("AttachPolicy")
|
2020-07-31 15:32:57 +00:00
|
|
|
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."
|
|
|
|
)
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-10-31 15:44:26 +00:00
|
|
|
response = client.attach_policy(
|
|
|
|
PolicyId=policy_id, TargetId="meaninglessstring"
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("AttachPolicy")
|
2020-07-31 15:32:57 +00:00
|
|
|
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.")
|
2019-05-25 09:20:19 +00:00
|
|
|
|
|
|
|
|
2020-07-27 11:32:11 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_update_policy():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
|
|
|
|
policy_dict = dict(
|
|
|
|
Content=json.dumps(policy_doc01),
|
|
|
|
Description="A dummy service control policy",
|
|
|
|
Name="MockServiceControlPolicy",
|
|
|
|
Type="SERVICE_CONTROL_POLICY",
|
|
|
|
)
|
|
|
|
policy_id = client.create_policy(**policy_dict)["Policy"]["PolicySummary"]["Id"]
|
|
|
|
|
|
|
|
for key in ("Description", "Name"):
|
|
|
|
response = client.update_policy(**{"PolicyId": policy_id, key: "foobar"})
|
|
|
|
policy = client.describe_policy(PolicyId=policy_id)
|
|
|
|
policy["Policy"]["PolicySummary"][key].should.equal("foobar")
|
|
|
|
validate_service_control_policy(org, response["Policy"])
|
|
|
|
|
|
|
|
response = client.update_policy(PolicyId=policy_id, Content="foobar")
|
|
|
|
policy = client.describe_policy(PolicyId=policy_id)
|
|
|
|
policy["Policy"]["Content"].should.equal("foobar")
|
|
|
|
validate_service_control_policy(org, response["Policy"])
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_update_policy_exception():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
2020-08-02 09:56:19 +00:00
|
|
|
non_existent_policy_id = utils.make_random_policy_id()
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-27 11:32:11 +00:00
|
|
|
response = client.update_policy(PolicyId=non_existent_policy_id)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-27 11:32:11 +00:00
|
|
|
ex.operation_name.should.equal("UpdatePolicy")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain("PolicyNotFoundException")
|
|
|
|
|
|
|
|
|
2019-05-25 09:20:19 +00:00
|
|
|
@mock_organizations
|
|
|
|
def test_list_polices():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
for i in range(0, 4):
|
2019-05-25 09:20:19 +00:00
|
|
|
client.create_policy(
|
|
|
|
Content=json.dumps(policy_doc01),
|
2019-10-31 15:44:26 +00:00
|
|
|
Description="A dummy service control policy",
|
|
|
|
Name="MockServiceControlPolicy" + str(i),
|
|
|
|
Type="SERVICE_CONTROL_POLICY",
|
2019-05-25 09:20:19 +00:00
|
|
|
)
|
2019-10-31 15:44:26 +00:00
|
|
|
response = client.list_policies(Filter="SERVICE_CONTROL_POLICY")
|
|
|
|
for policy in response["Policies"]:
|
2019-05-25 09:20:19 +00:00
|
|
|
validate_policy_summary(org, policy)
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2019-05-25 09:20:19 +00:00
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_policies_for_target():
|
2019-10-31 15:44:26 +00:00
|
|
|
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"]
|
2019-05-25 09:20:19 +00:00
|
|
|
policy_id = client.create_policy(
|
|
|
|
Content=json.dumps(policy_doc01),
|
2019-10-31 15:44:26 +00:00
|
|
|
Description="A dummy service control policy",
|
|
|
|
Name="MockServiceControlPolicy",
|
|
|
|
Type="SERVICE_CONTROL_POLICY",
|
|
|
|
)["Policy"]["PolicySummary"]["Id"]
|
2019-05-25 09:20:19 +00:00
|
|
|
client.attach_policy(PolicyId=policy_id, TargetId=ou_id)
|
|
|
|
response = client.list_policies_for_target(
|
2019-10-31 15:44:26 +00:00
|
|
|
TargetId=ou_id, Filter="SERVICE_CONTROL_POLICY"
|
2019-05-25 09:20:19 +00:00
|
|
|
)
|
2019-10-31 15:44:26 +00:00
|
|
|
for policy in response["Policies"]:
|
2019-05-25 09:20:19 +00:00
|
|
|
validate_policy_summary(org, policy)
|
|
|
|
client.attach_policy(PolicyId=policy_id, TargetId=account_id)
|
|
|
|
response = client.list_policies_for_target(
|
2019-10-31 15:44:26 +00:00
|
|
|
TargetId=account_id, Filter="SERVICE_CONTROL_POLICY"
|
2019-05-25 09:20:19 +00:00
|
|
|
)
|
2019-10-31 15:44:26 +00:00
|
|
|
for policy in response["Policies"]:
|
2019-05-25 09:20:19 +00:00
|
|
|
validate_policy_summary(org, policy)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_policies_for_target_exception():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")["Organization"]
|
2020-08-02 09:56:19 +00:00
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
2019-10-31 15:44:26 +00:00
|
|
|
ou_id = "ou-gi99-i7r8eh2i2"
|
|
|
|
account_id = "126644886543"
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-05-25 09:20:19 +00:00
|
|
|
response = client.list_policies_for_target(
|
2019-10-31 15:44:26 +00:00
|
|
|
TargetId=ou_id, Filter="SERVICE_CONTROL_POLICY"
|
2019-05-25 09:20:19 +00:00
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("ListPoliciesForTarget")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain(
|
|
|
|
"OrganizationalUnitNotFoundException"
|
|
|
|
)
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-05-25 09:20:19 +00:00
|
|
|
response = client.list_policies_for_target(
|
2019-10-31 15:44:26 +00:00
|
|
|
TargetId=account_id, Filter="SERVICE_CONTROL_POLICY"
|
2019-05-25 09:20:19 +00:00
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("ListPoliciesForTarget")
|
2020-07-31 15:32:57 +00:00
|
|
|
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."
|
|
|
|
)
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-05-25 09:20:19 +00:00
|
|
|
response = client.list_policies_for_target(
|
2019-10-31 15:44:26 +00:00
|
|
|
TargetId="meaninglessstring", Filter="SERVICE_CONTROL_POLICY"
|
2019-05-25 09:20:19 +00:00
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("ListPoliciesForTarget")
|
2020-07-31 15:32:57 +00:00
|
|
|
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.")
|
2019-10-31 15:44:26 +00:00
|
|
|
|
2020-08-02 09:56:19 +00:00
|
|
|
# not existing root
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-08-02 09:56:19 +00:00
|
|
|
client.list_policies_for_target(
|
|
|
|
TargetId="r-0000", Filter="SERVICE_CONTROL_POLICY"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-08-02 09:56:19 +00:00
|
|
|
ex.operation_name.should.equal("ListPoliciesForTarget")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("TargetNotFoundException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified a target that doesn't exist."
|
|
|
|
)
|
|
|
|
|
|
|
|
# invalid policy type
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-08-02 09:56:19 +00:00
|
|
|
client.list_policies_for_target(TargetId=root_id, Filter="MOTO")
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-08-02 09:56:19 +00:00
|
|
|
ex.operation_name.should.equal("ListPoliciesForTarget")
|
|
|
|
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.")
|
|
|
|
|
2019-05-25 09:20:19 +00:00
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_targets_for_policy():
|
2019-10-31 15:44:26 +00:00
|
|
|
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"]
|
2019-05-25 09:20:19 +00:00
|
|
|
policy_id = client.create_policy(
|
|
|
|
Content=json.dumps(policy_doc01),
|
2019-10-31 15:44:26 +00:00
|
|
|
Description="A dummy service control policy",
|
|
|
|
Name="MockServiceControlPolicy",
|
|
|
|
Type="SERVICE_CONTROL_POLICY",
|
|
|
|
)["Policy"]["PolicySummary"]["Id"]
|
2019-05-25 09:20:19 +00:00
|
|
|
client.attach_policy(PolicyId=policy_id, TargetId=root_id)
|
|
|
|
client.attach_policy(PolicyId=policy_id, TargetId=ou_id)
|
|
|
|
client.attach_policy(PolicyId=policy_id, TargetId=account_id)
|
|
|
|
response = client.list_targets_for_policy(PolicyId=policy_id)
|
2019-10-31 15:44:26 +00:00
|
|
|
for target in response["Targets"]:
|
2019-05-25 09:20:19 +00:00
|
|
|
target.should.be.a(dict)
|
2019-10-31 15:44:26 +00:00
|
|
|
target.should.have.key("Name").should.be.a(six.string_types)
|
|
|
|
target.should.have.key("Arn").should.be.a(six.string_types)
|
|
|
|
target.should.have.key("TargetId").should.be.a(six.string_types)
|
|
|
|
target.should.have.key("Type").should.be.within(
|
|
|
|
["ROOT", "ORGANIZATIONAL_UNIT", "ACCOUNT"]
|
2019-05-25 09:20:19 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_targets_for_policy_exception():
|
2019-10-31 15:44:26 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
policy_id = "p-47fhe9s3"
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-05-25 09:20:19 +00:00
|
|
|
response = client.list_targets_for_policy(PolicyId=policy_id)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("ListTargetsForPolicy")
|
|
|
|
ex.response["Error"]["Code"].should.equal("400")
|
|
|
|
ex.response["Error"]["Message"].should.contain("PolicyNotFoundException")
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-10-31 15:44:26 +00:00
|
|
|
response = client.list_targets_for_policy(PolicyId="meaninglessstring")
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-10-31 15:44:26 +00:00
|
|
|
ex.operation_name.should.equal("ListTargetsForPolicy")
|
2020-07-31 15:32:57 +00:00
|
|
|
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.")
|
2019-11-17 13:52:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
2021-06-05 14:12:17 +00:00
|
|
|
def test_tag_resource_account():
|
2019-11-17 13:52:57 +00:00
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
2021-06-05 14:12:17 +00:00
|
|
|
resource_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
2019-11-17 13:52:57 +00:00
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
|
2021-06-05 14:12:17 +00:00
|
|
|
client.tag_resource(ResourceId=resource_id, Tags=[{"Key": "key", "Value": "value"}])
|
2019-11-17 13:52:57 +00:00
|
|
|
|
2021-06-05 14:12:17 +00:00
|
|
|
response = client.list_tags_for_resource(ResourceId=resource_id)
|
2019-11-17 14:10:38 +00:00
|
|
|
response["Tags"].should.equal([{"Key": "key", "Value": "value"}])
|
|
|
|
|
|
|
|
# adding a tag with an existing key, will update the value
|
|
|
|
client.tag_resource(
|
2021-06-05 14:12:17 +00:00
|
|
|
ResourceId=resource_id, Tags=[{"Key": "key", "Value": "new-value"}]
|
2019-11-17 14:10:38 +00:00
|
|
|
)
|
|
|
|
|
2021-06-05 14:12:17 +00:00
|
|
|
response = client.list_tags_for_resource(ResourceId=resource_id)
|
2019-11-17 14:10:38 +00:00
|
|
|
response["Tags"].should.equal([{"Key": "key", "Value": "new-value"}])
|
|
|
|
|
2021-06-05 14:12:17 +00:00
|
|
|
client.untag_resource(ResourceId=resource_id, TagKeys=["key"])
|
|
|
|
|
|
|
|
response = client.list_tags_for_resource(ResourceId=resource_id)
|
|
|
|
response["Tags"].should.equal([])
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_tag_resource_organization_organization_root():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
|
|
|
resource_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
client.tag_resource(ResourceId=resource_id, Tags=[{"Key": "key", "Value": "value"}])
|
|
|
|
|
|
|
|
response = client.list_tags_for_resource(ResourceId=resource_id)
|
|
|
|
response["Tags"].should.equal([{"Key": "key", "Value": "value"}])
|
|
|
|
|
|
|
|
# adding a tag with an existing key, will update the value
|
|
|
|
client.tag_resource(
|
|
|
|
ResourceId=resource_id, Tags=[{"Key": "key", "Value": "new-value"}]
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.list_tags_for_resource(ResourceId=resource_id)
|
|
|
|
response["Tags"].should.equal([{"Key": "key", "Value": "new-value"}])
|
|
|
|
|
|
|
|
client.untag_resource(ResourceId=resource_id, TagKeys=["key"])
|
|
|
|
|
|
|
|
response = client.list_tags_for_resource(ResourceId=resource_id)
|
|
|
|
response["Tags"].should.equal([])
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_tag_resource_organization_organizational_unit():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
resource_id = client.create_organizational_unit(ParentId=root_id, Name="ou01")[
|
|
|
|
"OrganizationalUnit"
|
|
|
|
]["Id"]
|
|
|
|
|
|
|
|
client.tag_resource(ResourceId=resource_id, Tags=[{"Key": "key", "Value": "value"}])
|
|
|
|
|
|
|
|
response = client.list_tags_for_resource(ResourceId=resource_id)
|
|
|
|
response["Tags"].should.equal([{"Key": "key", "Value": "value"}])
|
|
|
|
|
|
|
|
# adding a tag with an existing key, will update the value
|
|
|
|
client.tag_resource(
|
|
|
|
ResourceId=resource_id, Tags=[{"Key": "key", "Value": "new-value"}]
|
|
|
|
)
|
|
|
|
|
|
|
|
response = client.list_tags_for_resource(ResourceId=resource_id)
|
|
|
|
response["Tags"].should.equal([{"Key": "key", "Value": "new-value"}])
|
|
|
|
|
|
|
|
client.untag_resource(ResourceId=resource_id, TagKeys=["key"])
|
|
|
|
|
|
|
|
response = client.list_tags_for_resource(ResourceId=resource_id)
|
|
|
|
response["Tags"].should.equal([])
|
|
|
|
|
2019-11-17 13:52:57 +00:00
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_tag_resource_errors():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2019-11-17 13:52:57 +00:00
|
|
|
client.tag_resource(
|
2021-06-05 14:12:17 +00:00
|
|
|
ResourceId="0A000000X000", Tags=[{"Key": "key", "Value": "value"},],
|
2019-11-17 13:52:57 +00:00
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-11-17 13:52:57 +00:00
|
|
|
ex.operation_name.should.equal("TagResource")
|
2019-11-21 21:03:25 +00:00
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("InvalidInputException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
2019-11-17 13:52:57 +00:00
|
|
|
"You provided a value that does not match the required pattern."
|
|
|
|
)
|
2021-06-05 14:12:17 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
|
|
|
client.tag_resource(
|
|
|
|
ResourceId="000000000000", Tags=[{"Key": "key", "Value": "value"}]
|
|
|
|
)
|
|
|
|
ex = e.value
|
|
|
|
ex.operation_name.should.equal("TagResource")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("TargetNotFoundException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified a target that doesn't exist."
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_for_tagging_existing_root():
|
|
|
|
org = FakeOrganization("ALL")
|
|
|
|
root = FakeRoot(org)
|
|
|
|
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
org_backend.ou.append(root)
|
|
|
|
response = org_backend._get_resource_for_tagging(root.id)
|
|
|
|
response.id.should.equal(root.id)
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_for_tagging_existing_non_root():
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
with pytest.raises(TargetNotFoundException) as e:
|
|
|
|
org_backend._get_resource_for_tagging("r-abcd")
|
|
|
|
ex = e.value
|
|
|
|
ex.code.should.equal(400)
|
|
|
|
ex.description.should.contain("TargetNotFoundException")
|
|
|
|
ex.message.should.equal("You specified a target that doesn't exist.")
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_for_tagging_existing_ou():
|
|
|
|
org = FakeOrganization("ALL")
|
|
|
|
ou = FakeOrganizationalUnit(org)
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
|
|
|
|
org_backend.ou.append(ou)
|
|
|
|
response = org_backend._get_resource_for_tagging(ou.id)
|
|
|
|
response.id.should.equal(ou.id)
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_for_tagging_non_existing_ou():
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
with pytest.raises(TargetNotFoundException) as e:
|
|
|
|
org_backend._get_resource_for_tagging("ou-9oyc-lv2q36ln")
|
|
|
|
ex = e.value
|
|
|
|
ex.code.should.equal(400)
|
|
|
|
ex.description.should.contain("TargetNotFoundException")
|
|
|
|
ex.message.should.equal("You specified a target that doesn't exist.")
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_for_tagging_existing_account():
|
|
|
|
org = FakeOrganization("ALL")
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
account = FakeAccount(org, AccountName="test", Email="test@test.test")
|
|
|
|
|
|
|
|
org_backend.accounts.append(account)
|
|
|
|
response = org_backend._get_resource_for_tagging(account.id)
|
|
|
|
response.id.should.equal(account.id)
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_for_tagging_non_existing_account():
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
with pytest.raises(TargetNotFoundException) as e:
|
|
|
|
org_backend._get_resource_for_tagging("100326223992")
|
|
|
|
ex = e.value
|
|
|
|
ex.code.should.equal(400)
|
|
|
|
ex.description.should.contain("TargetNotFoundException")
|
|
|
|
ex.message.should.equal("You specified a target that doesn't exist.")
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_for_tagging_existing_policy():
|
|
|
|
org = FakeOrganization("ALL")
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
policy = FakePolicy(org, Type="SERVICE_CONTROL_POLICY")
|
|
|
|
|
|
|
|
org_backend.policies.append(policy)
|
|
|
|
response = org_backend._get_resource_for_tagging(policy.id)
|
|
|
|
response.id.should.equal(policy.id)
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_for_tagging_non_existing_policy():
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
with pytest.raises(TargetNotFoundException) as e:
|
|
|
|
org_backend._get_resource_for_tagging("p-y1vas4da")
|
|
|
|
ex = e.value
|
|
|
|
ex.code.should.equal(400)
|
|
|
|
ex.description.should.contain("TargetNotFoundException")
|
|
|
|
ex.message.should.equal("You specified a target that doesn't exist.")
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_for_tagging_non_existing_policy():
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
with pytest.raises(TargetNotFoundException) as e:
|
|
|
|
org_backend._get_resource_for_tagging("p-y1vas4da")
|
|
|
|
ex = e.value
|
|
|
|
ex.code.should.equal(400)
|
|
|
|
ex.description.should.contain("TargetNotFoundException")
|
|
|
|
ex.message.should.equal("You specified a target that doesn't exist.")
|
|
|
|
|
|
|
|
|
|
|
|
def test__get_resource_to_tag_incorrect_resource():
|
|
|
|
org_backend = OrganizationsBackend()
|
|
|
|
with pytest.raises(InvalidInputException) as e:
|
|
|
|
org_backend._get_resource_for_tagging("10032622399200")
|
|
|
|
ex = e.value
|
|
|
|
ex.code.should.equal(400)
|
|
|
|
ex.description.should.contain("InvalidInputException")
|
|
|
|
ex.message.should.equal(
|
|
|
|
"You provided a value that does not match the required pattern."
|
|
|
|
)
|
2019-11-17 14:10:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_tags_for_resource():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
client.tag_resource(ResourceId=account_id, Tags=[{"Key": "key", "Value": "value"}])
|
|
|
|
|
|
|
|
response = client.list_tags_for_resource(ResourceId=account_id)
|
|
|
|
|
|
|
|
response["Tags"].should.equal([{"Key": "key", "Value": "value"}])
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_tags_for_resource_errors():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2021-06-05 14:12:17 +00:00
|
|
|
client.list_tags_for_resource(ResourceId="000x00000A00")
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-11-17 14:10:38 +00:00
|
|
|
ex.operation_name.should.equal("ListTagsForResource")
|
2019-11-21 21:03:25 +00:00
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("InvalidInputException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
2019-11-17 14:10:38 +00:00
|
|
|
"You provided a value that does not match the required pattern."
|
|
|
|
)
|
2021-06-05 14:12:17 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
|
|
|
client.list_tags_for_resource(ResourceId="000000000000")
|
|
|
|
ex = e.value
|
|
|
|
ex.operation_name.should.equal("ListTagsForResource")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("TargetNotFoundException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified a target that doesn't exist."
|
|
|
|
)
|
2019-11-17 14:28:38 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_untag_resource():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
client.tag_resource(ResourceId=account_id, Tags=[{"Key": "key", "Value": "value"}])
|
|
|
|
response = client.list_tags_for_resource(ResourceId=account_id)
|
|
|
|
response["Tags"].should.equal([{"Key": "key", "Value": "value"}])
|
|
|
|
|
|
|
|
# removing a non existing tag should not raise any error
|
|
|
|
client.untag_resource(ResourceId=account_id, TagKeys=["not-existing"])
|
|
|
|
response = client.list_tags_for_resource(ResourceId=account_id)
|
|
|
|
response["Tags"].should.equal([{"Key": "key", "Value": "value"}])
|
|
|
|
|
|
|
|
client.untag_resource(ResourceId=account_id, TagKeys=["key"])
|
|
|
|
response = client.list_tags_for_resource(ResourceId=account_id)
|
|
|
|
response["Tags"].should.have.length_of(0)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_untag_resource_errors():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2021-06-05 14:12:17 +00:00
|
|
|
client.untag_resource(ResourceId="0X00000000A0", TagKeys=["key"])
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2019-11-17 14:28:38 +00:00
|
|
|
ex.operation_name.should.equal("UntagResource")
|
2019-11-21 21:03:25 +00:00
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("InvalidInputException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
2019-11-17 14:28:38 +00:00
|
|
|
"You provided a value that does not match the required pattern."
|
|
|
|
)
|
2021-06-05 14:12:17 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
|
|
|
client.untag_resource(ResourceId="000000000000", TagKeys=["key"])
|
|
|
|
ex = e.value
|
|
|
|
ex.operation_name.should.equal("UntagResource")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("TargetNotFoundException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified a target that doesn't exist."
|
|
|
|
)
|
2020-02-06 10:49:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_update_organizational_unit():
|
|
|
|
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_name = "ou01"
|
|
|
|
response = client.create_organizational_unit(ParentId=root_id, Name=ou_name)
|
|
|
|
validate_organizational_unit(org, response)
|
|
|
|
response["OrganizationalUnit"]["Name"].should.equal(ou_name)
|
|
|
|
new_ou_name = "ou02"
|
|
|
|
response = client.update_organizational_unit(
|
|
|
|
OrganizationalUnitId=response["OrganizationalUnit"]["Id"], Name=new_ou_name
|
|
|
|
)
|
|
|
|
validate_organizational_unit(org, response)
|
|
|
|
response["OrganizationalUnit"]["Name"].should.equal(new_ou_name)
|
2020-02-06 11:38:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_update_organizational_unit_duplicate_error():
|
|
|
|
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_name = "ou01"
|
|
|
|
response = client.create_organizational_unit(ParentId=root_id, Name=ou_name)
|
|
|
|
validate_organizational_unit(org, response)
|
|
|
|
response["OrganizationalUnit"]["Name"].should.equal(ou_name)
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-02-06 11:38:37 +00:00
|
|
|
client.update_organizational_unit(
|
|
|
|
OrganizationalUnitId=response["OrganizationalUnit"]["Id"], Name=ou_name
|
|
|
|
)
|
2020-10-06 06:04:09 +00:00
|
|
|
exc = e.value
|
2020-02-06 11:38:37 +00:00
|
|
|
exc.operation_name.should.equal("UpdateOrganizationalUnit")
|
|
|
|
exc.response["Error"]["Code"].should.contain("DuplicateOrganizationalUnitException")
|
|
|
|
exc.response["Error"]["Message"].should.equal(
|
|
|
|
"An OU with the same name already exists."
|
|
|
|
)
|
2020-07-14 09:27:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_enable_aws_service_access():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
|
|
|
# when
|
|
|
|
client.enable_aws_service_access(ServicePrincipal="config.amazonaws.com")
|
|
|
|
|
|
|
|
# then
|
|
|
|
response = client.list_aws_service_access_for_organization()
|
|
|
|
response["EnabledServicePrincipals"].should.have.length_of(1)
|
|
|
|
service = response["EnabledServicePrincipals"][0]
|
|
|
|
service["ServicePrincipal"].should.equal("config.amazonaws.com")
|
|
|
|
date_enabled = service["DateEnabled"]
|
|
|
|
date_enabled["DateEnabled"].should.be.a(datetime)
|
|
|
|
|
|
|
|
# enabling the same service again should not result in any error or change
|
|
|
|
# when
|
|
|
|
client.enable_aws_service_access(ServicePrincipal="config.amazonaws.com")
|
|
|
|
|
|
|
|
# then
|
|
|
|
response = client.list_aws_service_access_for_organization()
|
|
|
|
response["EnabledServicePrincipals"].should.have.length_of(1)
|
|
|
|
service = response["EnabledServicePrincipals"][0]
|
|
|
|
service["ServicePrincipal"].should.equal("config.amazonaws.com")
|
|
|
|
service["DateEnabled"].should.equal(date_enabled)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_enable_aws_service_access():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-14 09:27:39 +00:00
|
|
|
client.enable_aws_service_access(ServicePrincipal="moto.amazonaws.com")
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-14 09:27:39 +00:00
|
|
|
ex.operation_name.should.equal("EnableAWSServiceAccess")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("InvalidInputException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified an unrecognized service principal."
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_enable_aws_service_access():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
client.enable_aws_service_access(ServicePrincipal="config.amazonaws.com")
|
|
|
|
client.enable_aws_service_access(ServicePrincipal="ram.amazonaws.com")
|
|
|
|
|
|
|
|
# when
|
|
|
|
response = client.list_aws_service_access_for_organization()
|
|
|
|
|
|
|
|
# then
|
|
|
|
response["EnabledServicePrincipals"].should.have.length_of(2)
|
|
|
|
services = sorted(
|
|
|
|
response["EnabledServicePrincipals"], key=lambda i: i["ServicePrincipal"]
|
|
|
|
)
|
|
|
|
services[0]["ServicePrincipal"].should.equal("config.amazonaws.com")
|
|
|
|
services[0]["DateEnabled"].should.be.a(datetime)
|
|
|
|
services[1]["ServicePrincipal"].should.equal("ram.amazonaws.com")
|
|
|
|
services[1]["DateEnabled"].should.be.a(datetime)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_disable_aws_service_access():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
client.enable_aws_service_access(ServicePrincipal="config.amazonaws.com")
|
|
|
|
|
|
|
|
# when
|
|
|
|
client.disable_aws_service_access(ServicePrincipal="config.amazonaws.com")
|
|
|
|
|
|
|
|
# then
|
|
|
|
response = client.list_aws_service_access_for_organization()
|
|
|
|
response["EnabledServicePrincipals"].should.have.length_of(0)
|
|
|
|
|
|
|
|
# disabling the same service again should not result in any error
|
|
|
|
# when
|
|
|
|
client.disable_aws_service_access(ServicePrincipal="config.amazonaws.com")
|
|
|
|
|
|
|
|
# then
|
|
|
|
response = client.list_aws_service_access_for_organization()
|
|
|
|
response["EnabledServicePrincipals"].should.have.length_of(0)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_disable_aws_service_access_errors():
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-14 09:27:39 +00:00
|
|
|
client.disable_aws_service_access(ServicePrincipal="moto.amazonaws.com")
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-14 09:27:39 +00:00
|
|
|
ex.operation_name.should.equal("DisableAWSServiceAccess")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("InvalidInputException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified an unrecognized service principal."
|
|
|
|
)
|
2020-07-31 15:32:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_register_delegated_administrator():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org_id = client.create_organization(FeatureSet="ALL")["Organization"]["Id"]
|
|
|
|
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
|
|
|
|
# when
|
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
|
|
|
response = client.list_delegated_administrators()
|
|
|
|
response["DelegatedAdministrators"].should.have.length_of(1)
|
|
|
|
admin = response["DelegatedAdministrators"][0]
|
|
|
|
admin["Id"].should.equal(account_id)
|
|
|
|
admin["Arn"].should.equal(
|
|
|
|
"arn:aws:organizations::{0}:account/{1}/{2}".format(
|
|
|
|
ACCOUNT_ID, org_id, account_id
|
|
|
|
)
|
|
|
|
)
|
|
|
|
admin["Email"].should.equal(mockemail)
|
|
|
|
admin["Name"].should.equal(mockname)
|
|
|
|
admin["Status"].should.equal("ACTIVE")
|
|
|
|
admin["JoinedMethod"].should.equal("CREATED")
|
|
|
|
admin["JoinedTimestamp"].should.be.a(datetime)
|
|
|
|
admin["DelegationEnabledDate"].should.be.a(datetime)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_register_delegated_administrator_errors():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# register master Account
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=ACCOUNT_ID, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("RegisterDelegatedAdministrator")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("ConstraintViolationException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You cannot register master account/yourself as delegated administrator for your organization."
|
|
|
|
)
|
|
|
|
|
|
|
|
# register not existing Account
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId="000000000000", ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("RegisterDelegatedAdministrator")
|
|
|
|
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."
|
|
|
|
)
|
|
|
|
|
|
|
|
# register not supported service
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="moto.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("RegisterDelegatedAdministrator")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("InvalidInputException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified an unrecognized service principal."
|
|
|
|
)
|
|
|
|
|
|
|
|
# register service again
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("RegisterDelegatedAdministrator")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("AccountAlreadyRegisteredException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"The provided account is already a delegated administrator for your organization."
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_delegated_administrators():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org_id = client.create_organization(FeatureSet="ALL")["Organization"]["Id"]
|
|
|
|
account_id_1 = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
account_id_2 = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id_1, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id_2, ServicePrincipal="guardduty.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# when
|
|
|
|
response = client.list_delegated_administrators()
|
|
|
|
|
|
|
|
# then
|
|
|
|
response["DelegatedAdministrators"].should.have.length_of(2)
|
|
|
|
sorted([admin["Id"] for admin in response["DelegatedAdministrators"]]).should.equal(
|
|
|
|
sorted([account_id_1, account_id_2])
|
|
|
|
)
|
|
|
|
|
|
|
|
# when
|
|
|
|
response = client.list_delegated_administrators(
|
|
|
|
ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
|
|
|
response["DelegatedAdministrators"].should.have.length_of(1)
|
|
|
|
admin = response["DelegatedAdministrators"][0]
|
|
|
|
admin["Id"].should.equal(account_id_1)
|
|
|
|
admin["Arn"].should.equal(
|
|
|
|
"arn:aws:organizations::{0}:account/{1}/{2}".format(
|
|
|
|
ACCOUNT_ID, org_id, account_id_1
|
|
|
|
)
|
|
|
|
)
|
|
|
|
admin["Email"].should.equal(mockemail)
|
|
|
|
admin["Name"].should.equal(mockname)
|
|
|
|
admin["Status"].should.equal("ACTIVE")
|
|
|
|
admin["JoinedMethod"].should.equal("CREATED")
|
|
|
|
admin["JoinedTimestamp"].should.be.a(datetime)
|
|
|
|
admin["DelegationEnabledDate"].should.be.a(datetime)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_delegated_administrators_erros():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
|
|
|
# list not supported service
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.list_delegated_administrators(ServicePrincipal="moto.amazonaws.com")
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("ListDelegatedAdministrators")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("InvalidInputException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified an unrecognized service principal."
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_delegated_services_for_account():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="guardduty.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# when
|
|
|
|
response = client.list_delegated_services_for_account(AccountId=account_id)
|
|
|
|
|
|
|
|
# then
|
|
|
|
response["DelegatedServices"].should.have.length_of(2)
|
|
|
|
sorted(
|
|
|
|
[service["ServicePrincipal"] for service in response["DelegatedServices"]]
|
|
|
|
).should.equal(["guardduty.amazonaws.com", "ssm.amazonaws.com"])
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_list_delegated_services_for_account_erros():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
|
|
|
|
# list services for not existing Account
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.list_delegated_services_for_account(AccountId="000000000000")
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("ListDelegatedServicesForAccount")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("AWSOrganizationsNotInUseException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"Your account is not a member of an organization."
|
|
|
|
)
|
|
|
|
|
|
|
|
# list services for not registered Account
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.list_delegated_services_for_account(AccountId=ACCOUNT_ID)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("ListDelegatedServicesForAccount")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("AccountNotRegisteredException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"The provided account is not a registered delegated administrator for your organization."
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_deregister_delegated_administrator():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# when
|
|
|
|
client.deregister_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
|
|
|
response = client.list_delegated_administrators()
|
|
|
|
response["DelegatedAdministrators"].should.have.length_of(0)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_deregister_delegated_administrator_erros():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
account_id = client.create_account(AccountName=mockname, Email=mockemail)[
|
|
|
|
"CreateAccountStatus"
|
|
|
|
]["AccountId"]
|
|
|
|
|
|
|
|
# deregister master Account
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.deregister_delegated_administrator(
|
|
|
|
AccountId=ACCOUNT_ID, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("DeregisterDelegatedAdministrator")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("ConstraintViolationException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You cannot register master account/yourself as delegated administrator for your organization."
|
|
|
|
)
|
|
|
|
|
|
|
|
# deregister not existing Account
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.deregister_delegated_administrator(
|
|
|
|
AccountId="000000000000", ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("DeregisterDelegatedAdministrator")
|
|
|
|
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."
|
|
|
|
)
|
|
|
|
|
|
|
|
# deregister not registered Account
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.deregister_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("DeregisterDelegatedAdministrator")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("AccountNotRegisteredException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"The provided account is not a registered delegated administrator for your organization."
|
|
|
|
)
|
|
|
|
|
|
|
|
# given
|
|
|
|
client.register_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="ssm.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# deregister not registered service
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-07-31 15:32:57 +00:00
|
|
|
client.deregister_delegated_administrator(
|
|
|
|
AccountId=account_id, ServicePrincipal="guardduty.amazonaws.com"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-07-31 15:32:57 +00:00
|
|
|
ex.operation_name.should.equal("DeregisterDelegatedAdministrator")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("InvalidInputException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified an unrecognized service principal."
|
|
|
|
)
|
2020-08-02 09:56:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_enable_policy_type():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
|
|
|
|
# when
|
|
|
|
response = client.enable_policy_type(
|
|
|
|
RootId=root_id, PolicyType="AISERVICES_OPT_OUT_POLICY"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
|
|
|
root = response["Root"]
|
|
|
|
root["Id"].should.equal(root_id)
|
|
|
|
root["Arn"].should.equal(
|
|
|
|
utils.ROOT_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], root_id)
|
|
|
|
)
|
|
|
|
root["Name"].should.equal("Root")
|
|
|
|
sorted(root["PolicyTypes"], key=lambda x: x["Type"]).should.equal(
|
|
|
|
[
|
|
|
|
{"Type": "AISERVICES_OPT_OUT_POLICY", "Status": "ENABLED"},
|
|
|
|
{"Type": "SERVICE_CONTROL_POLICY", "Status": "ENABLED"},
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_enable_policy_type_errors():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
|
|
|
|
# not existing root
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-08-02 09:56:19 +00:00
|
|
|
client.enable_policy_type(
|
|
|
|
RootId="r-0000", PolicyType="AISERVICES_OPT_OUT_POLICY"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-08-02 09:56:19 +00:00
|
|
|
ex.operation_name.should.equal("EnablePolicyType")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("RootNotFoundException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified a root that doesn't exist."
|
|
|
|
)
|
|
|
|
|
|
|
|
# enable policy again ('SERVICE_CONTROL_POLICY' is enabled by default)
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-08-02 09:56:19 +00:00
|
|
|
client.enable_policy_type(RootId=root_id, PolicyType="SERVICE_CONTROL_POLICY")
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-08-02 09:56:19 +00:00
|
|
|
ex.operation_name.should.equal("EnablePolicyType")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("PolicyTypeAlreadyEnabledException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"The specified policy type is already enabled."
|
|
|
|
)
|
|
|
|
|
|
|
|
# invalid policy type
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-08-02 09:56:19 +00:00
|
|
|
client.enable_policy_type(RootId=root_id, PolicyType="MOTO")
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-08-02 09:56:19 +00:00
|
|
|
ex.operation_name.should.equal("EnablePolicyType")
|
|
|
|
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_disable_policy_type():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
client.enable_policy_type(RootId=root_id, PolicyType="AISERVICES_OPT_OUT_POLICY")
|
|
|
|
|
|
|
|
# when
|
|
|
|
response = client.disable_policy_type(
|
|
|
|
RootId=root_id, PolicyType="AISERVICES_OPT_OUT_POLICY"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
|
|
|
root = response["Root"]
|
|
|
|
root["Id"].should.equal(root_id)
|
|
|
|
root["Arn"].should.equal(
|
|
|
|
utils.ROOT_ARN_FORMAT.format(org["MasterAccountId"], org["Id"], root_id)
|
|
|
|
)
|
|
|
|
root["Name"].should.equal("Root")
|
|
|
|
root["PolicyTypes"].should.equal(
|
|
|
|
[{"Type": "SERVICE_CONTROL_POLICY", "Status": "ENABLED"}]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@mock_organizations
|
|
|
|
def test_disable_policy_type_errors():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
client.create_organization(FeatureSet="ALL")
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
|
|
|
|
# not existing root
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-08-02 09:56:19 +00:00
|
|
|
client.disable_policy_type(
|
|
|
|
RootId="r-0000", PolicyType="AISERVICES_OPT_OUT_POLICY"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-08-02 09:56:19 +00:00
|
|
|
ex.operation_name.should.equal("DisablePolicyType")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("RootNotFoundException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"You specified a root that doesn't exist."
|
|
|
|
)
|
|
|
|
|
|
|
|
# disable not enabled policy
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-08-02 09:56:19 +00:00
|
|
|
client.disable_policy_type(
|
|
|
|
RootId=root_id, PolicyType="AISERVICES_OPT_OUT_POLICY"
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-08-02 09:56:19 +00:00
|
|
|
ex.operation_name.should.equal("DisablePolicyType")
|
|
|
|
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
|
|
|
ex.response["Error"]["Code"].should.contain("PolicyTypeNotEnabledException")
|
|
|
|
ex.response["Error"]["Message"].should.equal(
|
|
|
|
"This operation can be performed only for enabled policy types."
|
|
|
|
)
|
|
|
|
|
|
|
|
# invalid policy type
|
|
|
|
# when
|
2020-10-06 05:54:49 +00:00
|
|
|
with pytest.raises(ClientError) as e:
|
2020-08-02 09:56:19 +00:00
|
|
|
client.disable_policy_type(RootId=root_id, PolicyType="MOTO")
|
|
|
|
|
|
|
|
# then
|
2020-10-06 06:04:09 +00:00
|
|
|
ex = e.value
|
2020-08-02 09:56:19 +00:00
|
|
|
ex.operation_name.should.equal("DisablePolicyType")
|
|
|
|
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_aiservices_opt_out_policy():
|
|
|
|
# given
|
|
|
|
client = boto3.client("organizations", region_name="us-east-1")
|
|
|
|
org = client.create_organization(FeatureSet="ALL")["Organization"]
|
|
|
|
root_id = client.list_roots()["Roots"][0]["Id"]
|
|
|
|
client.enable_policy_type(RootId=root_id, PolicyType="AISERVICES_OPT_OUT_POLICY")
|
|
|
|
ai_policy = {
|
|
|
|
"services": {
|
|
|
|
"@@operators_allowed_for_child_policies": ["@@none"],
|
|
|
|
"default": {
|
|
|
|
"@@operators_allowed_for_child_policies": ["@@none"],
|
|
|
|
"opt_out_policy": {
|
|
|
|
"@@operators_allowed_for_child_policies": ["@@none"],
|
|
|
|
"@@assign": "optOut",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# when
|
|
|
|
response = client.create_policy(
|
|
|
|
Content=json.dumps(ai_policy),
|
|
|
|
Description="Opt out of all AI services",
|
|
|
|
Name="ai-opt-out",
|
|
|
|
Type="AISERVICES_OPT_OUT_POLICY",
|
|
|
|
)
|
|
|
|
|
|
|
|
# then
|
|
|
|
summary = response["Policy"]["PolicySummary"]
|
|
|
|
policy_id = summary["Id"]
|
|
|
|
summary["Id"].should.match(utils.POLICY_ID_REGEX)
|
|
|
|
summary["Arn"].should.equal(
|
|
|
|
utils.AI_POLICY_ARN_FORMAT.format(
|
|
|
|
org["MasterAccountId"], org["Id"], summary["Id"]
|
|
|
|
)
|
|
|
|
)
|
|
|
|
summary["Name"].should.equal("ai-opt-out")
|
|
|
|
summary["Description"].should.equal("Opt out of all AI services")
|
|
|
|
summary["Type"].should.equal("AISERVICES_OPT_OUT_POLICY")
|
|
|
|
summary["AwsManaged"].should_not.be.ok
|
|
|
|
json.loads(response["Policy"]["Content"]).should.equal(ai_policy)
|
|
|
|
|
|
|
|
# when
|
|
|
|
client.attach_policy(PolicyId=policy_id, TargetId=root_id)
|
|
|
|
|
|
|
|
# then
|
|
|
|
response = client.list_policies_for_target(
|
|
|
|
TargetId=root_id, Filter="AISERVICES_OPT_OUT_POLICY"
|
|
|
|
)
|
|
|
|
response["Policies"].should.have.length_of(1)
|
|
|
|
response["Policies"][0]["Id"].should.equal(policy_id)
|