mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-11-09 04:38:49 +00:00
fix(outputs): refresh scan timestamps per run (#9272)
This commit is contained in:
1 parent
b6ba6c6e31
commit
dc7d2d5aeb
5 files changed
+65
-4
No files matched your search
@@ -27,6 +27,7 @@ All notable changes to the **Prowler API** are documented in this file.
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Scans no longer fail when findings have UIDs exceeding 300 characters; such findings are now skipped with detailed logging [(#9246)](https://github.com/prowler-cloud/prowler/pull/9246)
|
- Scans no longer fail when findings have UIDs exceeding 300 characters; such findings are now skipped with detailed logging [(#9246)](https://github.com/prowler-cloud/prowler/pull/9246)
|
||||||
|
- Refresh output report timestamps for each scan [(#9272)](https://github.com/prowler-cloud/prowler/pull/9272)
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
- Django updated to the latest 5.1 security release, 5.1.14, due to problems with potential [SQL injection](https://github.com/prowler-cloud/prowler/security/dependabot/113) and [denial-of-service vulnerability](https://github.com/prowler-cloud/prowler/security/dependabot/114) [(#9176)](https://github.com/prowler-cloud/prowler/pull/9176)
|
- Django updated to the latest 5.1 security release, 5.1.14, due to problems with potential [SQL injection](https://github.com/prowler-cloud/prowler/security/dependabot/113) and [denial-of-service vulnerability](https://github.com/prowler-cloud/prowler/security/dependabot/114) [(#9176)](https://github.com/prowler-cloud/prowler/pull/9176)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ from prowler.config.config import (
|
|||||||
html_file_suffix,
|
html_file_suffix,
|
||||||
json_asff_file_suffix,
|
json_asff_file_suffix,
|
||||||
json_ocsf_file_suffix,
|
json_ocsf_file_suffix,
|
||||||
|
set_output_timestamp,
|
||||||
)
|
)
|
||||||
from prowler.lib.outputs.asff.asff import ASFF
|
from prowler.lib.outputs.asff.asff import ASFF
|
||||||
from prowler.lib.outputs.compliance.aws_well_architected.aws_well_architected import (
|
from prowler.lib.outputs.compliance.aws_well_architected.aws_well_architected import (
|
||||||
@@ -275,6 +276,8 @@ def _build_output_path(
|
|||||||
with rls_transaction(tenant_id):
|
with rls_transaction(tenant_id):
|
||||||
started_at = Scan.objects.get(id=scan_id).started_at
|
started_at = Scan.objects.get(id=scan_id).started_at
|
||||||
|
|
||||||
|
set_output_timestamp(started_at)
|
||||||
|
|
||||||
timestamp = started_at.strftime("%Y%m%d%H%M%S")
|
timestamp = started_at.strftime("%Y%m%d%H%M%S")
|
||||||
|
|
||||||
if subdirectory:
|
if subdirectory:
|
||||||
|
|||||||
@@ -148,10 +148,11 @@ class TestOutputs:
|
|||||||
)
|
)
|
||||||
mock_logger.assert_called()
|
mock_logger.assert_called()
|
||||||
|
|
||||||
|
@patch("tasks.jobs.export.set_output_timestamp")
|
||||||
@patch("tasks.jobs.export.rls_transaction")
|
@patch("tasks.jobs.export.rls_transaction")
|
||||||
@patch("tasks.jobs.export.Scan")
|
@patch("tasks.jobs.export.Scan")
|
||||||
def test_generate_output_directory_creates_paths(
|
def test_generate_output_directory_creates_paths(
|
||||||
self, mock_scan, mock_rls_transaction, tmpdir
|
self, mock_scan, mock_rls_transaction, mock_set_timestamp, tmpdir
|
||||||
):
|
):
|
||||||
# Mock the scan object with a started_at timestamp
|
# Mock the scan object with a started_at timestamp
|
||||||
mock_scan_instance = MagicMock()
|
mock_scan_instance = MagicMock()
|
||||||
@@ -198,10 +199,11 @@ class TestOutputs:
|
|||||||
assert ens.endswith(f"{provider}-{expected_timestamp}")
|
assert ens.endswith(f"{provider}-{expected_timestamp}")
|
||||||
assert "/ens/" in ens
|
assert "/ens/" in ens
|
||||||
|
|
||||||
|
@patch("tasks.jobs.export.set_output_timestamp")
|
||||||
@patch("tasks.jobs.export.rls_transaction")
|
@patch("tasks.jobs.export.rls_transaction")
|
||||||
@patch("tasks.jobs.export.Scan")
|
@patch("tasks.jobs.export.Scan")
|
||||||
def test_generate_output_directory_invalid_character(
|
def test_generate_output_directory_invalid_character(
|
||||||
self, mock_scan, mock_rls_transaction, tmpdir
|
self, mock_scan, mock_rls_transaction, mock_set_timestamp, tmpdir
|
||||||
):
|
):
|
||||||
# Mock the scan object with a started_at timestamp
|
# Mock the scan object with a started_at timestamp
|
||||||
mock_scan_instance = MagicMock()
|
mock_scan_instance = MagicMock()
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
|||||||
- Rename `get_oci_assessment_summary` to `get_oraclecloud_assessment_summary` in HTML output [(#9200)](https://github.com/prowler-cloud/prowler/pull/9200)
|
- Rename `get_oci_assessment_summary` to `get_oraclecloud_assessment_summary` in HTML output [(#9200)](https://github.com/prowler-cloud/prowler/pull/9200)
|
||||||
- Fix Validation and other errors in Azure provider [(#8915)](https://github.com/prowler-cloud/prowler/pull/8915)
|
- Fix Validation and other errors in Azure provider [(#8915)](https://github.com/prowler-cloud/prowler/pull/8915)
|
||||||
- Update documentation URLs from docs.prowler.cloud to docs.prowler.com [(#9240)](https://github.com/prowler-cloud/prowler/pull/9240)
|
- Update documentation URLs from docs.prowler.cloud to docs.prowler.com [(#9240)](https://github.com/prowler-cloud/prowler/pull/9240)
|
||||||
|
- Refresh output report timestamps for each scan [(#9272)](https://github.com/prowler-cloud/prowler/pull/9272)
|
||||||
- Fix file name parsing for checks on Windows [(#9268)](https://github.com/prowler-cloud/prowler/pull/9268)
|
- Fix file name parsing for checks on Windows [(#9268)](https://github.com/prowler-cloud/prowler/pull/9268)
|
||||||
- Remove typo for Prowler ThreatScore - M365 [(#9274)](https://github.com/prowler-cloud/prowler/pull/9274)
|
- Remove typo for Prowler ThreatScore - M365 [(#9274)](https://github.com/prowler-cloud/prowler/pull/9274)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import pathlib
|
|||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from os import getcwd
|
from os import getcwd
|
||||||
|
from typing import Tuple
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import yaml
|
import yaml
|
||||||
@@ -10,8 +11,33 @@ from packaging import version
|
|||||||
|
|
||||||
from prowler.lib.logger import logger
|
from prowler.lib.logger import logger
|
||||||
|
|
||||||
timestamp = datetime.today()
|
|
||||||
timestamp_utc = datetime.now(timezone.utc).replace(tzinfo=timezone.utc)
|
class _MutableTimestamp:
|
||||||
|
"""Lightweight proxy to keep timestamp references in sync across modules."""
|
||||||
|
|
||||||
|
def __init__(self, value: datetime) -> None:
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def set(self, value: datetime) -> None:
|
||||||
|
self.value = value
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
return getattr(self.value, name)
|
||||||
|
|
||||||
|
def __str__(self) -> str: # pragma: no cover - trivial forwarder
|
||||||
|
return str(self.value)
|
||||||
|
|
||||||
|
def __repr__(self) -> str: # pragma: no cover - trivial forwarder
|
||||||
|
return repr(self.value)
|
||||||
|
|
||||||
|
def __eq__(self, other) -> bool:
|
||||||
|
if isinstance(other, _MutableTimestamp):
|
||||||
|
return self.value == other.value
|
||||||
|
return self.value == other
|
||||||
|
|
||||||
|
|
||||||
|
timestamp = _MutableTimestamp(datetime.today())
|
||||||
|
timestamp_utc = _MutableTimestamp(datetime.now(timezone.utc))
|
||||||
prowler_version = "5.14.0"
|
prowler_version = "5.14.0"
|
||||||
html_logo_url = "https://github.com/prowler-cloud/prowler/"
|
html_logo_url = "https://github.com/prowler-cloud/prowler/"
|
||||||
square_logo_img = "https://prowler.com/wp-content/uploads/logo-html.png"
|
square_logo_img = "https://prowler.com/wp-content/uploads/logo-html.png"
|
||||||
@@ -84,6 +110,34 @@ encoding_format_utf_8 = "utf-8"
|
|||||||
available_output_formats = ["csv", "json-asff", "json-ocsf", "html"]
|
available_output_formats = ["csv", "json-asff", "json-ocsf", "html"]
|
||||||
|
|
||||||
|
|
||||||
|
def set_output_timestamp(
|
||||||
|
new_timestamp: datetime,
|
||||||
|
) -> Tuple[datetime, datetime, str, str]:
|
||||||
|
"""
|
||||||
|
Override the global output timestamps so generated artifacts reflect a specific scan.
|
||||||
|
Returns the previous values so callers can restore them afterwards.
|
||||||
|
"""
|
||||||
|
global timestamp, timestamp_utc, output_file_timestamp, timestamp_iso
|
||||||
|
|
||||||
|
previous_values = (
|
||||||
|
timestamp.value,
|
||||||
|
timestamp_utc.value,
|
||||||
|
output_file_timestamp,
|
||||||
|
timestamp_iso,
|
||||||
|
)
|
||||||
|
|
||||||
|
timestamp.set(new_timestamp)
|
||||||
|
timestamp_utc.set(
|
||||||
|
new_timestamp.astimezone(timezone.utc)
|
||||||
|
if new_timestamp.tzinfo
|
||||||
|
else new_timestamp.replace(tzinfo=timezone.utc)
|
||||||
|
)
|
||||||
|
output_file_timestamp = timestamp.strftime("%Y%m%d%H%M%S")
|
||||||
|
timestamp_iso = timestamp.isoformat(sep=" ", timespec="seconds")
|
||||||
|
|
||||||
|
return previous_values
|
||||||
|
|
||||||
|
|
||||||
def get_default_mute_file_path(provider: str):
|
def get_default_mute_file_path(provider: str):
|
||||||
"""
|
"""
|
||||||
get_default_mute_file_path returns the default mute file path for the provider
|
get_default_mute_file_path returns the default mute file path for the provider
|
||||||
|
|||||||
Reference in new issue
Block a user