fix(sdk): exclude sdk_only providers from scan config schema (#12094)

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
This commit is contained in:
StylusFrost
2026-07-31 08:49:31 +02:00
committed by GitHub
co-authored by coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> CodeRabbit
parent 3dd6b29477
commit 9185b043da
4 changed files with 59 additions and 1 deletions
@@ -0,0 +1 @@
Scan configuration schema no longer exposes SDK/CLI-only providers such as `e2enetworks`; the aggregated schema served by `/scan-configurations/schema` now includes only app providers (`sdk_only = False`)
+11
View File
@@ -225,9 +225,20 @@ def _build_aggregated_schema() -> dict:
The output mirrors the layout of `prowler/config/config.yaml` (a mapping
keyed by provider type) and is what the UI consumes via `ajv`.
Only app-facing providers (`sdk_only = False`, see
`Provider.get_app_providers`) are included. SDK/CLI-only providers may
still have a schema registered in `SCHEMAS` so the CLI validates their
`config.yaml` (`load_and_validate_config_file` reads `SCHEMAS.get`), but
they must not surface in this app-facing schema.
"""
from prowler.providers.common.provider import Provider
app_providers = set(Provider.get_app_providers())
properties: dict[str, dict] = {}
for provider, schema_cls in SCHEMAS.items():
if provider not in app_providers:
continue
properties[provider] = schema_cls.model_json_schema()
return {
"$schema": "https://json-schema.org/draft/2020-12/schema",
+7 -1
View File
@@ -15,12 +15,18 @@ from prowler.config.scan_config_schema import SCAN_CONFIG_SCHEMA
from prowler.config.schema.aws import AWSProviderConfig
from prowler.config.schema.registry import SCHEMAS
from prowler.config.schema.validator import validate_provider_config
from prowler.providers.common.provider import Provider
EXCLUSION_FIELDS = ("excluded_checks", "excluded_services")
class Test_JSON_Schema_Exposes_Exclusion_Fields:
@pytest.mark.parametrize("provider", sorted(SCHEMAS))
# The aggregated schema is app-facing and only carries app providers
# (``sdk_only = False``); iterate exactly what it exposes so SDK/CLI-only
# providers (still in ``SCHEMAS`` for CLI validation) are not asserted here.
@pytest.mark.parametrize(
"provider", sorted(set(Provider.get_app_providers()) & set(SCHEMAS))
)
@pytest.mark.parametrize("field", EXCLUSION_FIELDS)
def test_field_shape(self, provider, field):
field_schema = SCAN_CONFIG_SCHEMA["properties"][provider]["properties"][field]
@@ -13,11 +13,15 @@ from unittest.mock import call, patch
import pytest
from prowler.config.scan_config_schema import (
SCAN_CONFIG_SCHEMA,
_build_aggregated_schema,
_get_provider_check_ids,
_get_provider_services,
validate_and_normalize_scan_config,
validate_scan_config,
)
from prowler.config.schema.registry import SCHEMAS
from prowler.providers.common.provider import Provider
@pytest.fixture(autouse=True)
@@ -391,3 +395,39 @@ class Test_Backward_Compatible_Wrapper:
"message": "Scan config must be a mapping with provider sections.",
}
]
class Test_Aggregated_Schema_Is_App_Facing:
"""``SCAN_CONFIG_SCHEMA`` is served by the app
(``/scan-configurations/schema``) and consumed by the UI editor, so it must
expose only app providers (``sdk_only = False``). SDK/CLI-only providers
must not leak into it, even when they have a config schema registered in
``SCHEMAS`` for CLI ``config.yaml`` validation."""
def test_sdk_only_provider_is_absent_from_schema(self):
# ``e2enetworks`` is ``sdk_only = True`` yet has a schema registered in
# ``SCHEMAS``; it must not surface in the app-facing aggregated schema.
assert "e2enetworks" not in SCAN_CONFIG_SCHEMA["properties"]
def test_schema_contains_only_app_providers(self):
app_providers = set(Provider.get_app_providers())
registered_app_providers = app_providers & set(SCHEMAS)
assert set(SCAN_CONFIG_SCHEMA["properties"]) == registered_app_providers
def test_app_provider_with_registered_schema_is_present(self):
assert "aws" in SCAN_CONFIG_SCHEMA["properties"]
def test_registry_still_registers_sdk_only_provider_for_cli(self):
# Guard against "fixing" the leak by dropping ``e2enetworks`` from
# ``SCHEMAS``: ``load_and_validate_config_file()`` relies on
# ``SCHEMAS.get(provider)`` and a missing schema silently disables
# ``config.yaml`` validation for that provider on the CLI.
assert "e2enetworks" in SCHEMAS
def test_build_filters_registry_by_app_providers(self):
# Deterministic mechanism check: only providers returned by
# ``get_app_providers()`` survive the aggregation, regardless of what
# ``SCHEMAS`` contains.
with patch.object(Provider, "get_app_providers", return_value=["aws"]):
schema = _build_aggregated_schema()
assert set(schema["properties"]) == {"aws"}