mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-04 02:04:06 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e5d2053ee | ||
|
|
83caa89d9f |
@@ -0,0 +1 @@
|
||||
Zones without a challenge passage TTL are reported as non-compliant by `zone_challenge_passage_configured`
|
||||
+15
-9
@@ -29,17 +29,23 @@ class zone_challenge_passage_configured(Check):
|
||||
metadata=self.metadata(),
|
||||
resource=zone,
|
||||
)
|
||||
# API returns seconds, convert to minutes
|
||||
challenge_ttl_minutes = zone.settings.challenge_ttl // 60
|
||||
|
||||
if min_minutes <= challenge_ttl_minutes <= max_minutes:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Challenge Passage is set to {challenge_ttl_minutes} minutes for zone {zone.name}."
|
||||
else:
|
||||
challenge_ttl = zone.settings.challenge_ttl
|
||||
if challenge_ttl is None:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Challenge Passage is set to {challenge_ttl_minutes} minutes for zone {zone.name} "
|
||||
f"(recommended: between {min_minutes} and {max_minutes} minutes)."
|
||||
f"Challenge Passage is not configured for zone {zone.name}."
|
||||
)
|
||||
else:
|
||||
# API returns seconds, convert to minutes
|
||||
challenge_ttl_minutes = challenge_ttl // 60
|
||||
if min_minutes <= challenge_ttl_minutes <= max_minutes:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Challenge Passage is set to {challenge_ttl_minutes} minutes for zone {zone.name}."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = (
|
||||
f"Challenge Passage is set to {challenge_ttl_minutes} minutes for zone {zone.name} "
|
||||
f"(recommended: between {min_minutes} and {max_minutes} minutes)."
|
||||
)
|
||||
findings.append(report)
|
||||
return findings
|
||||
|
||||
@@ -9,7 +9,6 @@ from prowler.providers.cloudflare.exceptions.exceptions import (
|
||||
CloudflareInvalidAPIKeyError,
|
||||
CloudflareInvalidAPITokenError,
|
||||
CloudflareNoAccountsError,
|
||||
CloudflareUserTokenRequiredError,
|
||||
)
|
||||
from prowler.providers.cloudflare.models import (
|
||||
CloudflareAccount,
|
||||
@@ -308,8 +307,8 @@ class TestCloudflareValidateCredentials:
|
||||
CloudflareProvider.validate_credentials(session)
|
||||
mock_client.user.get.assert_called_once()
|
||||
|
||||
def test_validate_credentials_user_token_required(self):
|
||||
"""Test that user token required error is raised for Account tokens."""
|
||||
def test_validate_credentials_account_token_without_accounts(self):
|
||||
"""Test that account tokens fall back to account discovery."""
|
||||
mock_client = MagicMock()
|
||||
# Simulate error code 9109 - user-level authentication required
|
||||
from cloudflare._exceptions import PermissionDeniedError
|
||||
@@ -319,6 +318,7 @@ class TestCloudflareValidateCredentials:
|
||||
response=MagicMock(status_code=403),
|
||||
body=None,
|
||||
)
|
||||
mock_client.accounts.list.return_value = iter([])
|
||||
|
||||
session = CloudflareSession(
|
||||
client=mock_client,
|
||||
@@ -327,8 +327,10 @@ class TestCloudflareValidateCredentials:
|
||||
api_email=None,
|
||||
)
|
||||
|
||||
with pytest.raises(CloudflareUserTokenRequiredError):
|
||||
with pytest.raises(CloudflareNoAccountsError):
|
||||
CloudflareProvider.validate_credentials(session)
|
||||
mock_client.user.get.assert_called_once()
|
||||
mock_client.accounts.list.assert_called_once()
|
||||
|
||||
def test_validate_credentials_invalid_api_token(self):
|
||||
"""Test that invalid API token error is raised."""
|
||||
@@ -487,8 +489,8 @@ class TestCloudflareTestConnection:
|
||||
assert connection.is_connected is False
|
||||
assert isinstance(connection.error, CloudflareInvalidAPITokenError)
|
||||
|
||||
def test_test_connection_user_token_required(self):
|
||||
"""Test that user token required error is properly returned."""
|
||||
def test_test_connection_account_token_without_accounts(self):
|
||||
"""Test that account tokens without accessible accounts return an error."""
|
||||
mock_client = MagicMock()
|
||||
from cloudflare._exceptions import PermissionDeniedError
|
||||
|
||||
@@ -497,6 +499,7 @@ class TestCloudflareTestConnection:
|
||||
response=MagicMock(status_code=403),
|
||||
body=None,
|
||||
)
|
||||
mock_client.accounts.list.return_value = iter([])
|
||||
|
||||
with patch(
|
||||
"prowler.providers.cloudflare.cloudflare_provider.CloudflareProvider.setup_session",
|
||||
@@ -512,9 +515,10 @@ class TestCloudflareTestConnection:
|
||||
)
|
||||
|
||||
assert connection.is_connected is False
|
||||
assert isinstance(connection.error, CloudflareUserTokenRequiredError)
|
||||
# Verify the error message is user-friendly
|
||||
assert "User-level API token required" in str(connection.error)
|
||||
assert isinstance(connection.error, CloudflareNoAccountsError)
|
||||
assert "No Cloudflare accounts found" in str(connection.error)
|
||||
mock_client.user.get.assert_called_once()
|
||||
mock_client.accounts.list.assert_called_once()
|
||||
|
||||
def test_test_connection_invalid_api_key(self):
|
||||
"""Test that invalid API key error is properly returned."""
|
||||
|
||||
+4
@@ -240,3 +240,7 @@ class Test_zone_challenge_passage_configured:
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Challenge Passage is not configured for zone {ZONE_NAME}."
|
||||
)
|
||||
|
||||
+4
-2
@@ -102,8 +102,10 @@ class Test_zone_development_mode_disabled:
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert "Development mode is enabled" in result[0].status_extended
|
||||
assert "bypasses" in result[0].status_extended
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Development mode is enabled for zone {ZONE_NAME}."
|
||||
)
|
||||
|
||||
def test_zone_development_mode_none(self):
|
||||
zone_client = mock.MagicMock
|
||||
|
||||
Reference in New Issue
Block a user