mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-04-06 02:58:15 +00:00
Merge branch 'cloudflare-pr2-tls-email-checks' into cloudflare-pr3-bot-config-checks
This commit is contained in:
5
api/poetry.lock
generated
5
api/poetry.lock
generated
@@ -6764,6 +6764,7 @@ files = [
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6"},
|
||||
@@ -6772,6 +6773,7 @@ files = [
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632"},
|
||||
@@ -6780,6 +6782,7 @@ files = [
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a"},
|
||||
@@ -6788,6 +6791,7 @@ files = [
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987"},
|
||||
@@ -6796,6 +6800,7 @@ files = [
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2c59aa6170b990d8d2719323e628aaf36f3bfbc1c26279c0eeeb24d05d2d11c7"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12"},
|
||||
{file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b"},
|
||||
{file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"},
|
||||
|
||||
@@ -3,7 +3,25 @@ from prowler.providers.cloudflare.services.zones.zones_client import zones_clien
|
||||
|
||||
|
||||
class zones_dnssec_enabled(Check):
|
||||
"""Ensure that DNSSEC is enabled for Cloudflare zones.
|
||||
|
||||
DNSSEC (Domain Name System Security Extensions) adds cryptographic signatures
|
||||
to DNS records, protecting against DNS spoofing and cache poisoning attacks.
|
||||
When enabled, it ensures that DNS responses are authentic and have not been
|
||||
tampered with during transit.
|
||||
"""
|
||||
|
||||
def execute(self) -> list[CheckReportCloudflare]:
|
||||
"""Execute the DNSSEC enabled check.
|
||||
|
||||
Iterates through all Cloudflare zones and verifies that DNSSEC status
|
||||
is set to 'active'. A zone passes the check if DNSSEC is actively
|
||||
protecting its DNS records; otherwise, it fails.
|
||||
|
||||
Returns:
|
||||
A list of CheckReportCloudflare objects with PASS status if DNSSEC
|
||||
is active, or FAIL status if DNSSEC is not enabled for the zone.
|
||||
"""
|
||||
findings = []
|
||||
for zone in zones_client.zones.values():
|
||||
report = CheckReportCloudflare(
|
||||
|
||||
@@ -3,7 +3,28 @@ from prowler.providers.cloudflare.services.zones.zones_client import zones_clien
|
||||
|
||||
|
||||
class zones_hsts_enabled(Check):
|
||||
"""Ensure that HSTS is enabled with secure settings for Cloudflare zones.
|
||||
|
||||
HTTP Strict Transport Security (HSTS) forces browsers to only connect via
|
||||
HTTPS, preventing protocol downgrade attacks and cookie hijacking. This check
|
||||
verifies that HSTS is enabled with a minimum max-age of 6 months (15768000
|
||||
seconds) and includes subdomains for complete protection.
|
||||
"""
|
||||
|
||||
def execute(self) -> list[CheckReportCloudflare]:
|
||||
"""Execute the HSTS enabled check.
|
||||
|
||||
Iterates through all Cloudflare zones and validates HSTS configuration
|
||||
against security best practices. The check verifies three conditions:
|
||||
1. HSTS is enabled for the zone
|
||||
2. The includeSubdomains directive is set to protect all subdomains
|
||||
3. The max-age is at least 6 months (15768000 seconds)
|
||||
|
||||
Returns:
|
||||
A list of CheckReportCloudflare objects with PASS status if all
|
||||
HSTS requirements are met, or FAIL status if HSTS is disabled,
|
||||
missing subdomain inclusion, or has insufficient max-age.
|
||||
"""
|
||||
findings = []
|
||||
# Recommended minimum max-age is 6 months (15768000 seconds)
|
||||
recommended_max_age = 15768000
|
||||
|
||||
@@ -3,7 +3,26 @@ from prowler.providers.cloudflare.services.zones.zones_client import zones_clien
|
||||
|
||||
|
||||
class zones_https_redirect_enabled(Check):
|
||||
"""Ensure that Always Use HTTPS redirect is enabled for Cloudflare zones.
|
||||
|
||||
The Always Use HTTPS setting automatically redirects all HTTP requests to
|
||||
HTTPS, ensuring that all traffic to the zone is encrypted. This prevents
|
||||
man-in-the-middle attacks and protects sensitive data transmitted between
|
||||
clients and the origin server.
|
||||
"""
|
||||
|
||||
def execute(self) -> list[CheckReportCloudflare]:
|
||||
"""Execute the HTTPS redirect enabled check.
|
||||
|
||||
Iterates through all Cloudflare zones and verifies that the
|
||||
always_use_https setting is turned on. When enabled, Cloudflare
|
||||
automatically redirects all HTTP requests to their HTTPS equivalents.
|
||||
|
||||
Returns:
|
||||
A list of CheckReportCloudflare objects with PASS status if
|
||||
Always Use HTTPS is enabled ('on'), or FAIL status if the
|
||||
setting is disabled for the zone.
|
||||
"""
|
||||
findings = []
|
||||
for zone in zones_client.zones.values():
|
||||
report = CheckReportCloudflare(
|
||||
|
||||
@@ -3,7 +3,27 @@ from prowler.providers.cloudflare.services.zones.zones_client import zones_clien
|
||||
|
||||
|
||||
class zones_min_tls_version_secure(Check):
|
||||
"""Ensure that minimum TLS version is set to 1.2 or higher for Cloudflare zones.
|
||||
|
||||
TLS 1.0 and 1.1 have known vulnerabilities (BEAST, POODLE) and are deprecated.
|
||||
Setting the minimum TLS version to 1.2 or higher ensures that only secure
|
||||
cipher suites are used for encrypted connections, protecting against
|
||||
downgrade attacks and known cryptographic weaknesses.
|
||||
"""
|
||||
|
||||
def execute(self) -> list[CheckReportCloudflare]:
|
||||
"""Execute the minimum TLS version check.
|
||||
|
||||
Iterates through all Cloudflare zones and verifies that the minimum
|
||||
TLS version is configured to 1.2 or higher. The check parses the
|
||||
min_tls_version setting as a float for comparison, defaulting to 0
|
||||
if the value cannot be parsed.
|
||||
|
||||
Returns:
|
||||
A list of CheckReportCloudflare objects with PASS status if the
|
||||
minimum TLS version is 1.2 or higher, or FAIL status if older
|
||||
TLS versions (1.0, 1.1) are still allowed.
|
||||
"""
|
||||
findings = []
|
||||
|
||||
for zone in zones_client.zones.values():
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Provider": "cloudflare",
|
||||
"CheckID": "zones_ssl_strict",
|
||||
"CheckTitle": "SSL/TLS encryption mode is set to Full Strict",
|
||||
"CheckTitle": "SSL/TLS encryption mode is set to Full, or Full Strict",
|
||||
"CheckType": [],
|
||||
"ServiceName": "zones",
|
||||
"SubServiceName": "",
|
||||
|
||||
@@ -3,7 +3,28 @@ from prowler.providers.cloudflare.services.zones.zones_client import zones_clien
|
||||
|
||||
|
||||
class zones_ssl_strict(Check):
|
||||
"""Ensure that SSL/TLS encryption mode is set to strict for Cloudflare zones.
|
||||
|
||||
The SSL/TLS encryption mode determines how Cloudflare connects to the origin
|
||||
server. In 'strict' or 'full' mode, Cloudflare validates the origin
|
||||
server's SSL certificate, ensuring end-to-end encryption with certificate
|
||||
verification. Lower modes (off, flexible, full) are vulnerable to
|
||||
man-in-the-middle attacks between Cloudflare and the origin.
|
||||
"""
|
||||
|
||||
def execute(self) -> list[CheckReportCloudflare]:
|
||||
"""Execute the SSL strict mode check.
|
||||
|
||||
Iterates through all Cloudflare zones and verifies that the SSL/TLS
|
||||
encryption mode is set to 'strict' or 'full'. These modes
|
||||
require a valid SSL certificate on the origin server and provide
|
||||
full end-to-end encryption with certificate validation.
|
||||
|
||||
Returns:
|
||||
A list of CheckReportCloudflare objects with PASS status if
|
||||
SSL mode is 'strict' or 'full', or FAIL status if using
|
||||
less secure modes like 'off', 'flexible', or 'full'.
|
||||
"""
|
||||
findings = []
|
||||
for zone in zones_client.zones.values():
|
||||
report = CheckReportCloudflare(
|
||||
@@ -11,11 +32,11 @@ class zones_ssl_strict(Check):
|
||||
resource=zone,
|
||||
)
|
||||
ssl_mode = (zone.settings.ssl_encryption_mode or "").lower()
|
||||
if ssl_mode in ["strict", "full_strict"]:
|
||||
if ssl_mode in ["strict", "full"]:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"SSL/TLS encryption mode is set to {ssl_mode} for zone {zone.name}."
|
||||
else:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"SSL/TLS encryption mode is set to {ssl_mode} for zone {zone.name}."
|
||||
report.status_extended = f"SSL/TLS encryption mode is set to {ssl_mode} for zone {zone.name}, which is not strict or full."
|
||||
findings.append(report)
|
||||
return findings
|
||||
|
||||
@@ -73,43 +73,6 @@ class Test_zones_ssl_strict:
|
||||
== f"SSL/TLS encryption mode is set to strict for zone {ZONE_NAME}."
|
||||
)
|
||||
|
||||
def test_zone_ssl_full_strict_mode(self):
|
||||
zones_client = mock.MagicMock
|
||||
zones_client.zones = {
|
||||
ZONE_ID: CloudflareZone(
|
||||
id=ZONE_ID,
|
||||
name=ZONE_NAME,
|
||||
status="active",
|
||||
paused=False,
|
||||
settings=CloudflareZoneSettings(
|
||||
ssl_encryption_mode="full_strict",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_cloudflare_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.cloudflare.services.zones.zones_ssl_strict.zones_ssl_strict.zones_client",
|
||||
new=zones_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.cloudflare.services.zones.zones_ssl_strict.zones_ssl_strict import (
|
||||
zones_ssl_strict,
|
||||
)
|
||||
|
||||
check = zones_ssl_strict()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SSL/TLS encryption mode is set to full_strict for zone {ZONE_NAME}."
|
||||
)
|
||||
|
||||
def test_zone_ssl_full_mode(self):
|
||||
zones_client = mock.MagicMock
|
||||
zones_client.zones = {
|
||||
@@ -141,7 +104,7 @@ class Test_zones_ssl_strict:
|
||||
check = zones_ssl_strict()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SSL/TLS encryption mode is set to full for zone {ZONE_NAME}."
|
||||
@@ -181,7 +144,7 @@ class Test_zones_ssl_strict:
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SSL/TLS encryption mode is set to flexible for zone {ZONE_NAME}."
|
||||
== f"SSL/TLS encryption mode is set to flexible for zone {ZONE_NAME}, which is not strict or full."
|
||||
)
|
||||
|
||||
def test_zone_ssl_off_mode(self):
|
||||
@@ -218,5 +181,5 @@ class Test_zones_ssl_strict:
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"SSL/TLS encryption mode is set to off for zone {ZONE_NAME}."
|
||||
== f"SSL/TLS encryption mode is set to off for zone {ZONE_NAME}, which is not strict or full."
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user