From 7858417ce253986074621d9d4c259feeb35f820f Mon Sep 17 00:00:00 2001 From: Anastasia Dusak <61540676+k-a-il@users.noreply.github.com> Date: Tue, 28 Jan 2025 15:17:51 +0100 Subject: [PATCH 1/2] Organizations: list_roots() now returns roots for requests made by other accounts within the organization --- moto/organizations/models.py | 11 +++++- .../test_organizations_boto3.py | 36 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/moto/organizations/models.py b/moto/organizations/models.py index dba3eef7c21a..7c241b9d958a 100644 --- a/moto/organizations/models.py +++ b/moto/organizations/models.py @@ -482,7 +482,16 @@ def delete_organization(self) -> None: self._reset() def list_roots(self) -> Dict[str, Any]: - return dict(Roots=[ou.describe() for ou in self.ou if isinstance(ou, FakeRoot)]) + if self.org: + return dict(Roots=[ou.describe() for ou in self.ou if isinstance(ou, FakeRoot)]) + + if self.account_id in organizations_backends.master_accounts: + master_account_id, partition = organizations_backends.master_accounts[ + self.account_id + ] + return organizations_backends[master_account_id][partition].list_roots() + + raise AWSOrganizationsNotInUseException def create_organizational_unit(self, **kwargs: Any) -> Dict[str, Any]: new_ou = FakeOrganizationalUnit(self.org, **kwargs) # type: ignore diff --git a/tests/test_organizations/test_organizations_boto3.py b/tests/test_organizations/test_organizations_boto3.py index 478d094406e4..a860fe722418 100644 --- a/tests/test_organizations/test_organizations_boto3.py +++ b/tests/test_organizations/test_organizations_boto3.py @@ -189,6 +189,42 @@ def test_list_roots(): validate_roots(org, response) +@mock_aws +def test_list_roots_for_new_account_in_organization(): + if not settings.TEST_DECORATOR_MODE: + raise SkipTest("Involves changing account using env variable") + client = boto3.client("organizations", region_name="us-east-1") + org = client.create_organization()["Organization"] + org_roots = client.list_roots() + new_account_id = client.create_account( + AccountName="test_account", + Email="test@test.xyz", + RoleName="CustomOrganizationRole", + )["CreateAccountStatus"]["AccountId"] + + with mock.patch.dict(os.environ, {"MOTO_ACCOUNT_ID": new_account_id}): + client_for_new_account = boto3.client("organizations", "us-east-1") + new_account_roots = client_for_new_account.list_roots() + validate_roots(org, new_account_roots) + assert len(new_account_roots["Roots"]) == 1 + assert len(org_roots["Roots"]) == len(new_account_roots["Roots"]) + assert org_roots["Roots"][0] == new_account_roots["Roots"][0] + + +@mock_aws +def test_list_roots_for_account_without_organization_exception(): + client = boto3.client("organizations", region_name="us-east-1") + with pytest.raises(ClientError) as e: + client.list_roots() + ex = e.value + assert ex.operation_name == "ListRoots" + assert ex.response["ResponseMetadata"]["HTTPStatusCode"] == 400 + assert "AWSOrganizationsNotInUseException" in ex.response["Error"]["Code"] + assert ex.response["Error"]["Message"] == ( + "Your account is not a member of an organization." + ) + + @mock_aws def test_create_organizational_unit(): client = boto3.client("organizations", region_name="us-east-1") From 964600b9ca132d0f2d66a1a304f5fe371f73e408 Mon Sep 17 00:00:00 2001 From: Anastasia Dusak <61540676+k-a-il@users.noreply.github.com> Date: Tue, 28 Jan 2025 20:31:07 +0100 Subject: [PATCH 2/2] Fixed formatting --- moto/organizations/models.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/moto/organizations/models.py b/moto/organizations/models.py index 7c241b9d958a..3f036076ac14 100644 --- a/moto/organizations/models.py +++ b/moto/organizations/models.py @@ -483,7 +483,9 @@ def delete_organization(self) -> None: def list_roots(self) -> Dict[str, Any]: if self.org: - return dict(Roots=[ou.describe() for ou in self.ou if isinstance(ou, FakeRoot)]) + return dict( + Roots=[ou.describe() for ou in self.ou if isinstance(ou, FakeRoot)] + ) if self.account_id in organizations_backends.master_accounts: master_account_id, partition = organizations_backends.master_accounts[