fix(organization): list all accessible organizations (#8535)

Co-authored-by: MrCloudSec <hello@mistercloudsec.com>
This commit is contained in:
Hugo Pereira Brito
2025-08-20 12:13:01 +02:00
committed by GitHub
parent 3c599a75cc
commit 55099abc86
3 changed files with 106 additions and 3 deletions
+1
View File
@@ -26,6 +26,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
### Fixed
- AWS resource-arn filtering [(#8533)](https://github.com/prowler-cloud/prowler/pull/8533)
- GitHub App authentication for GitHub provider [(#8529)](https://github.com/prowler-cloud/prowler/pull/8529)
- List all accessible organizations in GitHub provider [(#8535)](https://github.com/prowler-cloud/prowler/pull/8535)
---
@@ -5,6 +5,7 @@ from pydantic.v1 import BaseModel
from prowler.lib.logger import logger
from prowler.providers.github.lib.service.service import GithubService
from prowler.providers.github.models import GithubAppIdentityInfo, GithubIdentityInfo
class Organization(GithubService):
@@ -113,8 +114,15 @@ class Organization(GithubService):
elif not self.provider.repositories:
# Default behavior: get all organizations the user is a member of
# Only when no repositories are specified
for org in client.get_user().get_orgs():
self._process_organization(org, organizations)
if isinstance(self.provider.identity, GithubIdentityInfo):
orgs = client.get_user().get_orgs()
for org in orgs:
self._process_organization(org, organizations)
elif isinstance(self.provider.identity, GithubAppIdentityInfo):
orgs = client.get_organizations()
if orgs.totalCount > 0:
for org in orgs:
self._process_organization(org, organizations)
except github.RateLimitExceededException as error:
logger.error(f"GitHub API rate limit exceeded: {error}")
@@ -63,7 +63,12 @@ class Test_Organization_Scoping:
mock_client = MagicMock()
mock_user = MagicMock()
mock_user.get_orgs.return_value = [self.mock_org1, self.mock_org2]
mock_orgs = MagicMock()
mock_orgs.totalCount = 2
mock_orgs.__iter__ = MagicMock(
return_value=iter([self.mock_org1, self.mock_org2])
)
mock_user.get_orgs.return_value = mock_orgs
mock_client.get_user.return_value = mock_user
with patch(
@@ -81,6 +86,95 @@ class Test_Organization_Scoping:
assert orgs[1].name == "test-org1"
assert orgs[2].name == "test-org2"
def test_no_organizations_found_for_user(self):
"""Test that when user has no organizations, empty dict is returned"""
provider = set_mocked_github_provider()
provider.repositories = []
provider.organizations = []
mock_client = MagicMock()
mock_user = MagicMock()
mock_orgs = MagicMock()
mock_orgs.totalCount = 0
mock_user.get_orgs.return_value = mock_orgs
mock_client.get_user.return_value = mock_user
with patch(
"prowler.providers.github.services.organization.organization_service.GithubService.__init__"
):
organization_service = Organization(provider)
organization_service.clients = [mock_client]
organization_service.provider = provider
orgs = organization_service._list_organizations()
assert len(orgs) == 0
def test_github_app_organization_scoping(self):
"""Test GitHub App organization listing"""
from prowler.providers.github.models import GithubAppIdentityInfo
provider = set_mocked_github_provider()
provider.repositories = []
provider.organizations = []
# Set GitHub App identity
provider.identity = GithubAppIdentityInfo(
app_id="test-app-id",
app_name="test-app",
installations=["test-org1", "test-org2"],
)
mock_client = MagicMock()
mock_orgs = MagicMock()
mock_orgs.totalCount = 2
mock_orgs.__iter__ = MagicMock(
return_value=iter([self.mock_org1, self.mock_org2])
)
mock_client.get_organizations.return_value = mock_orgs
with patch(
"prowler.providers.github.services.organization.organization_service.GithubService.__init__"
):
organization_service = Organization(provider)
organization_service.clients = [mock_client]
organization_service.provider = provider
orgs = organization_service._list_organizations()
assert len(orgs) == 2
assert 1 in orgs
assert 2 in orgs
assert orgs[1].name == "test-org1"
assert orgs[2].name == "test-org2"
def test_github_app_no_organizations_found(self):
"""Test GitHub App when no organizations are accessible"""
from prowler.providers.github.models import GithubAppIdentityInfo
provider = set_mocked_github_provider()
provider.repositories = []
provider.organizations = []
# Set GitHub App identity
provider.identity = GithubAppIdentityInfo(
app_id="test-app-id", app_name="test-app", installations=[]
)
mock_client = MagicMock()
mock_orgs = MagicMock()
mock_orgs.totalCount = 0
mock_client.get_organizations.return_value = mock_orgs
with patch(
"prowler.providers.github.services.organization.organization_service.GithubService.__init__"
):
organization_service = Organization(provider)
organization_service.clients = [mock_client]
organization_service.provider = provider
orgs = organization_service._list_organizations()
assert len(orgs) == 0
def test_specific_organization_scoping(self):
"""Test that only specified organizations are returned"""
provider = set_mocked_github_provider()