mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-08 13:11:52 +00:00
0610866b73
Co-authored-by: Pepe Fagoaga <pepe@prowler.com>
125 lines
4.9 KiB
Python
125 lines
4.9 KiB
Python
"""End-to-end tests that exercise the real ``load_and_validate_config_file``
|
|
through a temp YAML file. Anything that breaks here would break the actual
|
|
``prowler aws -c …`` code path."""
|
|
|
|
import logging
|
|
import os
|
|
import pathlib
|
|
from typing import Callable
|
|
|
|
import pytest
|
|
|
|
from prowler.config.config import load_and_validate_config_file
|
|
|
|
|
|
@pytest.fixture
|
|
def write_config(tmp_path: pathlib.Path) -> Callable[[str], str]:
|
|
def _write(content: str) -> str:
|
|
path = tmp_path / "config.yaml"
|
|
path.write_text(content)
|
|
return str(path)
|
|
|
|
return _write
|
|
|
|
|
|
class Test_Loader_With_Schema_Integration:
|
|
def test_shipped_default_config_loads_without_warnings(self, caplog):
|
|
"""The default ``prowler/config/config.yaml`` must round-trip every
|
|
provider WITHOUT emitting any schema warnings. If this fails,
|
|
someone added a key to the YAML without updating the schema."""
|
|
repo_root = pathlib.Path(os.path.dirname(os.path.realpath(__file__))).parents[2]
|
|
shipped = repo_root / "prowler" / "config" / "config.yaml"
|
|
with caplog.at_level(logging.WARNING, logger="prowler"):
|
|
for provider in [
|
|
"aws",
|
|
"azure",
|
|
"gcp",
|
|
"kubernetes",
|
|
"m365",
|
|
"github",
|
|
"mongodbatlas",
|
|
"cloudflare",
|
|
"vercel",
|
|
]:
|
|
cfg = load_and_validate_config_file(provider, str(shipped))
|
|
# Provider always exists in the shipped file → non-empty.
|
|
assert cfg, f"{provider} returned an empty config"
|
|
|
|
offending = [
|
|
r.getMessage()
|
|
for r in caplog.records
|
|
if "prowler.config[" in r.getMessage()
|
|
]
|
|
assert not offending, (
|
|
"Shipped config.yaml triggered schema warnings — schema or YAML out of sync:\n"
|
|
+ "\n".join(offending)
|
|
)
|
|
|
|
def test_user_config_with_bad_threshold_falls_back(self, write_config, caplog):
|
|
path = write_config(
|
|
"aws:\n"
|
|
" threat_detection_privilege_escalation_threshold: 5.0\n"
|
|
" lambda_min_azs: 2\n"
|
|
)
|
|
with caplog.at_level(logging.WARNING, logger="prowler"):
|
|
cfg = load_and_validate_config_file("aws", path)
|
|
assert cfg == {"lambda_min_azs": 2}
|
|
assert any(
|
|
"threat_detection_privilege_escalation_threshold" in r.getMessage()
|
|
for r in caplog.records
|
|
)
|
|
|
|
def test_old_format_config_still_works(self, write_config):
|
|
# Old format = flat keys, no provider header.
|
|
path = write_config(
|
|
"max_ec2_instance_age_in_days: 90\n"
|
|
"ecr_repository_vulnerability_minimum_severity: HIGH\n"
|
|
)
|
|
cfg = load_and_validate_config_file("aws", path)
|
|
assert cfg == {
|
|
"max_ec2_instance_age_in_days": 90,
|
|
"ecr_repository_vulnerability_minimum_severity": "HIGH",
|
|
}
|
|
|
|
def test_unknown_keys_pass_through_via_loader(self, write_config):
|
|
path = write_config(
|
|
"aws:\n" " third_party_plugin_setting: hello\n" " lambda_min_azs: 2\n"
|
|
)
|
|
cfg = load_and_validate_config_file("aws", path)
|
|
assert cfg == {
|
|
"third_party_plugin_setting": "hello",
|
|
"lambda_min_azs": 2,
|
|
}
|
|
|
|
def test_quoted_numeric_is_coerced_via_loader(self, write_config):
|
|
# YAML quotes the number: ``"180"`` arrives as a Python str.
|
|
# The schema must coerce it to int so downstream comparisons work.
|
|
path = write_config('aws:\n max_ec2_instance_age_in_days: "180"\n')
|
|
cfg = load_and_validate_config_file("aws", path)
|
|
assert cfg == {"max_ec2_instance_age_in_days": 180}
|
|
assert isinstance(cfg["max_ec2_instance_age_in_days"], int)
|
|
|
|
def test_invalid_yaml_shape_list_as_string_drops_key(self, write_config, caplog):
|
|
path = write_config(
|
|
"aws:\n"
|
|
" disallowed_regions: me-south-1\n" # forgot list dashes
|
|
" lambda_min_azs: 2\n"
|
|
)
|
|
with caplog.at_level(logging.WARNING, logger="prowler"):
|
|
cfg = load_and_validate_config_file("aws", path)
|
|
assert cfg == {"lambda_min_azs": 2}
|
|
assert any("disallowed_regions" in r.getMessage() for r in caplog.records)
|
|
|
|
def test_other_providers_unaffected_by_aws_block(self, write_config):
|
|
path = write_config(
|
|
"aws:\n max_ec2_instance_age_in_days: 90\n" "gcp:\n mig_min_zones: 5\n"
|
|
)
|
|
assert load_and_validate_config_file("aws", path) == {
|
|
"max_ec2_instance_age_in_days": 90
|
|
}
|
|
assert load_and_validate_config_file("gcp", path) == {"mig_min_zones": 5}
|
|
|
|
def test_missing_provider_block_returns_empty(self, write_config):
|
|
path = write_config("aws:\n max_ec2_instance_age_in_days: 90\n")
|
|
assert load_and_validate_config_file("azure", path) == {}
|