Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(resource metadata): add resource metadata to JSON OCSF #6592

Merged
merged 14 commits into from
Jan 23, 2025
Merged
  •  
  •  
  •  
97 changes: 37 additions & 60 deletions prowler/lib/check/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,12 +405,12 @@
status: str
status_extended: str
check_metadata: CheckMetadata
resource_metadata: dict
resource: dict
resource_details: str
resource_tags: list
muted: bool

def __init__(self, metadata: Dict, resource: Any = None) -> None:
def __init__(self, metadata: Dict, resource: Any) -> None:
"""Initialize the Check's finding information.

Args:
Expand All @@ -421,20 +421,20 @@
self.status = ""
self.check_metadata = CheckMetadata.parse_raw(metadata)
if isinstance(resource, dict):
self.resource_metadata = resource
self.resource = resource
elif isinstance(resource, list):
self.resource_metadata = dict(enumerate(resource))
self.resource = dict(enumerate(resource))
elif hasattr(resource, "dict"):
self.resource_metadata = resource.dict()
self.resource = resource.dict()
elif hasattr(resource, "to_dict"):
self.resource_metadata = resource.to_dict()
self.resource = resource.to_dict()

Check warning on line 430 in prowler/lib/check/models.py

View check run for this annotation

Codecov / codecov/patch

prowler/lib/check/models.py#L430

Added line #L430 was not covered by tests
elif hasattr(resource, "__dict__"):
jfagoagas marked this conversation as resolved.
Show resolved Hide resolved
self.resource_metadata = resource.__dict__
self.resource = resource.__dict__
else:
logger.error(
f"Resource metadata {type(resource)} could not be converted to dict"
)
self.resource_metadata = {}
self.resource = {}

Check warning on line 437 in prowler/lib/check/models.py

View check run for this annotation

Codecov / codecov/patch

prowler/lib/check/models.py#L437

Added line #L437 was not covered by tests
self.status_extended = ""
self.resource_details = ""
self.resource_tags = getattr(resource, "tags", []) if resource else []
Expand All @@ -449,20 +449,13 @@
resource_arn: str
region: str

def __init__(self, metadata, resource_metadata=None):
super().__init__(metadata, resource_metadata)
if resource_metadata:
self.resource_id = (
getattr(resource_metadata, "id", None)
or getattr(resource_metadata, "name", None)
or ""
)
self.resource_arn = getattr(resource_metadata, "arn", "")
self.region = getattr(resource_metadata, "region", "")
else:
self.resource_id = ""
self.resource_arn = ""
self.region = ""
def __init__(self, metadata: Dict, resource: Any) -> None:
super().__init__(metadata, resource)
self.resource_id = (
getattr(resource, "id", None) or getattr(resource, "name", None) or ""
)
self.resource_arn = getattr(resource, "arn", "")
self.region = getattr(resource, "region", "")


@dataclass
Expand All @@ -474,34 +467,20 @@
subscription: str
location: str

def __init__(self, metadata: Dict, resource_metadata: Any = None) -> None:
def __init__(self, metadata: Dict, resource: Any) -> None:
"""Initialize the Azure Check's finding information.

