chore(config): add missing providers config (#11725)

This commit is contained in:
Pedro Martín
2026-06-30 11:32:47 +02:00
committed by GitHub
parent 4e7e2f7eab
commit 717d48b0e0
8 changed files with 283 additions and 0 deletions
+1
View File
@@ -26,6 +26,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
- Compliance frameworks contributed by several external packages under the same provider are now merged instead of overwritten, so every entry-point directory a provider contributes is discovered [(#11578)](https://github.com/prowler-cloud/prowler/pull/11578)
- Azure PostgreSQL flexible server collection no longer drops the remaining servers in a subscription when one server fails to collect; the `connection_throttle.enable` parameter (removed in PostgreSQL 16+) is treated as absent only when the Azure SDK reports it as not found, so unexpected lookup failures are not silently reported as throttling disabled [(#11595)](https://github.com/prowler-cloud/prowler/pull/11595)
- Azure `keyvault_logging_enabled` now accepts Key Vault diagnostic settings that enable the explicit `AuditEvent` category, avoiding false failures when Azure returns category-based logs without category groups [(#11660)](https://github.com/prowler-cloud/prowler/pull/11660)
- Okta, Alibaba Cloud and OpenStack scan-config sections are now validated against a registered schema instead of being silently accepted, so their configurable thresholds (session/idle timeouts, retention days, image-sharing and secret-scanning settings) log a warning and fall back to the built-in default whenever a value is out of range [(#11725)](https://github.com/prowler-cloud/prowler/pull/11725)
---
+44
View File
@@ -705,9 +705,53 @@ okta:
# 15 per DISA STIG V-273186 (OKTA-APP-000020); raise it only with an
# explicit risk acceptance.
okta_max_session_idle_minutes: 15
# okta.signon_global_session_lifetime_18h
# Maximum acceptable Global Session lifetime, in minutes. Defaults to
# 18h (1080); raise it only with an explicit risk acceptance.
okta_max_session_lifetime_minutes: 1080
# Okta Applications
# okta.application_admin_console_session_idle_timeout_15min
# Maximum acceptable Okta Admin Console app idle timeout, in minutes.
# Defaults to 15 per DISA STIG V-273187 (OKTA-APP-000025); raise it only
# with an explicit risk acceptance.
okta_admin_console_idle_timeout_max_minutes: 15
# Okta Users
# okta.user_inactivity_automation_35d_enabled
# Maximum number of days a user can stay inactive before the
# inactivity-automation check flags the org. Defaults to 35.
okta_user_inactivity_max_days: 35
# Okta Identity Providers
# okta.idp_smart_card_dod_approved_ca
# Extra regex patterns matched against a Smart Card IdP certificate issuer
# DN to recognise a DOD-approved CA, on top of the built-in `OU=DoD` /
# `OU=ECA` patterns.
okta_dod_approved_ca_issuer_patterns: []
alibabacloud:
# alibabacloud.cs_kubernetes_cluster_check_recent / cs_kubernetes_cluster_check_weekly
# Maximum number of days an ACK cluster can go without a security check
# before being flagged. Defaults to 7.
max_cluster_check_days: 7
# alibabacloud.ram_user_console_access_unused
# Days a RAM user's console access can stay unused before being flagged.
# Defaults to 90.
max_console_access_days: 90
# alibabacloud.sls_logstore_retention_period
# Minimum required SLS log store retention, in days. Defaults to 365.
min_log_retention_days: 365
# alibabacloud.rds_instance_sql_audit_retention
# Minimum required RDS SQL audit log retention, in days. Defaults to 180.
min_rds_audit_retention_days: 180
openstack:
# openstack.image_not_shared_with_multiple_projects
# Maximum number of accepted project members a shared image may have before
# being flagged. Defaults to 5.
image_sharing_threshold: 5
# openstack.<compute|blockstorage|objectstorage>_*_metadata_sensitive_data
# Regex patterns whose matches are excluded from detect-secrets scanning of
# resource metadata.
secrets_ignore_patterns: []
# Custom detect-secrets plugin configuration for metadata scanning. Each
# entry requires a `name`; entropy plugins also accept a `limit` (0..10).
detect_secrets_plugins: []
+54
View File
@@ -0,0 +1,54 @@
"""Alibaba Cloud provider config schema with safety bounds."""
from typing import Optional
from pydantic import Field
from prowler.config.schema.base import ProviderConfigBase
class AlibabaCloudProviderConfig(ProviderConfigBase):
"""Alibaba Cloud provider configuration schema.
Bounds the retention and staleness thresholds consumed by the Alibaba
Cloud checks. Every field is optional: when omitted (or dropped for being
out of range) the check falls back to its own default via
``audit_config.get(key, default)``.
"""
max_cluster_check_days: Optional[int] = Field(
default=None,
ge=1,
le=365,
description=(
"Maximum number of days an ACK cluster can go without a security "
"check before being flagged. Range: 1..365 (defaults to 7)."
),
)
max_console_access_days: Optional[int] = Field(
default=None,
ge=30,
le=180,
description=(
"Days a RAM user's console access can stay unused before being "
"flagged. Range: 30..180 (defaults to 90)."
),
)
min_log_retention_days: Optional[int] = Field(
default=None,
ge=1,
le=3650,
description=(
"Minimum required SLS log store retention, in days. Range: "
"1..3650 (defaults to 365)."
),
)
min_rds_audit_retention_days: Optional[int] = Field(
default=None,
ge=1,
le=3650,
description=(
"Minimum required RDS SQL audit log retention, in days. Range: "
"1..3650 (defaults to 180)."
),
)
+65
View File
@@ -0,0 +1,65 @@
"""Okta provider config schema with safety bounds."""
from typing import Optional
from pydantic import Field
from prowler.config.schema.base import ProviderConfigBase
class OktaProviderConfig(ProviderConfigBase):
"""Okta provider configuration schema.
Bounds the session, idle-timeout and inactivity thresholds consumed by
the Okta checks. Every field is optional: when omitted (or dropped for
being out of range) the check falls back to its own DISA STIG-derived
default via ``audit_config.get(key, default)``.
"""
okta_max_session_idle_minutes: Optional[int] = Field(
default=None,
ge=1,
le=1440,
description=(
"Maximum acceptable Global Session idle timeout, in minutes. "
"Range: 1..1440 (DISA STIG V-273186 recommends 15; raising it "
"weakens the idle-timeout control)."
),
)
okta_max_session_lifetime_minutes: Optional[int] = Field(
default=None,
ge=1,
le=43200,
description=(
"Maximum acceptable Global Session lifetime, in minutes. "
"Range: 1..43200 i.e. up to 30 days (DISA STIG recommends 18h = "
"1080; raising it weakens the session-lifetime control)."
),
)
okta_admin_console_idle_timeout_max_minutes: Optional[int] = Field(
default=None,
ge=1,
le=1440,
description=(
"Maximum acceptable Okta Admin Console app idle timeout, in "
"minutes. Range: 1..1440 (DISA STIG V-273187 recommends 15)."
),
)
okta_user_inactivity_max_days: Optional[int] = Field(
default=None,
ge=1,
le=3650,
description=(
"Maximum number of days a user can stay inactive before the "
"inactivity-automation check flags the org. Range: 1..3650 "
"(defaults to 35)."
),
)
okta_dod_approved_ca_issuer_patterns: Optional[list[str]] = Field(
default=None,
description=(
"Additional regex patterns matched against a Smart Card IdP "
"certificate issuer DN to recognise a DOD-approved CA. Extends "
"the built-in `OU=DoD` / `OU=ECA` patterns."
),
)
+40
View File
@@ -0,0 +1,40 @@
"""OpenStack provider config schema with safety bounds."""
from typing import Optional
from pydantic import Field
from prowler.config.schema.aws import _DetectSecretsPlugin
from prowler.config.schema.base import ProviderConfigBase
class OpenStackProviderConfig(ProviderConfigBase):
"""OpenStack provider configuration schema.
Bounds the image-sharing threshold and reuses the AWS secret-scanning
config models (``detect_secrets_plugins`` / ``secrets_ignore_patterns``)
consumed by the metadata sensitive-data checks. Every field is optional:
when omitted (or dropped for being out of range) the check falls back to
its own default via ``audit_config.get(key, default)``.
"""
image_sharing_threshold: Optional[int] = Field(
default=None,
ge=1,
le=1000,
description=(
"Maximum number of accepted project members a shared image may "
"have before being flagged. Range: 1..1000 (defaults to 5)."
),
)
secrets_ignore_patterns: Optional[list[str]] = Field(
default=None,
description=(
"Regex patterns whose matches are excluded from detect-secrets "
"scanning of resource metadata."
),
)
detect_secrets_plugins: Optional[list[_DetectSecretsPlugin]] = Field(
default=None,
description="Custom detect-secrets plugin configuration for metadata scanning.",
)
+6
View File
@@ -4,6 +4,7 @@ Kept in its own module so the validator stays free of provider-schema imports
and callers pay the import cost only when they actually need the registry.
"""
from prowler.config.schema.alibabacloud import AlibabaCloudProviderConfig
from prowler.config.schema.aws import AWSProviderConfig
from prowler.config.schema.azure import AzureProviderConfig
from prowler.config.schema.base import ProviderConfigBase
@@ -13,6 +14,8 @@ from prowler.config.schema.github import GitHubProviderConfig
from prowler.config.schema.kubernetes import KubernetesProviderConfig
from prowler.config.schema.m365 import M365ProviderConfig
from prowler.config.schema.mongodbatlas import MongoDBAtlasProviderConfig
from prowler.config.schema.okta import OktaProviderConfig
from prowler.config.schema.openstack import OpenStackProviderConfig
from prowler.config.schema.vercel import VercelProviderConfig
SCHEMAS: dict[str, type[ProviderConfigBase]] = {
@@ -25,4 +28,7 @@ SCHEMAS: dict[str, type[ProviderConfigBase]] = {
"mongodbatlas": MongoDBAtlasProviderConfig,
"cloudflare": CloudflareProviderConfig,
"vercel": VercelProviderConfig,
"okta": OktaProviderConfig,
"alibabacloud": AlibabaCloudProviderConfig,
"openstack": OpenStackProviderConfig,
}
+12
View File
@@ -70,6 +70,18 @@ INT_BOUND_CASES = [
("vercel", "stale_invitation_threshold_days", 7, 365),
("vercel", "max_owner_percentage", 1, 50),
("vercel", "max_owners", 1, 1000),
# Okta
("okta", "okta_max_session_idle_minutes", 1, 1440),
("okta", "okta_max_session_lifetime_minutes", 1, 43200),
("okta", "okta_admin_console_idle_timeout_max_minutes", 1, 1440),
("okta", "okta_user_inactivity_max_days", 1, 3650),
# Alibaba Cloud
("alibabacloud", "max_cluster_check_days", 1, 365),
("alibabacloud", "max_console_access_days", 30, 180),
("alibabacloud", "min_log_retention_days", 1, 3650),
("alibabacloud", "min_rds_audit_retention_days", 1, 3650),
# OpenStack
("openstack", "image_sharing_threshold", 1, 1000),
]
@@ -150,3 +150,64 @@ class Test_Vercel_Schema:
"secret_suffixes": ["_KEY", "_SECRET", "_TOKEN"],
}
assert _validate("vercel", raw) == raw
class Test_Okta_Schema:
def test_valid_values_round_trip(self):
raw = {
"okta_max_session_idle_minutes": 15,
"okta_max_session_lifetime_minutes": 18 * 60,
"okta_admin_console_idle_timeout_max_minutes": 15,
"okta_user_inactivity_max_days": 35,
"okta_dod_approved_ca_issuer_patterns": [r"\bOU=DoD\b", r"\bOU=ECA\b"],
}
assert _validate("okta", raw) == raw
def test_zero_idle_minutes_dropped(self):
assert _validate("okta", {"okta_max_session_idle_minutes": 0}) == {}
def test_negative_inactivity_days_dropped(self):
assert _validate("okta", {"okta_user_inactivity_max_days": -1}) == {}
class Test_AlibabaCloud_Schema:
def test_valid_values_round_trip(self):
raw = {
"max_cluster_check_days": 7,
"max_console_access_days": 90,
"min_log_retention_days": 365,
"min_rds_audit_retention_days": 180,
}
assert _validate("alibabacloud", raw) == raw
def test_zero_cluster_check_days_dropped(self):
assert _validate("alibabacloud", {"max_cluster_check_days": 0}) == {}
def test_console_access_below_min_dropped(self):
# 30 is the documented floor; anything below produces false positives.
assert _validate("alibabacloud", {"max_console_access_days": 29}) == {}
class Test_OpenStack_Schema:
def test_valid_values_round_trip(self):
raw = {
"image_sharing_threshold": 5,
"secrets_ignore_patterns": ["AKIA[0-9A-Z]{16}"],
"detect_secrets_plugins": [
{"name": "Base64HighEntropyString", "limit": 4.5}
],
}
assert _validate("openstack", raw) == raw
def test_zero_threshold_dropped(self):
assert _validate("openstack", {"image_sharing_threshold": 0}) == {}
def test_invalid_plugin_entropy_dropped(self):
# Reuses the AWS _DetectSecretsPlugin entropy bound (0..10).
assert (
_validate(
"openstack",
{"detect_secrets_plugins": [{"name": "X", "limit": 50}]},
)
== {}
)