mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-29 23:04:23 +00:00
feat(api): drive provider-type filters from SDK-available providers
- Replace the static provider enum in filters with the SDK provider list - Cache the provider-type choices for hot list endpoints - Drop the dead provider enum filter override
This commit is contained in:
1 parent
f14778438e
commit
37323e691a
2 files changed
+58
-28
No files matched your search
@@ -1,4 +1,5 @@
|
||||
from datetime import date, datetime, timedelta, timezone
|
||||
from functools import lru_cache
|
||||
|
||||
from dateutil.parser import parse
|
||||
from django.conf import settings
|
||||
@@ -19,7 +20,6 @@ from api.constants import SEVERITY_ORDER
|
||||
from api.db_utils import (
|
||||
FindingDeltaEnumField,
|
||||
InvitationStateEnumField,
|
||||
ProviderEnumField,
|
||||
SeverityEnumField,
|
||||
StatusEnumField,
|
||||
)
|
||||
@@ -68,6 +68,18 @@ from api.uuid_utils import (
|
||||
uuid7_start,
|
||||
)
|
||||
from api.v1.serializers import TaskBase
|
||||
from prowler.providers.common.provider import Provider as SDKProvider
|
||||
|
||||
|
||||
@lru_cache(maxsize=1)
|
||||
def get_provider_type_choices():
|
||||
"""Provider-type filter choices driven by the SDK's available providers
|
||||
instead of a static enum, so filtering covers external providers too.
|
||||
|
||||
Cached because the installed providers are fixed for the process lifetime
|
||||
and provider-type filters live on hot list endpoints.
|
||||
"""
|
||||
return [(name, name) for name in SDKProvider.get_available_providers()]
|
||||
|
||||
|
||||
class CustomDjangoFilterBackend(DjangoFilterBackend):
|
||||
@@ -109,11 +121,11 @@ class BaseProviderFilter(FilterSet):
|
||||
provider_id = UUIDFilter(field_name="provider__id", lookup_expr="exact")
|
||||
provider_id__in = UUIDInFilter(field_name="provider__id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
field_name="provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
field_name="provider__provider",
|
||||
choices=Provider.ProviderChoices.choices,
|
||||
choices=get_provider_type_choices(),
|
||||
lookup_expr="in",
|
||||
)
|
||||
|
||||
@@ -133,11 +145,11 @@ class BaseScanProviderFilter(FilterSet):
|
||||
provider_id = UUIDFilter(field_name="scan__provider__id", lookup_expr="exact")
|
||||
provider_id__in = UUIDInFilter(field_name="scan__provider__id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
field_name="scan__provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="scan__provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
field_name="scan__provider__provider",
|
||||
choices=Provider.ProviderChoices.choices,
|
||||
choices=get_provider_type_choices(),
|
||||
lookup_expr="in",
|
||||
)
|
||||
|
||||
@@ -155,10 +167,10 @@ class CommonFindingFilters(FilterSet):
|
||||
provider_id = UUIDFilter(field_name="scan__provider__id", lookup_expr="exact")
|
||||
provider_id__in = UUIDInFilter(field_name="scan__provider__id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
choices=Provider.ProviderChoices.choices, field_name="scan__provider__provider"
|
||||
choices=get_provider_type_choices(), field_name="scan__provider__provider"
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
choices=Provider.ProviderChoices.choices, field_name="scan__provider__provider"
|
||||
choices=get_provider_type_choices(), field_name="scan__provider__provider"
|
||||
)
|
||||
provider_uid = CharFilter(field_name="scan__provider__uid", lookup_expr="exact")
|
||||
provider_uid__in = CharInFilter(field_name="scan__provider__uid", lookup_expr="in")
|
||||
@@ -356,18 +368,18 @@ class ProviderFilter(FilterSet):
|
||||
included. Providers with no connection attempt (status is null) are
|
||||
excluded from this filter."""
|
||||
)
|
||||
provider = ChoiceFilter(choices=Provider.ProviderChoices.choices)
|
||||
provider = ChoiceFilter(choices=get_provider_type_choices())
|
||||
provider__in = ChoiceInFilter(
|
||||
field_name="provider",
|
||||
choices=Provider.ProviderChoices.choices,
|
||||
choices=get_provider_type_choices(),
|
||||
lookup_expr="in",
|
||||
)
|
||||
provider_type = ChoiceFilter(
|
||||
choices=Provider.ProviderChoices.choices, field_name="provider"
|
||||
choices=get_provider_type_choices(), field_name="provider"
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
field_name="provider",
|
||||
choices=Provider.ProviderChoices.choices,
|
||||
choices=get_provider_type_choices(),
|
||||
lookup_expr="in",
|
||||
)
|
||||
|
||||
@@ -381,19 +393,14 @@ class ProviderFilter(FilterSet):
|
||||
"inserted_at": ["gte", "lte"],
|
||||
"updated_at": ["gte", "lte"],
|
||||
}
|
||||
filter_overrides = {
|
||||
ProviderEnumField: {
|
||||
"filter_class": CharFilter,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class ProviderRelationshipFilterSet(FilterSet):
|
||||
provider_type = ChoiceFilter(
|
||||
choices=Provider.ProviderChoices.choices, field_name="provider__provider"
|
||||
choices=get_provider_type_choices(), field_name="provider__provider"
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
choices=Provider.ProviderChoices.choices, field_name="provider__provider"
|
||||
choices=get_provider_type_choices(), field_name="provider__provider"
|
||||
)
|
||||
provider_uid = CharFilter(field_name="provider__uid", lookup_expr="exact")
|
||||
provider_uid__in = CharInFilter(field_name="provider__uid", lookup_expr="in")
|
||||
@@ -998,7 +1005,7 @@ class FindingGroupSummaryFilter(_CheckTitleToCheckIdMixin, FilterSet):
|
||||
provider_id = UUIDFilter(field_name="provider_id", lookup_expr="exact")
|
||||
provider_id__in = UUIDInFilter(field_name="provider_id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
field_name="provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
provider_type__in = CharInFilter(field_name="provider__provider", lookup_expr="in")
|
||||
|
||||
@@ -1098,7 +1105,7 @@ class LatestFindingGroupSummaryFilter(_CheckTitleToCheckIdMixin, FilterSet):
|
||||
provider_id = UUIDFilter(field_name="provider_id", lookup_expr="exact")
|
||||
provider_id__in = UUIDInFilter(field_name="provider_id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
field_name="provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
provider_type__in = CharInFilter(field_name="provider__provider", lookup_expr="in")
|
||||
|
||||
@@ -1301,10 +1308,10 @@ class ScanSummaryFilter(FilterSet):
|
||||
provider_id = UUIDFilter(field_name="scan__provider__id", lookup_expr="exact")
|
||||
provider_id__in = UUIDInFilter(field_name="scan__provider__id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
field_name="scan__provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="scan__provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
field_name="scan__provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="scan__provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
region = CharFilter(field_name="region")
|
||||
|
||||
@@ -1324,10 +1331,10 @@ class DailySeveritySummaryFilter(FilterSet):
|
||||
provider_id = UUIDFilter(field_name="provider_id", lookup_expr="exact")
|
||||
provider_id__in = UUIDInFilter(field_name="provider_id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
field_name="provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
field_name="provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
date_from = DateFilter(method="filter_noop")
|
||||
date_to = DateFilter(method="filter_noop")
|
||||
@@ -1578,11 +1585,11 @@ class ThreatScoreSnapshotFilter(FilterSet):
|
||||
provider_id = UUIDFilter(field_name="provider__id", lookup_expr="exact")
|
||||
provider_id__in = UUIDInFilter(field_name="provider__id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
field_name="provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
field_name="provider__provider",
|
||||
choices=Provider.ProviderChoices.choices,
|
||||
choices=get_provider_type_choices(),
|
||||
lookup_expr="in",
|
||||
)
|
||||
compliance_id = CharFilter(field_name="compliance_id", lookup_expr="exact")
|
||||
@@ -1621,11 +1628,11 @@ class ResourceGroupOverviewFilter(FilterSet):
|
||||
provider_id = UUIDFilter(field_name="scan__provider__id", lookup_expr="exact")
|
||||
provider_id__in = UUIDInFilter(field_name="scan__provider__id", lookup_expr="in")
|
||||
provider_type = ChoiceFilter(
|
||||
field_name="scan__provider__provider", choices=Provider.ProviderChoices.choices
|
||||
field_name="scan__provider__provider", choices=get_provider_type_choices()
|
||||
)
|
||||
provider_type__in = ChoiceInFilter(
|
||||
field_name="scan__provider__provider",
|
||||
choices=Provider.ProviderChoices.choices,
|
||||
choices=get_provider_type_choices(),
|
||||
lookup_expr="in",
|
||||
)
|
||||
resource_group = CharFilter(field_name="resource_group", lookup_expr="exact")
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
from api.filters import get_provider_type_choices
|
||||
from prowler.providers.common.provider import Provider as SDKProvider
|
||||
|
||||
|
||||
class TestProviderTypeChoices:
|
||||
"""Provider-type filter choices are driven by the SDK's available providers
|
||||
so filtering covers external providers, not just a static enum."""
|
||||
|
||||
def test_choices_track_sdk_available_providers(self):
|
||||
available = set(SDKProvider.get_available_providers())
|
||||
choices = get_provider_type_choices()
|
||||
|
||||
assert {value for value, _ in choices} == available
|
||||
|
||||
def test_choices_include_provider_absent_from_legacy_enum(self):
|
||||
from api.models import Provider
|
||||
|
||||
legacy = {value for value, _ in Provider.ProviderChoices.choices}
|
||||
choice_values = {value for value, _ in get_provider_type_choices()}
|
||||
|
||||
# `llm` is exposed by the SDK but is not part of the legacy static enum.
|
||||
assert "llm" in choice_values
|
||||
assert "llm" not in legacy
|
||||
Reference in new issue
Block a user