Args:
metadata: The metadata of the check.
resource_metadata: Basic information about the resource. Defaults to None.
resource: Basic information about the resource. Defaults to None.
"""
super().__init__(metadata, resource_metadata)
self.resource_name = (
resource_metadata.name
if hasattr(resource_metadata, "name")
else (
resource_metadata.resource_name
if hasattr(resource_metadata, "resource_name")
else ""
)
)
self.resource_id = (
resource_metadata.id
if hasattr(resource_metadata, "id")
else (
resource_metadata.resource_id
if hasattr(resource_metadata, "resource_id")
else ""
)
super().__init__(metadata, resource)
self.resource_name = getattr(
resource, "name", getattr(resource, "resource_name", "")
)
self.resource_id = getattr(resource, "id", getattr(resource, "resource_id", ""))
self.subscription = ""
self.location = getattr(resource_metadata, "location", "global")
self.location = getattr(resource, "location", "global")


@dataclass
Expand All @@ -515,26 +494,26 @@

def __init__(
self,
metadata,
resource_metadata,
metadata: Dict,
resource: Any,
location=None,
resource_name=None,
resource_id=None,
project_id=None,
):
super().__init__(metadata, resource_metadata)
) -> None:
super().__init__(metadata, resource)
self.resource_id = (
resource_id
or getattr(resource_metadata, "id", None)
or getattr(resource_metadata, "name", None)
or getattr(resource, "id", None)
or getattr(resource, "name", None)
or ""
)
self.resource_name = resource_name or getattr(resource_metadata, "name", "")
self.project_id = project_id or getattr(resource_metadata, "project_id", "")
self.resource_name = resource_name or getattr(resource, "name", "")
self.project_id = project_id or getattr(resource, "project_id", "")
self.location = (
location
or getattr(resource_metadata, "location", "")
or getattr(resource_metadata, "region", "")
or getattr(resource, "location", "")
or getattr(resource, "region", "")
)


Expand All @@ -547,15 +526,13 @@
resource_id: str
namespace: str

def __init__(self, metadata, resource_metadata):
super().__init__(metadata, resource_metadata)
def __init__(self, metadata: Dict, resource: Any) -> None:
super().__init__(metadata, resource)

Check warning on line 530 in prowler/lib/check/models.py

View check run for this annotation

Codecov / codecov/patch

prowler/lib/check/models.py#L530

Added line #L530 was not covered by tests
self.resource_id = (
getattr(resource_metadata, "uid", None)
or getattr(resource_metadata, "name", None)
or ""
getattr(resource, "uid", None) or getattr(resource, "name", None) or ""
)
self.resource_name = getattr(resource_metadata, "name", "")
self.namespace = getattr(resource_metadata, "namespace", "cluster-wide")
self.resource_name = getattr(resource, "name", "")
self.namespace = getattr(resource, "namespace", "cluster-wide")

Check warning on line 535 in prowler/lib/check/models.py

View check run for this annotation

Codecov / codecov/patch

prowler/lib/check/models.py#L534-L535

Added lines #L534 - L535 were not covered by tests
if not self.namespace:
self.namespace = "cluster-wide"

Expand Down
2 changes: 1 addition & 1 deletion prowler/lib/outputs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def fill_common_finding_data(finding: dict, unix_timestamp: bool) -> dict:
"status_extended": finding.status_extended,
"muted": finding.muted,
"resource_details": finding.resource_details,
# "resource_metadata": finding.resource_metadata, TODO: add resource_metadata to the finding
"resource": finding.resource,
"resource_tags": unroll_tags(finding.resource_tags),
}
return finding_data
Expand Down
2 changes: 1 addition & 1 deletion prowler/lib/outputs/finding.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Finding(BaseModel):
status_extended: str
muted: bool = False
resource_uid: str
# resource_metadata: dict = Field(default_factory=dict) TODO: add resource_metadata to the finding
resource: dict = Field(default_factory=dict)
jfagoagas marked this conversation as resolved.
Show resolved Hide resolved
resource_name: str
resource_details: str
resource_tags: dict = Field(default_factory=dict)
Expand Down
5 changes: 3 additions & 2 deletions prowler/lib/outputs/ocsf/ocsf.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
region=finding.region,
data={
"details": finding.resource_details,
# "metadata": finding.resource_metadata, TODO: add the resource_metadata to the finding
"metadata": finding.resource,
},
)
]
Expand All @@ -127,7 +127,7 @@
type=finding.metadata.ResourceType,
data={
"details": finding.resource_details,
# "metadata": finding.resource_metadata, TODO: add the resource_metadata to the finding
"metadata": finding.resource,
},
namespace=finding.region.replace("namespace: ", ""),
)
Expand Down Expand Up @@ -206,6 +206,7 @@
self._file_descriptor.write("]")
self._file_descriptor.close()
except Exception as error:
print(finding)

Check warning on line 209 in prowler/lib/outputs/ocsf/ocsf.py

View check run for this annotation

Codecov / codecov/patch

prowler/lib/outputs/ocsf/ocsf.py#L209

Added line #L209 was not covered by tests
jfagoagas marked this conversation as resolved.
Show resolved Hide resolved
logger.error(
f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ class accessanalyzer_enabled(Check):
def execute(self):
findings = []
for analyzer in accessanalyzer_client.analyzers:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=analyzer
)
report = Check_Report_AWS(metadata=self.metadata(), resource=analyzer)
if analyzer.status == "ACTIVE":
report.status = "PASS"
report.status_extended = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ class accessanalyzer_enabled_without_findings(Check):
def execute(self):
findings = []
for analyzer in accessanalyzer_client.analyzers:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=analyzer
)
report = Check_Report_AWS(metadata=self.metadata(), resource=analyzer)
if analyzer.status == "ACTIVE":
report.status = "PASS"
report.status_extended = f"IAM Access Analyzer {analyzer.name} does not have active findings."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class account_maintain_current_contact_details(Check):
def execute(self):
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=account_client.contact_base
metadata=self.metadata(), resource=account_client.contact_base
)
report.region = account_client.region
report.resource_id = account_client.audited_account
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def execute(self):
findings = []
if account_client.contact_base:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=account_client.contact_base
metadata=self.metadata(), resource=account_client.contact_base
)
report.resource_id = account_client.audited_account
report.resource_arn = account_client.audited_account_arn
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class account_security_contact_information_is_registered(Check):
def execute(self):
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=account_client.contact_base
metadata=self.metadata(), resource=account_client.contact_base
)
report.region = account_client.region
report.resource_id = account_client.audited_account
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class account_security_questions_are_registered_in_the_aws_account(Check):
def execute(self):
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=account_client.contacts_security
metadata=self.metadata(), resource=account_client.contacts_security
)
report.region = account_client.region
report.resource_id = account_client.audited_account
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def execute(self):
for certificate in acm_client.certificates.values():
if certificate.in_use or acm_client.provider.scan_unused_services:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=certificate
metadata=self.metadata(), resource=certificate
)
if certificate.expiration_days > acm_client.audit_config.get(
"days_to_expire_threshold", 7
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def execute(self):
for certificate in acm_client.certificates.values():
if certificate.in_use or acm_client.provider.scan_unused_services:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=certificate
metadata=self.metadata(), resource=certificate
)
if certificate.type == "IMPORTED":
report.status = "PASS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def execute(self):
for certificate in acm_client.certificates.values():
if certificate.in_use or acm_client.provider.scan_unused_services:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=certificate
metadata=self.metadata(), resource=certificate
)

report.status = "PASS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ class apigateway_restapi_authorizers_enabled(Check):
def execute(self):
findings = []
for rest_api in apigateway_client.rest_apis:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=rest_api
)
report = Check_Report_AWS(metadata=self.metadata(), resource=rest_api)
report.resource_id = rest_api.name

# it there are not authorizers at api level and resources without methods (default case) ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ def execute(self):
for rest_api in apigateway_client.rest_apis:
for stage in rest_api.stages:
if stage.cache_enabled:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=stage
)
report = Check_Report_AWS(metadata=self.metadata(), resource=stage)
report.region = rest_api.region
report.resource_id = rest_api.name
report.status = "PASS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ def execute(self):
findings = []
for rest_api in apigateway_client.rest_apis:
for stage in rest_api.stages:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=stage
)
report = Check_Report_AWS(metadata=self.metadata(), resource=stage)
report.resource_id = rest_api.name
report.region = rest_api.region
if stage.client_certificate:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ def execute(self):
findings = []
for rest_api in apigateway_client.rest_apis:
for stage in rest_api.stages:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=stage
)
report = Check_Report_AWS(metadata=self.metadata(), resource=stage)
report.resource_id = rest_api.name
report.region = rest_api.region
if stage.logging:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ class apigateway_restapi_public(Check):
def execute(self):
findings = []
for rest_api in apigateway_client.rest_apis:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=rest_api
)
report = Check_Report_AWS(metadata=self.metadata(), resource=rest_api)
report.resource_id = rest_api.name

if rest_api.public_endpoint:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ def execute(self):
findings = []
for rest_api in apigateway_client.rest_apis:
if rest_api.public_endpoint:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=rest_api
)
report = Check_Report_AWS(metadata=self.metadata(), resource=rest_api)
report.resource_id = rest_api.name

report.status = "PASS"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ def execute(self):
findings = []
for rest_api in apigateway_client.rest_apis:
for stage in rest_api.stages:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=stage
)
report = Check_Report_AWS(metadata=self.metadata(), resource=stage)
report.region = rest_api.region
report.resource_id = rest_api.name
report.status = "FAIL"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ def execute(self):
findings = []
for rest_api in apigateway_client.rest_apis:
for stage in rest_api.stages:
report = Check_Report_AWS(
metadata=self.metadata(), resource_metadata=stage
)
report = Check_Report_AWS(metadata=self.metadata(), resource=stage)
report.resource_id = rest_api.name
report.region = rest_api.region
if stage.waf:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class apigatewayv2_api_access_logging_enabled(Check):
def execute(self):
findings = []
for api in apigatewayv2_client.apis:
report = Check_Report_AWS(metadata=self.metadata(), resource_metadata=api)
report = Check_Report_AWS(metadata=self.metadata(), resource=api)
for stage in api.stages:
if stage.logging:
report.status = "PASS"
Expand Down
Loading
Loading