mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-04-07 07:57:11 +00:00
Compare commits
4 Commits
dependabot
...
fix/api-re
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47b33ca4dd | ||
|
|
ec6516f5de | ||
|
|
c99ed991b7 | ||
|
|
7c0034524a |
@@ -28,6 +28,7 @@ All notable changes to the **Prowler API** are documented in this file.
|
||||
- Membership `post_delete` signal using raw FK ids to avoid `DoesNotExist` during cascade deletions [(#10497)](https://github.com/prowler-cloud/prowler/pull/10497)
|
||||
- Finding group resources endpoints returning false 404 when filters match no results, and `sort` parameter being ignored [(#10510)](https://github.com/prowler-cloud/prowler/pull/10510)
|
||||
- Jira integration failing with `JiraInvalidIssueTypeError` on non-English Jira instances due to hardcoded `"Task"` issue type; now dynamically fetches available issue types per project [(#10534)](https://github.com/prowler-cloud/prowler/pull/10534)
|
||||
- Attack Paths: Remove `clear_cache` call from read-only query endpoints; cache clearing belongs to the scan/ingestion flow, not API queries [(#10586)](https://github.com/prowler-cloud/prowler/pull/10586)
|
||||
|
||||
### 🔐 Security
|
||||
|
||||
|
||||
@@ -4287,7 +4287,6 @@ class TestAttackPathsScanViewSet:
|
||||
"api.v1.views.attack_paths_views_helpers.execute_query",
|
||||
return_value=graph_payload,
|
||||
) as mock_execute,
|
||||
patch("api.v1.views.graph_database.clear_cache") as mock_clear_cache,
|
||||
):
|
||||
response = authenticated_client.post(
|
||||
reverse(
|
||||
@@ -4314,7 +4313,6 @@ class TestAttackPathsScanViewSet:
|
||||
prepared_parameters,
|
||||
provider_id,
|
||||
)
|
||||
mock_clear_cache.assert_called_once_with(expected_db_name)
|
||||
result = response.json()["data"]
|
||||
attributes = result["attributes"]
|
||||
assert attributes["nodes"] == graph_payload["nodes"]
|
||||
@@ -4369,7 +4367,6 @@ class TestAttackPathsScanViewSet:
|
||||
"api.v1.views.attack_paths_views_helpers.execute_query",
|
||||
return_value=graph_payload,
|
||||
),
|
||||
patch("api.v1.views.graph_database.clear_cache"),
|
||||
):
|
||||
response = authenticated_client.post(
|
||||
reverse(
|
||||
@@ -4453,7 +4450,6 @@ class TestAttackPathsScanViewSet:
|
||||
"truncated": False,
|
||||
},
|
||||
),
|
||||
patch("api.v1.views.graph_database.clear_cache"),
|
||||
patch(
|
||||
"api.v1.views.graph_database.get_database_name", return_value="db-test"
|
||||
),
|
||||
@@ -4508,7 +4504,6 @@ class TestAttackPathsScanViewSet:
|
||||
"truncated": False,
|
||||
},
|
||||
),
|
||||
patch("api.v1.views.graph_database.clear_cache"),
|
||||
patch(
|
||||
"api.v1.views.graph_database.get_database_name", return_value="db-test"
|
||||
),
|
||||
@@ -4588,7 +4583,6 @@ class TestAttackPathsScanViewSet:
|
||||
"truncated": False,
|
||||
},
|
||||
),
|
||||
patch("api.v1.views.graph_database.clear_cache"),
|
||||
):
|
||||
response = authenticated_client.post(
|
||||
reverse(
|
||||
@@ -4654,7 +4648,6 @@ class TestAttackPathsScanViewSet:
|
||||
"api.v1.views.graph_database.get_database_name",
|
||||
return_value="db-test",
|
||||
),
|
||||
patch("api.v1.views.graph_database.clear_cache"),
|
||||
):
|
||||
response = authenticated_client.post(
|
||||
reverse(
|
||||
@@ -4711,7 +4704,6 @@ class TestAttackPathsScanViewSet:
|
||||
"api.v1.views.graph_database.get_database_name",
|
||||
return_value="db-test",
|
||||
),
|
||||
patch("api.v1.views.graph_database.clear_cache"),
|
||||
):
|
||||
response = authenticated_client.post(
|
||||
reverse(
|
||||
@@ -4758,7 +4750,6 @@ class TestAttackPathsScanViewSet:
|
||||
"api.v1.views.graph_database.get_database_name",
|
||||
return_value="db-test",
|
||||
),
|
||||
patch("api.v1.views.graph_database.clear_cache"),
|
||||
):
|
||||
response = authenticated_client.post(
|
||||
reverse(
|
||||
@@ -5109,9 +5100,6 @@ class TestAttackPathsScanViewSet:
|
||||
"api.v1.views.graph_database.get_database_name",
|
||||
return_value="db-test",
|
||||
),
|
||||
patch(
|
||||
"api.v1.views.graph_database.clear_cache",
|
||||
),
|
||||
):
|
||||
for i in range(11):
|
||||
response = authenticated_client.post(
|
||||
|
||||
@@ -2628,7 +2628,6 @@ class AttackPathsScanViewSet(BaseRLSViewSet):
|
||||
provider_id,
|
||||
)
|
||||
query_duration = time.monotonic() - start
|
||||
graph_database.clear_cache(database_name)
|
||||
|
||||
result_nodes = len(graph.get("nodes", []))
|
||||
result_relationships = len(graph.get("relationships", []))
|
||||
@@ -2696,7 +2695,6 @@ class AttackPathsScanViewSet(BaseRLSViewSet):
|
||||
provider_id,
|
||||
)
|
||||
query_duration = time.monotonic() - start
|
||||
graph_database.clear_cache(database_name)
|
||||
|
||||
query_length = len(serializer.validated_data["query"])
|
||||
result_nodes = len(graph.get("nodes", []))
|
||||
|
||||
12
poetry.lock
generated
12
poetry.lock
generated
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 2.2.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "about-time"
|
||||
@@ -4444,14 +4444,14 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pre-commit"
|
||||
version = "4.5.1"
|
||||
version = "4.2.0"
|
||||
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||
optional = false
|
||||
python-versions = ">=3.10"
|
||||
python-versions = ">=3.9"
|
||||
groups = ["dev"]
|
||||
files = [
|
||||
{file = "pre_commit-4.5.1-py2.py3-none-any.whl", hash = "sha256:3b3afd891e97337708c1674210f8eba659b52a38ea5f822ff142d10786221f77"},
|
||||
{file = "pre_commit-4.5.1.tar.gz", hash = "sha256:eb545fcff725875197837263e977ea257a402056661f09dae08e4b149b030a61"},
|
||||
{file = "pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd"},
|
||||
{file = "pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@@ -6743,4 +6743,4 @@ files = [
|
||||
[metadata]
|
||||
lock-version = "2.1"
|
||||
python-versions = ">=3.10,<3.13"
|
||||
content-hash = "442dc9728a450d6af769362abba1f7221e3aa6c615fc6e61d11c15b1f5a43768"
|
||||
content-hash = "91739ee5e383337160f9f08b76944ab4e8629c94084c8a9d115246862557f7c5"
|
||||
|
||||
@@ -29,6 +29,8 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
|
||||
- `return` statements in `finally` blocks replaced across IAM, Organizations, GCP provider, and custom checks metadata to stop silently swallowing exceptions [(#10102)](https://github.com/prowler-cloud/prowler/pull/10102)
|
||||
- `JiraConnection` now includes issue types per project fetched during `test_connection`, fixing `JiraInvalidIssueTypeError` on non-English Jira instances [(#10534)](https://github.com/prowler-cloud/prowler/pull/10534)
|
||||
- `--list-checks` and `--list-checks-json` now include `threat-detection` category checks in their output [(#10578)](https://github.com/prowler-cloud/prowler/pull/10578)
|
||||
- Missing `__init__.py` in `codebuild_project_uses_allowed_github_organizations` check preventing discovery by `--list-checks` [(#10584)](https://github.com/prowler-cloud/prowler/pull/10584)
|
||||
|
||||
### 🔐 Security
|
||||
|
||||
|
||||
@@ -271,6 +271,8 @@ def prowler():
|
||||
categories=categories,
|
||||
resource_groups=resource_groups,
|
||||
provider=provider,
|
||||
list_checks=getattr(args, "list_checks", False)
|
||||
or getattr(args, "list_checks_json", False),
|
||||
)
|
||||
|
||||
# if --list-checks-json, dump a json file and exit
|
||||
|
||||
@@ -20,6 +20,7 @@ def load_checks_to_execute(
|
||||
compliance_frameworks: list = None,
|
||||
categories: set = None,
|
||||
resource_groups: set = None,
|
||||
list_checks: bool = False,
|
||||
) -> set:
|
||||
"""Generate the list of checks to execute based on the cloud provider and the input arguments given"""
|
||||
try:
|
||||
@@ -209,7 +210,12 @@ def load_checks_to_execute(
|
||||
):
|
||||
checks_to_execute.add(check_name)
|
||||
# Only execute threat detection checks if threat-detection category is set
|
||||
if (not categories or "threat-detection" not in categories) and not check_list:
|
||||
# Skip this exclusion when listing checks (--list-checks or --list-checks-json)
|
||||
if (
|
||||
(not categories or "threat-detection" not in categories)
|
||||
and not check_list
|
||||
and not list_checks
|
||||
):
|
||||
for threat_detection_check in check_categories.get("threat-detection", []):
|
||||
checks_to_execute.discard(threat_detection_check)
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ mock = "5.2.0"
|
||||
moto = {extras = ["all"], version = "5.1.11"}
|
||||
openapi-schema-validator = "0.6.3"
|
||||
openapi-spec-validator = "0.7.1"
|
||||
pre-commit = "4.5.1"
|
||||
pre-commit = "4.2.0"
|
||||
pylint = "3.3.4"
|
||||
pytest = "8.3.5"
|
||||
pytest-cov = "6.0.0"
|
||||
|
||||
@@ -629,3 +629,49 @@ class TestCheckLoader:
|
||||
provider=self.provider,
|
||||
)
|
||||
assert exc_info.value.code == 1
|
||||
|
||||
def test_list_checks_includes_threat_detection(self):
|
||||
"""Test that list_checks=True includes threat-detection checks (fixes #10576)"""
|
||||
bulk_checks_metadata = {
|
||||
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata(),
|
||||
CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME: self.get_threat_detection_check_metadata(),
|
||||
}
|
||||
|
||||
result = load_checks_to_execute(
|
||||
bulk_checks_metadata=bulk_checks_metadata,
|
||||
provider=self.provider,
|
||||
list_checks=True,
|
||||
)
|
||||
assert CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME in result
|
||||
assert S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME in result
|
||||
|
||||
def test_list_checks_with_service_includes_threat_detection(self):
|
||||
"""Test that list_checks=True with service filter includes threat-detection checks (fixes #10576)"""
|
||||
bulk_checks_metadata = {
|
||||
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata(),
|
||||
CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME: self.get_threat_detection_check_metadata(),
|
||||
}
|
||||
service_list = ["cloudtrail"]
|
||||
|
||||
result = load_checks_to_execute(
|
||||
bulk_checks_metadata=bulk_checks_metadata,
|
||||
service_list=service_list,
|
||||
provider=self.provider,
|
||||
list_checks=True,
|
||||
)
|
||||
assert CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME in result
|
||||
assert S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME not in result
|
||||
|
||||
def test_scan_still_excludes_threat_detection_by_default(self):
|
||||
"""Test that without list_checks, threat-detection checks are still excluded"""
|
||||
bulk_checks_metadata = {
|
||||
S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME: self.get_custom_check_s3_metadata(),
|
||||
CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME: self.get_threat_detection_check_metadata(),
|
||||
}
|
||||
|
||||
result = load_checks_to_execute(
|
||||
bulk_checks_metadata=bulk_checks_metadata,
|
||||
provider=self.provider,
|
||||
)
|
||||
assert CLOUDTRAIL_THREAT_DETECTION_ENUMERATION_NAME not in result
|
||||
assert S3_BUCKET_LEVEL_PUBLIC_ACCESS_BLOCK_NAME in result
|
||||
|
||||
Reference in New Issue
Block a user