mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-23 12:31:54 +00:00
fix(organization): list all accessible organizations (#8535)
Co-authored-by: MrCloudSec <hello@mistercloudsec.com>
This commit is contained in:
committed by
GitHub
parent
3c599a75cc
commit
55099abc86
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user