mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-02-09 15:10:36 +00:00
feat: max retries and avoid conflicting env vars
The Cloudflare SDK automatically reads credentials from environment variables, which causes conflicts. In that case, we prioritize the recommended token auth now.
This commit is contained in:
@@ -592,6 +592,9 @@ mongodbatlas:
|
||||
|
||||
# Cloudflare Configuration
|
||||
cloudflare:
|
||||
# Maximum number of retries for API requests (default is 2)
|
||||
# Set to 0 to disable retries
|
||||
max_retries: 3
|
||||
# zone_min_tls_version_secure --> Recommended minimum TLS version
|
||||
min_tls_version: "1.2"
|
||||
# zone_https_redirect_enabled --> Enforce HTTPS redirects
|
||||
|
||||
@@ -60,16 +60,6 @@ class CloudflareProvider(Provider):
|
||||
):
|
||||
logger.info("Instantiating Cloudflare provider...")
|
||||
|
||||
self._session = CloudflareProvider.setup_session(
|
||||
api_token=api_token,
|
||||
api_key=api_key,
|
||||
api_email=api_email,
|
||||
)
|
||||
|
||||
self._identity = CloudflareProvider.setup_identity(
|
||||
self._session, account_ids=account_ids
|
||||
)
|
||||
|
||||
if config_content:
|
||||
self._audit_config = config_content
|
||||
else:
|
||||
@@ -77,6 +67,19 @@ class CloudflareProvider(Provider):
|
||||
config_path = default_config_file_path
|
||||
self._audit_config = load_and_validate_config_file(self._type, config_path)
|
||||
|
||||
max_retries = self._audit_config.get("max_retries", 2)
|
||||
|
||||
self._session = CloudflareProvider.setup_session(
|
||||
api_token=api_token,
|
||||
api_key=api_key,
|
||||
api_email=api_email,
|
||||
max_retries=max_retries,
|
||||
)
|
||||
|
||||
self._identity = CloudflareProvider.setup_identity(
|
||||
self._session, account_ids=account_ids
|
||||
)
|
||||
|
||||
self._fixer_config = fixer_config
|
||||
|
||||
if mutelist_content:
|
||||
@@ -128,27 +131,53 @@ class CloudflareProvider(Provider):
|
||||
api_token: str = None,
|
||||
api_key: str = None,
|
||||
api_email: str = None,
|
||||
max_retries: int = 2,
|
||||
) -> CloudflareSession:
|
||||
"""Initialize Cloudflare SDK client."""
|
||||
"""Initialize Cloudflare SDK client.
|
||||
|
||||
Args:
|
||||
api_token: Cloudflare API token.
|
||||
api_key: Cloudflare API key.
|
||||
api_email: Cloudflare API email.
|
||||
max_retries: Maximum number of retries for API requests (default is 2).
|
||||
"""
|
||||
token = api_token or os.environ.get("CLOUDFLARE_API_TOKEN", "")
|
||||
key = api_key or os.environ.get("CLOUDFLARE_API_KEY", "")
|
||||
email = api_email or os.environ.get("CLOUDFLARE_API_EMAIL", "")
|
||||
|
||||
if not token and not (key and email):
|
||||
raise CloudflareCredentialsError(
|
||||
file=os.path.basename(__file__),
|
||||
message="Cloudflare credentials not found. Provide --cloudflare-api-token or --cloudflare-api-key and --cloudflare-api-email.",
|
||||
# Warn if both auth methods are set, use API Token (recommended)
|
||||
if token and key and email:
|
||||
logger.error(
|
||||
"Both API Token and API Key + Email credentials are set. "
|
||||
"Using API Token (recommended). "
|
||||
"To avoid this error, unset CLOUDFLARE_API_KEY and CLOUDFLARE_API_EMAIL, or CLOUDFLARE_API_TOKEN. "
|
||||
"Note: The Cloudflare SDK automatically reads credentials from environment variables, which causes conflicts."
|
||||
)
|
||||
|
||||
# The Cloudflare SDK reads credentials from environment variables automatically.
|
||||
# To ensure we use only the selected auth method, temporarily unset env vars.
|
||||
env_token = os.environ.pop("CLOUDFLARE_API_TOKEN", None)
|
||||
env_key = os.environ.pop("CLOUDFLARE_API_KEY", None)
|
||||
env_email = os.environ.pop("CLOUDFLARE_API_EMAIL", None)
|
||||
|
||||
try:
|
||||
if token:
|
||||
client = Cloudflare(api_token=token)
|
||||
client = Cloudflare(api_token=token, max_retries=max_retries)
|
||||
elif key and email:
|
||||
client = Cloudflare(
|
||||
api_key=key, api_email=email, max_retries=max_retries
|
||||
)
|
||||
else:
|
||||
client = Cloudflare(api_email=email, api_key=key)
|
||||
raise CloudflareCredentialsError(
|
||||
file=os.path.basename(__file__),
|
||||
message="Cloudflare credentials not found. Available authentication methods: "
|
||||
"(1) API Token: use --cloudflare-api-token or set CLOUDFLARE_API_TOKEN environment variable; "
|
||||
"(2) API Key + Email: use --cloudflare-api-key and --cloudflare-api-email or set CLOUDFLARE_API_KEY and CLOUDFLARE_API_EMAIL environment variables.",
|
||||
)
|
||||
|
||||
return CloudflareSession(
|
||||
client=client,
|
||||
api_token=token or None,
|
||||
api_token=client.api_token,
|
||||
api_key=key or None,
|
||||
api_email=email or None,
|
||||
)
|
||||
@@ -160,6 +189,14 @@ class CloudflareProvider(Provider):
|
||||
file=os.path.basename(__file__),
|
||||
original_exception=error,
|
||||
)
|
||||
finally:
|
||||
# Restore environment variables
|
||||
if env_token:
|
||||
os.environ["CLOUDFLARE_API_TOKEN"] = env_token
|
||||
if env_key:
|
||||
os.environ["CLOUDFLARE_API_KEY"] = env_key
|
||||
if env_email:
|
||||
os.environ["CLOUDFLARE_API_EMAIL"] = env_email
|
||||
|
||||
@staticmethod
|
||||
def setup_identity(
|
||||
|
||||
@@ -34,6 +34,10 @@ class CloudflareBaseException(ProwlerException):
|
||||
"message": "Cloudflare API call failed",
|
||||
"remediation": "Inspect the API response details and permissions for the failing request.",
|
||||
},
|
||||
(9007, "CloudflareCredentialsConflictError"): {
|
||||
"message": "Conflicting Cloudflare credentials provided",
|
||||
"remediation": "Use either API Token or API Key + Email, not both. Unset CLOUDFLARE_API_TOKEN or unset both CLOUDFLARE_API_KEY and CLOUDFLARE_API_EMAIL.",
|
||||
},
|
||||
}
|
||||
|
||||
def __init__(self, code, file=None, original_exception=None, message=None):
|
||||
@@ -111,3 +115,12 @@ class CloudflareAPIError(CloudflareBaseException):
|
||||
super().__init__(
|
||||
9006, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
|
||||
class CloudflareCredentialsConflictError(CloudflareBaseException):
|
||||
"""Exception for conflicting Cloudflare credentials."""
|
||||
|
||||
def __init__(self, file=None, original_exception=None, message=None):
|
||||
super().__init__(
|
||||
9007, file=file, original_exception=original_exception, message=message
|
||||
)
|
||||
|
||||
@@ -60,7 +60,7 @@ def validate_arguments(arguments) -> tuple[bool, str]:
|
||||
if not token and not (api_key and api_email):
|
||||
return (
|
||||
False,
|
||||
"Cloudflare provider requires --cloudflare-api-token or the combination of --cloudflare-api-key and --cloudflare-api-email (or matching environment variables).",
|
||||
"Cloudflare provider requires CLOUDFLARE_API_TOKEN (or --cloudflare-api-token) or the combination of CLOUDFLARE_API_KEY and CLOUDFLARE_API_EMAIL (or --cloudflare-api-key and --cloudflare-api-email).",
|
||||
)
|
||||
|
||||
return (True, "")
|
||||
|
||||
Reference in New Issue
Block a user