fix(github): solve Github APP auth method (#8529)

This commit is contained in:
Sergio Garcia
2025-08-18 02:35:19 -04:00
committed by GitHub
parent 39e4d20b24
commit fd833eecf0
7 changed files with 60 additions and 7 deletions
+8 -1
View File
@@ -17,7 +17,14 @@ All notable changes to the **Prowler SDK** are documented in this file.
---
## [v5.10.2] (Prowler UNRELEASED)
## [v5.10.3] (Prowler UNRELEASED)
### Fixed
- GitHub App authentication for GitHub provider [(#8529)](https://github.com/prowler-cloud/prowler/pull/8529)
---
## [v5.10.2] (Prowler v5.10.2)
### Fixed
- Order requirements by ID in Prowler ThreatScore AWS compliance framework [(#8495)](https://github.com/prowler-cloud/prowler/pull/8495)
+9 -1
View File
@@ -365,8 +365,16 @@ class GithubProvider(Provider):
elif session.id != 0 and session.key:
auth = Auth.AppAuth(session.id, session.key)
gi = GithubIntegration(auth=auth, retry=retry_config)
installations = []
for installation in gi.get_installations():
installations.append(
installation.raw_data.get("account", {}).get("login")
)
try:
identity = GithubAppIdentityInfo(app_id=gi.get_app().id)
identity = GithubAppIdentityInfo(
app_id=gi.get_app().id,
installations=installations,
)
return identity
except Exception as error:
+1
View File
@@ -18,6 +18,7 @@ class GithubIdentityInfo(BaseModel):
class GithubAppIdentityInfo(BaseModel):
app_id: str
installations: list[str]
class GithubOutputOptions(ProviderOutputOptions):
@@ -7,6 +7,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
class Repository(GithubService):
@@ -102,12 +103,23 @@ class Repository(GithubService):
def _list_repositories(self):
"""
List repositories based on provider scoping configuration.
If the provider is a GitHub App, it will list repositories in the organizations that the GitHub App is installed in.
If the provider is a user, it will list repositories where the user is a member or owner.
If input repositories are provided, it will list repositories that match the input repositories.
If input organizations are provided, it will list repositories in the organizations that match the input organizations.
"""
logger.info("Repository - Listing Repositories...")
repos = {}
try:
for client in self.clients:
if self.provider.repositories or self.provider.organizations:
if (
self.provider.repositories
or self.provider.organizations
or (
isinstance(self.provider.identity, GithubAppIdentityInfo)
and self.provider.identity.installations
)
):
if self.provider.repositories:
logger.info(
f"Filtering for specific repositories: {self.provider.repositories}"
@@ -141,6 +153,24 @@ class Repository(GithubService):
self._handle_github_api_error(
error, "processing organization", org_name
)
if (
isinstance(self.provider.identity, GithubAppIdentityInfo)
and self.provider.identity.installations
):
logger.info(
f"Filtering for repositories in the organizations or accounts that the GitHub App is installed in: {', '.join(self.provider.identity.installations)}"
)
for org_name in self.provider.identity.installations:
try:
repos_list, _ = self._get_repositories_from_owner(
client, org_name
)
for repo in repos_list:
self._process_repository(repo, repos)
except Exception as error:
self._handle_github_api_error(
error, "processing organization", org_name
)
else:
logger.info(
"No repository or organization specified, discovering accessible repositories via GraphQL API..."
+3 -1
View File
@@ -585,7 +585,9 @@ class TestFinding:
provider = MagicMock()
provider.type = "github"
# GitHub App identity only has app_id, not account_name/account_id
provider.identity = GithubAppIdentityInfo(app_id=APP_ID)
provider.identity = GithubAppIdentityInfo(
app_id=APP_ID, installations=["test-org"]
)
provider.auth_method = "GitHub App Token"
# Mock check result
+1 -1
View File
@@ -673,7 +673,7 @@ class TestHTML:
provider = set_mocked_github_provider(
auth_method="GitHub App Token",
identity=GithubAppIdentityInfo(app_id=APP_ID),
identity=GithubAppIdentityInfo(app_id=APP_ID, installations=["test-org"]),
)
summary = output.get_assessment_summary(provider)
@@ -135,6 +135,7 @@ class TestGitHubProvider:
"prowler.providers.github.github_provider.GithubProvider.setup_identity",
return_value=GithubAppIdentityInfo(
app_id=APP_ID,
installations=["test-org"],
),
),
):
@@ -147,7 +148,9 @@ class TestGitHubProvider:
assert provider._type == "github"
assert provider.session == GithubSession(token="", id=APP_ID, key=APP_KEY)
assert provider.identity == GithubAppIdentityInfo(app_id=APP_ID)
assert provider.identity == GithubAppIdentityInfo(
app_id=APP_ID, installations=["test-org"]
)
assert provider._audit_config == {
"inactive_not_archived_days_threshold": 180,
}
@@ -206,7 +209,9 @@ class TestGitHubProvider:
),
patch(
"prowler.providers.github.github_provider.GithubProvider.setup_identity",
return_value=GithubAppIdentityInfo(app_id=APP_ID),
return_value=GithubAppIdentityInfo(
app_id=APP_ID, installations=["test-org"]
),
),
):
connection = GithubProvider.test_connection(