feat: add new check to service

This commit is contained in:
HugoPBrito committed 2024-11-19 17:14:34 +01:00
1 parent d27c5b7190
commit d4e5b7c7c7
10 files changed
+150 -14

No files matched your search

+1 -1
View File
@@ -505,7 +505,7 @@ def load_check_metadata(metadata_file: str) -> CheckMetadata:
@dataclass
class Check_Report_GitHub(Check_Report):
class Check_Report_Github(Check_Report):
"""Contains the GitHub Check's finding information."""
account_name: str
+8
View File
@@ -232,6 +232,14 @@ class Finding(BaseModel):
)
output_data["region"] = f"namespace: {check_output.namespace}"
elif provider.type == "github":
output_data["auth_method"] = provider.auth_method
output_data["resource_name"] = check_output.resource_name
output_data["resource_uid"] = check_output.resource_id
output_data["account_name"] = provider.identity.account_name
output_data["account_uid"] = provider.identity.account_id
output_data["region"] = "global"
# check_output Unique ID
# TODO: move this to a function
# TODO: in Azure, GCP and K8s there are fidings without resource_name
+45
View File
@@ -538,6 +538,51 @@ class HTML(Output):
)
return ""
@staticmethod
def get_github_assessment_summary(provider: Provider) -> str:
"""
get_github_assessment_summary gets the HTML assessment summary for the provider
Args:
provider (Provider): the provider object
Returns:
str: the HTML assessment summary
"""
try:
return f"""
<div class="col-md-2">
<div class="card">
<div class="card-header">
GitHub Assessment Summary
</div>
<ul class="list-group
list-group-flush">
<li class="list-group-item">
<b>GitHub account:</b> {provider.identity.account_name}
</li>
</ul>
</div>
</div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
GitHub Credentials
</div>
<ul class="list-group
list-group-flush">
<li class="list-group-item">
<b>GitHub authentication method:</b> {provider.auth_method}
</li>
</ul>
</div>
</div>"""
except Exception as error:
logger.error(
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}"
)
return ""
@staticmethod
def get_assessment_summary(provider: Provider) -> str:
"""
+13 -4
View File
@@ -17,6 +17,7 @@ from prowler.providers.github.models import GithubIdentityInfo, GithubSession
class GithubProvider(Provider):
_type: str = "github"
_auth_method: str
_session: GithubSession
_identity: GithubIdentityInfo
_audit_config: dict
@@ -81,15 +82,20 @@ class GithubProvider(Provider):
Provider.set_global_provider(self)
@property
def identity(self):
"""Returns the identity information for the GitHub provider."""
return self._identity
def auth_method(self):
"""Returns the authentication method for the GitHub provider."""
return self._auth_method
@property
def session(self):
"""Returns the session object for the GitHub provider."""
return self._session
@property
def identity(self):
"""Returns the identity information for the GitHub provider."""
return self._identity
@property
def type(self):
"""Returns the type of the GitHub provider."""
@@ -130,10 +136,13 @@ class GithubProvider(Provider):
if personal_access_token:
session_token = getenv("GITHUB_PERSONAL_ACCESS_TOKEN")
self._auth_method = "personal_access_token"
elif github_app:
session_token = getenv("GITHUB_APP_TOKEN")
self._auth_method = "github_app"
elif oauth_app:
session_token = getenv("GITHUB_OAUTH_TOKEN")
self._auth_method = "oauth_app"
else:
raise ValueError(
"A GitHub API token of some kind is required to initialize GitHub provider."
@@ -175,4 +184,4 @@ class GithubProvider(Provider):
return identity
def print_credentials(self):
print("Using GitHub PAT")
print(f"You are using a {self.auth_method} as authentication method.")
@@ -1,4 +1,4 @@
from prowler.lib.check.models import Check_Report_GitHub
from prowler.lib.check.models import Check_Report_Github
from prowler.lib.mutelist.mutelist import Mutelist
from prowler.lib.outputs.utils import unroll_dict, unroll_tags
@@ -6,7 +6,7 @@ from prowler.lib.outputs.utils import unroll_dict, unroll_tags
class GitHubMutelist(Mutelist):
def is_finding_muted(
self,
finding: Check_Report_GitHub,
finding: Check_Report_Github,
) -> bool:
return self.is_muted(
finding.account_name,
@@ -11,9 +11,7 @@ class GithubService:
provider: GithubProvider,
):
self.client = self.__set_client__(
provider.identity,
provider.session,
service,
)
self.audit_config = provider.audit_config
@@ -1,4 +1,4 @@
from prowler.providers.common.provider import Provider
from prowler.providers.github.services.repository.repository_client import Repository
from prowler.providers.github.services.repository.repository_service import Repository
repository_client = Repository(Provider.get_global_provider())
@@ -0,0 +1,32 @@
{
"Provider": "github",
"CheckID": "repository_public_has_securitymd_file",
"CheckTitle": "Check if public repositories have a SECURITY.md file",
"CheckType": [
"CIS GitHub Benchmark v1.0.0"
],
"ServiceName": "repository",
"SubServiceName": "",
"ResourceIdTemplate": "github:user-id:repository/repository-name",
"Severity": "low",
"ResourceType": "Other",
"Description": "Ensure that public repositories have a SECURITY.md file",
"Risk": "Not having a SECURITY.md file in a public repository may lead to security vulnerabilities being overlooked by users and contributors.",
"RelatedUrl": "https://gist.github.com/bayudwiyansatria/3aa6a865aad8d45d69cdb80090bea7c7",
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "",
"Terraform": ""
},
"Recommendation": {
"Text": "Add a SECURITY.md file to the root of the repository. The file should contain information on how to report a security vulnerability, the security policy of the repository, and any other relevant information.",
"Url": "https://github.blog/changelog/2019-05-23-security-policy/"
}
},
"Categories": [],
"DependsOn": [],
"RelatedTo": [],
"Notes": ""
}
@@ -0,0 +1,42 @@
from typing import List
from prowler.lib.check.models import Check, Check_Report_Github
from prowler.providers.github.services.repository.repository_client import (
repository_client,
)
class repository_public_has_securitymd_file(Check):
"""Check if a public repository has a SECURITY.md file
This class verifies wheter each public repository has a SECURITY.md file.
"""
def execute(self) -> List[Check_Report_Github]:
"""Execute the Github Repository Public Has Securitymd File check
Iterates over all public repositories and checks if they have a SECURITY.md file.
Returns:
List[Check_Report_Github]: A list of reports for each repository
"""
findings = []
for repo in repository_client.repositories.values():
report = Check_Report_Github(self.metadata())
report.resource_id = repo.id
report.resource_name = repo.name
report.status = "PASS"
report.status_extended = (
f"Repository {repo.name} does have a SECURITY.md file."
)
if not repo.private:
if not repo.securitymd:
report.status = "FAIL"
report.status_extended = (
f"Repository {repo.name} does not have a SECURITY.md file."
)
findings.append(report)
return findings
@@ -10,19 +10,22 @@ class Repository(GithubService):
def __init__(self, provider):
super().__init__(__class__.__name__, provider)
self.repositories = {}
self.__threading_call__(self._list_repositories)
self._list_repositories()
def _list_repositories(self):
logger.info("Repository - Listing Repositories...")
try:
for repo in self.client.get_user().get_repos():
try:
securitymd_exists = repo.get_contents("SECURITY.md") is not None
except Exception:
securitymd_exists = False
self.repositories[repo.id] = Repo(
id=repo.id,
name=repo.name,
full_name=repo.full_name,
private=repo.private,
description=repo.description,
securitymd=repo.get_contents("SECURITY.md") is not None,
securitymd=securitymd_exists,
)
except Exception as error:
logger.error(
@@ -40,5 +43,4 @@ class Repo(BaseModel):
name: str
full_name: str
private: bool
description: Optional[str]
securitymd: Optional[bool] = False