feat(sdk): replace detect-secrets library with kingfisher (#11694)

This commit is contained in:
Daniel Barranquero authored and GitHub committed 2026-06-30 15:36:23 +02:00
1 parent ed1fec8866
commit 5dac8a0a53
60 files changed
+2969 -881

No files matched your search

@@ -2,6 +2,7 @@
from unittest import mock
from prowler.lib.check.models import Severity
from prowler.providers.openstack.services.compute.compute_service import ComputeInstance
from tests.providers.openstack.openstack_fixtures import (
OPENSTACK_PROJECT_ID,
@@ -181,7 +182,7 @@ class Test_compute_instance_metadata_sensitive_data:
private_v6="",
networks={},
has_config_drive=False,
metadata={"db_password": "supersecret123"},
metadata={"db_password": "Tr0ub4dor3xKq9vLmZ"},
user_data="",
trusted_image_certificates=[],
)
@@ -233,7 +234,9 @@ class Test_compute_instance_metadata_sensitive_data:
private_v6="",
networks={},
has_config_drive=False,
metadata={"api_key": "sk-1234567890"},
metadata={
"api_key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U"
},
user_data="",
trusted_image_certificates=[],
)
@@ -349,7 +352,9 @@ class Test_compute_instance_metadata_sensitive_data:
private_v6="",
networks={},
has_config_drive=False,
metadata={"ssh_key": "-----BEGIN RSA PRIVATE KEY-----"},
metadata={
"ssh_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCUzlT9QGi8ZSr5\nk+LTRz/1TaiCCs6o1icW4cur0Q0hdBnbRJXUdjlQsgzmBvCBNkGHI8hb/RUPssvc\nDLU5kOQ3Wp2KgtbphhZ2PfpuJrzwHL1ejcJkRxegm/aTdmpoQKcxGeehAfHbmlLA\nxdfn6wPDfGji973yiRH56JRukJAaqF50HC2a/AVNC5HtZoVlbQ+WvVbYVUnPxNkv\nPpc53PjrBgWiTtdMONEqJ3jDiaqfUBt+TZYF0CFc9HgjnUniRX28OukDyLu+idOz\nFKyZxMXtqexkAvQLDW1PATpZgVQ7hJoCD8UVTXAtcgzPq5fA6AR2URiECHI6ZyL0\nUmixKfMNAgMBAAECggEAJRzp5wjdpmEgDQOkjpfGXJ6sAJUD8mmI8cTKeJWIzhdo\nDH8oVEdRJ65kl6lS6hMXWEZlJgYyrsnj3MPBnjQkKycbRCy6P59s8jwmfbsFI+iz\nFUZLXZm6i5jicGhYBRzc5hrlIYu73863RXOClAnSFDsu6K6rzfYASQFIJeRBwJfs\njqXinuun/h2zGjpiY+TtNsa8c+nC7f3sGsTzNJugDvBPWQzsnAMzXJqiyharre4V\no157XIOvdC0joIp8j/Ib1ZtMfz1K1LcgBgw0szSieIw0Rq8yQ0Ek7GtLh43jG+ap\nvcSEesTD1p4mjPXoWkPG8KYd4iwGedZaePfheVcKKQKBgQDNE03SWv18AH0d4fpB\nlFAtRybCfSvMORzBrt2oilz8wDmK+Zga5o+phCnM8v3eJy1v8BvIQ9RvwQA2uVgZ\nr701wNMpVrTsMujk83oVRhimZLk6Hyw07wmMgEHX7+izkm2Lk4Lk7Zol3VRfnWG6\nmIcUk7xB1yAs3mudsfx0VO0QyQKBgQC5wfdqCLj2hZk4sMZu8Bth+BHKChGItmDk\nAW7aNt+gaPyoryOJoi2OUO8ud8EyuqXiuslSk2pPtjvLhCppkoq6V8kmPAUzaxFk\n4nDEAxT9Un8IJ0j2ebv+koQKsBWjssbVSjrZgIcYIDK1QblgbCp2FSE3ima+V8ip\nOdNjiatWJQKBgEX8lox5nRSanhh6rIuA8DPjmmi5ix7xRs0avm7seXuQppK1R6G2\nmcTCY/mb2+Pa/vi6uuCHtZJGDaqfal+pyCr2GZp8CtapMS4hocJs37C5ozUguld+\nVIXsp4voRkQybsw5lWxHYloVxNu0vEuQDlmJabAWmNZ3OcbhnUSeTyFxAoGAFtkZ\n0owCHChwoT11Gt4jsBgwL/avE27DWigm92Y6eWOQeDsalupAyjmAQenu9Itqrgml\ni6egMu/KSQ0Xnmas86CqmC5XwWxQ9mS31BRA96u2/ky+t7pfej+RSDNCZiEuPbvk\noy4g78G+GvdbktWbH20X6dn3K0Bm6RG4w4yCa5UCgYBs0zAVs0DZmM8SUZJA/HuQ\nN6a1vKKns7xKw5N3SmX1KbDhx5LSZXfbUo2+QktE7iRf9G2f1o0q8kz9l/4AGXi1\nKJNUHupWoaQzGNrzAb27TUtFA0ocMG8KnqxjANWox5oPJS9OU5tw5H5dxeI/Senc\nkYW6eCnRzPcmBqex6Vuw4w==\n-----END PRIVATE KEY-----\n"
},
user_data="",
trusted_image_certificates=[],
)
@@ -431,7 +436,7 @@ class Test_compute_instance_metadata_sensitive_data:
private_v6="",
networks={},
has_config_drive=False,
metadata={"admin_password": "secret123"},
metadata={"admin_password": "Tr0ub4dor3xKq9vLmZ"},
user_data="",
trusted_image_certificates=[],
),
@@ -486,7 +491,7 @@ class Test_compute_instance_metadata_sensitive_data:
metadata={
"environment": "production",
"application": "web-app",
"db_password": "supersecret123",
"db_password": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
"region": "us-east",
},
user_data="",
@@ -544,7 +549,7 @@ class Test_compute_instance_metadata_sensitive_data:
has_config_drive=False,
metadata={
"first_key": "safe_value",
"api_key": "sk-1234567890abcdef",
"api_key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
"third_key": "also_safe",
},
user_data="",
@@ -574,3 +579,128 @@ class Test_compute_instance_metadata_sensitive_data:
# Verify the secret is correctly attributed to 'api_key' key (second in order)
assert "in metadata key 'api_key'" in result[0].status_extended
assert result[0].resource_id == "instance-8"
def test_instance_verified_secret_escalates_to_critical(self):
"""Test that a confirmed live secret escalates the finding to CRITICAL (FAIL)."""
compute_client = mock.MagicMock()
compute_client.audit_config = {"secrets_validate": True}
compute_client.instances = [
ComputeInstance(
id="instance-verified",
name="Verified Secret",
status="ACTIVE",
flavor_id="flavor-1",
security_groups=["default"],
region=OPENSTACK_REGION,
project_id=OPENSTACK_PROJECT_ID,
is_locked=False,
locked_reason="",
key_name="",
user_id="",
access_ipv4="",
access_ipv6="",
public_v4="",
public_v6="",
private_v4="",
private_v6="",
networks={},
has_config_drive=False,
metadata={"api_key": "placeholder"},
user_data="",
trusted_image_certificates=[],
)
]
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_openstack_provider(),
),
mock.patch(
"prowler.providers.openstack.services.compute.compute_instance_metadata_sensitive_data.compute_instance_metadata_sensitive_data.compute_client",
new=compute_client,
),
mock.patch(
"prowler.providers.openstack.services.compute.compute_instance_metadata_sensitive_data.compute_instance_metadata_sensitive_data.detect_secrets_scan_batch",
return_value={
0: [
{
"type": "JSON Web Token (base64url-encoded)",
"line_number": 2,
"filename": "data",
"hashed_secret": "x",
"is_verified": True,
}
]
},
) as mock_scan,
):
from prowler.providers.openstack.services.compute.compute_instance_metadata_sensitive_data.compute_instance_metadata_sensitive_data import (
compute_instance_metadata_sensitive_data,
)
check = compute_instance_metadata_sensitive_data()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].check_metadata.Severity == Severity.critical
assert "confirmed to be live" in result[0].status_extended
assert mock_scan.call_args.kwargs.get("validate") is True
def test_scan_failure_reports_manual(self):
from prowler.lib.utils.utils import SecretsScanError
compute_client = mock.MagicMock()
compute_client.audit_config = {"secrets_ignore_patterns": []}
compute_client.instances = [
ComputeInstance(
id="instance-scan-fail",
name="Scan Fail",
status="ACTIVE",
flavor_id="flavor-1",
security_groups=["default"],
region=OPENSTACK_REGION,
project_id=OPENSTACK_PROJECT_ID,
is_locked=False,
locked_reason="",
key_name="",
user_id="",
access_ipv4="",
access_ipv6="",
public_v4="",
public_v6="",
private_v4="",
private_v6="",
networks={},
has_config_drive=False,
metadata={"api_key": "placeholder"},
user_data="",
trusted_image_certificates=[],
)
]
with (
mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=set_mocked_openstack_provider(),
),
mock.patch(
"prowler.providers.openstack.services.compute.compute_instance_metadata_sensitive_data.compute_instance_metadata_sensitive_data.compute_client",
new=compute_client,
),
mock.patch(
"prowler.providers.openstack.services.compute.compute_instance_metadata_sensitive_data.compute_instance_metadata_sensitive_data.detect_secrets_scan_batch",
side_effect=SecretsScanError("Kingfisher exited with code 1"),
),
):
from prowler.providers.openstack.services.compute.compute_instance_metadata_sensitive_data.compute_instance_metadata_sensitive_data import (
compute_instance_metadata_sensitive_data,
)
check = compute_instance_metadata_sensitive_data()
result = check.execute()
assert len(result) == 1
assert result[0].status == "MANUAL"
assert "Could not scan" in result[0].status_extended