mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-04 19:21:51 +00:00
chore(config): add missing providers config (#11725)
This commit is contained in:
@@ -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)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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: []
|
||||
|
||||
@@ -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)."
|
||||
),
|
||||
)
|
||||
@@ -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."
|
||||
),
|
||||
)
|
||||
@@ -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.",
|
||||
)
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
@@ -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}]},
|
||||
)
|
||||
== {}
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user