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)
|
- 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 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)
|
- 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
|
# 15 per DISA STIG V-273186 (OKTA-APP-000020); raise it only with an
|
||||||
# explicit risk acceptance.
|
# explicit risk acceptance.
|
||||||
okta_max_session_idle_minutes: 15
|
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 Applications
|
||||||
# okta.application_admin_console_session_idle_timeout_15min
|
# okta.application_admin_console_session_idle_timeout_15min
|
||||||
# Maximum acceptable Okta Admin Console app idle timeout, in minutes.
|
# Maximum acceptable Okta Admin Console app idle timeout, in minutes.
|
||||||
# Defaults to 15 per DISA STIG V-273187 (OKTA-APP-000025); raise it only
|
# Defaults to 15 per DISA STIG V-273187 (OKTA-APP-000025); raise it only
|
||||||
# with an explicit risk acceptance.
|
# with an explicit risk acceptance.
|
||||||
okta_admin_console_idle_timeout_max_minutes: 15
|
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.
|
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.aws import AWSProviderConfig
|
||||||
from prowler.config.schema.azure import AzureProviderConfig
|
from prowler.config.schema.azure import AzureProviderConfig
|
||||||
from prowler.config.schema.base import ProviderConfigBase
|
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.kubernetes import KubernetesProviderConfig
|
||||||
from prowler.config.schema.m365 import M365ProviderConfig
|
from prowler.config.schema.m365 import M365ProviderConfig
|
||||||
from prowler.config.schema.mongodbatlas import MongoDBAtlasProviderConfig
|
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
|
from prowler.config.schema.vercel import VercelProviderConfig
|
||||||
|
|
||||||
SCHEMAS: dict[str, type[ProviderConfigBase]] = {
|
SCHEMAS: dict[str, type[ProviderConfigBase]] = {
|
||||||
@@ -25,4 +28,7 @@ SCHEMAS: dict[str, type[ProviderConfigBase]] = {
|
|||||||
"mongodbatlas": MongoDBAtlasProviderConfig,
|
"mongodbatlas": MongoDBAtlasProviderConfig,
|
||||||
"cloudflare": CloudflareProviderConfig,
|
"cloudflare": CloudflareProviderConfig,
|
||||||
"vercel": VercelProviderConfig,
|
"vercel": VercelProviderConfig,
|
||||||
|
"okta": OktaProviderConfig,
|
||||||
|
"alibabacloud": AlibabaCloudProviderConfig,
|
||||||
|
"openstack": OpenStackProviderConfig,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,18 @@ INT_BOUND_CASES = [
|
|||||||
("vercel", "stale_invitation_threshold_days", 7, 365),
|
("vercel", "stale_invitation_threshold_days", 7, 365),
|
||||||
("vercel", "max_owner_percentage", 1, 50),
|
("vercel", "max_owner_percentage", 1, 50),
|
||||||
("vercel", "max_owners", 1, 1000),
|
("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"],
|
"secret_suffixes": ["_KEY", "_SECRET", "_TOKEN"],
|
||||||
}
|
}
|
||||||
assert _validate("vercel", raw) == raw
|
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