feat(detect-secrets): get secrets plugins from config.yaml (#6544)

Co-authored-by: Pepe Fagoaga <pepe@prowler.com>
This commit is contained in:
Pedro Martín
2025-01-23 12:33:19 +01:00
committed by Pepe Fagoaga
parent b25c0aaa00
commit 9d04a1bc52
15 changed files with 124 additions and 38 deletions
+31
View File
@@ -378,6 +378,37 @@ aws:
# Minimum retention period in hours for Kinesis streams
min_kinesis_stream_retention_hours: 168 # 7 days
# Detect Secrets plugin configuration
detect_secrets_plugins: [
{"name": "ArtifactoryDetector"},
{"name": "AWSKeyDetector"},
{"name": "AzureStorageKeyDetector"},
{"name": "BasicAuthDetector"},
{"name": "CloudantDetector"},
{"name": "DiscordBotTokenDetector"},
{"name": "GitHubTokenDetector"},
{"name": "GitLabTokenDetector"},
{"name": "Base64HighEntropyString", "limit": 6.0},
{"name": "HexHighEntropyString", "limit": 3.0},
{"name": "IbmCloudIamDetector"},
{"name": "IbmCosHmacDetector"},
# {"name": "IPPublicDetector"}, https://github.com/Yelp/detect-secrets/pull/885
{"name": "JwtTokenDetector"},
{"name": "KeywordDetector"},
{"name": "MailchimpDetector"},
{"name": "NpmDetector"},
{"name": "OpenAIDetector"},
{"name": "PrivateKeyDetector"},
{"name": "PypiTokenDetector"},
{"name": "SendGridDetector"},
{"name": "SlackDetector"},
{"name": "SoftlayerDetector"},
{"name": "SquareOAuthDetector"},
{"name": "StripeDetector"},
# {"name": "TelegramBotTokenDetector"}, https://github.com/Yelp/detect-secrets/pull/878
{"name": "TwilioKeyDetector"},
]
# Azure Configuration
azure:
+40 -30
View File
@@ -26,6 +26,36 @@ from detect_secrets.settings import transient_settings
from prowler.config.config import encoding_format_utf_8
from prowler.lib.logger import logger
default_detect_secrets_plugins = [
{"name": "ArtifactoryDetector"},
{"name": "AWSKeyDetector"},
{"name": "AzureStorageKeyDetector"},
{"name": "BasicAuthDetector"},
{"name": "CloudantDetector"},
{"name": "DiscordBotTokenDetector"},
{"name": "GitHubTokenDetector"},
{"name": "GitLabTokenDetector"},
{"name": "Base64HighEntropyString", "limit": 6.0},
{"name": "HexHighEntropyString", "limit": 3.0},
{"name": "IbmCloudIamDetector"},
{"name": "IbmCosHmacDetector"},
# {"name": "IPPublicDetector"}, https://github.com/Yelp/detect-secrets/pull/885
{"name": "JwtTokenDetector"},
{"name": "KeywordDetector"},
{"name": "MailchimpDetector"},
{"name": "NpmDetector"},
{"name": "OpenAIDetector"},
{"name": "PrivateKeyDetector"},
{"name": "PypiTokenDetector"},
{"name": "SendGridDetector"},
{"name": "SlackDetector"},
{"name": "SoftlayerDetector"},
{"name": "SquareOAuthDetector"},
{"name": "StripeDetector"},
# {"name": "TelegramBotTokenDetector"}, https://github.com/Yelp/detect-secrets/pull/878
{"name": "TwilioKeyDetector"},
]
def open_file(input_file: str, mode: str = "r") -> TextIOWrapper:
"""open_file returns a handler to the file using the specified mode."""
@@ -82,13 +112,17 @@ def hash_sha512(string: str) -> str:
def detect_secrets_scan(
data: str = None, file=None, excluded_secrets: list[str] = None
data: str = None,
file=None,
excluded_secrets: list[str] = None,
detect_secrets_plugins: dict = None,
) -> list[dict[str, str]]:
"""detect_secrets_scan scans the data or file for secrets using the detect-secrets library.
Args:
data (str): The data to scan for secrets.
file (str): The file to scan for secrets.
excluded_secrets (list): A list of regex patterns to exclude from the scan.
detect_secrets_plugins (dict): The settings to use for the scan.
Returns:
dict: The secrets found in the
Raises:
@@ -107,36 +141,11 @@ def detect_secrets_scan(
secrets = SecretsCollection()
if not detect_secrets_plugins:
detect_secrets_plugins = default_detect_secrets_plugins
settings = {
"plugins_used": [
{"name": "ArtifactoryDetector"},
{"name": "AWSKeyDetector"},
{"name": "AzureStorageKeyDetector"},
{"name": "BasicAuthDetector"},
{"name": "CloudantDetector"},
{"name": "DiscordBotTokenDetector"},
{"name": "GitHubTokenDetector"},
{"name": "GitLabTokenDetector"},
{"name": "Base64HighEntropyString", "limit": 6.0},
{"name": "HexHighEntropyString", "limit": 3.0},
{"name": "IbmCloudIamDetector"},
{"name": "IbmCosHmacDetector"},
# {"name": "IPPublicDetector"}, https://github.com/Yelp/detect-secrets/pull/885
{"name": "JwtTokenDetector"},
{"name": "KeywordDetector"},
{"name": "MailchimpDetector"},
{"name": "NpmDetector"},
{"name": "OpenAIDetector"},
{"name": "PrivateKeyDetector"},
{"name": "PypiTokenDetector"},
{"name": "SendGridDetector"},
{"name": "SlackDetector"},
{"name": "SoftlayerDetector"},
{"name": "SquareOAuthDetector"},
{"name": "StripeDetector"},
# {"name": "TelegramBotTokenDetector"}, https://github.com/Yelp/detect-secrets/pull/878
{"name": "TwilioKeyDetector"},
],
"plugins_used": detect_secrets_plugins,
"filters_used": [
{"path": "detect_secrets.filters.common.is_invalid_file"},
{"path": "detect_secrets.filters.common.is_known_false_positive"},
@@ -144,6 +153,7 @@ def detect_secrets_scan(
{"path": "detect_secrets.filters.heuristic.is_potential_secret"},
],
}
if excluded_secrets and len(excluded_secrets) > 0:
settings["filters_used"].append(
{
@@ -46,7 +46,11 @@ class autoscaling_find_secrets_ec2_launch_configuration(Check):
continue
has_secrets = detect_secrets_scan(
data=user_data, excluded_secrets=secrets_ignore_patterns
data=user_data,
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=autoscaling_client.audit_config.get(
"detect_secrets_plugins"
),
)
if has_secrets:
@@ -34,6 +34,9 @@ class awslambda_function_no_secrets_in_code(Check):
detect_secrets_output = detect_secrets_scan(
file=f"{tmp_dir_name}/{file}",
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=awslambda_client.audit_config.get(
"detect_secrets_plugins",
),
)
if detect_secrets_output:
for (
@@ -28,6 +28,9 @@ class awslambda_function_no_secrets_in_variables(Check):
detect_secrets_output = detect_secrets_scan(
data=json.dumps(function.environment, indent=2),
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=awslambda_client.audit_config.get(
"detect_secrets_plugins",
),
)
original_env_vars = {}
for name, value in function.environment.items():
@@ -31,7 +31,11 @@ class cloudformation_stack_outputs_find_secrets(Check):
data += f"{output}\n"
detect_secrets_output = detect_secrets_scan(
data=data, excluded_secrets=secrets_ignore_patterns
data=data,
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=cloudformation_client.audit_config.get(
"detect_secrets_plugins",
),
)
# If secrets are found, update the report status
if detect_secrets_output:
@@ -38,6 +38,9 @@ class cloudwatch_log_group_no_secrets_in_logs(Check):
log_stream_secrets_output = detect_secrets_scan(
data=log_stream_data,
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=logs_client.audit_config.get(
"detect_secrets_plugins",
),
)
if log_stream_secrets_output:
@@ -70,7 +73,10 @@ class cloudwatch_log_group_no_secrets_in_logs(Check):
# Can get more informative output if there is more than 1 line.
# Will rescan just this event to get the type of secret and the line number
event_detect_secrets_output = detect_secrets_scan(
data=log_event_data
data=log_event_data,
detect_secrets_plugins=logs_client.audit_config.get(
"detect_secrets_plugins"
),
)
if event_detect_secrets_output:
for secret in event_detect_secrets_output:
@@ -33,6 +33,9 @@ class codebuild_project_no_secrets_in_variables(Check):
detect_secrets_output = detect_secrets_scan(
data=json.dumps({env_var.name: env_var.value}),
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=codebuild_client.audit_config.get(
"detect_secrets_plugins",
),
)
if detect_secrets_output:
secrets_info = [
@@ -37,7 +37,11 @@ class ec2_instance_secrets_user_data(Check):
)
continue
detect_secrets_output = detect_secrets_scan(
data=user_data, excluded_secrets=secrets_ignore_patterns
data=user_data,
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=ec2_client.audit_config.get(
"detect_secrets_plugins"
),
)
if detect_secrets_output:
secrets_string = ", ".join(
@@ -43,7 +43,11 @@ class ec2_launch_template_no_secrets(Check):
continue
version_secrets = detect_secrets_scan(
data=user_data, excluded_secrets=secrets_ignore_patterns
data=user_data,
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=ec2_client.audit_config.get(
"detect_secrets_plugins"
),
)
if version_secrets:
@@ -39,7 +39,11 @@ class ecs_task_definitions_no_environment_secrets(Check):
env_data = dumps(dump_env_vars, indent=2)
detect_secrets_output = detect_secrets_scan(
data=env_data, excluded_secrets=secrets_ignore_patterns
data=env_data,
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=ecs_client.audit_config.get(
"detect_secrets_plugins",
),
)
if detect_secrets_output:
secrets_string = ", ".join(
@@ -26,6 +26,9 @@ class ssm_document_secrets(Check):
detect_secrets_output = detect_secrets_scan(
data=json.dumps(document.content, indent=2),
excluded_secrets=secrets_ignore_patterns,
detect_secrets_plugins=ssm_client.audit_config.get(
"detect_secrets_plugins"
),
)
if detect_secrets_output:
secrets_string = ", ".join(
+4 -2
View File
@@ -111,7 +111,7 @@ class Test_utils_validate_ip_address:
class Test_detect_secrets_scan:
def test_detect_secrets_scan_data(self):
data = "password=password"
secrets_detected = detect_secrets_scan(data=data)
secrets_detected = detect_secrets_scan(data=data, excluded_secrets=[])
assert type(secrets_detected) is list
assert len(secrets_detected) == 1
assert "filename" in secrets_detected[0]
@@ -128,7 +128,9 @@ class Test_detect_secrets_scan:
temp_data_file = tempfile.NamedTemporaryFile(delete=False)
temp_data_file.write(b"password=password")
temp_data_file.seek(0)
secrets_detected = detect_secrets_scan(file=temp_data_file.name)
secrets_detected = detect_secrets_scan(
file=temp_data_file.name, excluded_secrets=[]
)
assert type(secrets_detected) is list
assert len(secrets_detected) == 1
assert "filename" in secrets_detected[0]
@@ -203,6 +203,7 @@ class Test_ec2_launch_template_no_secrets:
)
ec2_client.launch_templates = [launch_template]
ec2_client.audit_config = {"detect_secrets_plugins": None}
with mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -277,6 +278,7 @@ class Test_ec2_launch_template_no_secrets:
)
ec2_client.launch_templates = [launch_template]
ec2_client.audit_config = {"detect_secrets_plugins": None}
with mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -341,6 +343,7 @@ class Test_ec2_launch_template_no_secrets:
)
ec2_client.launch_templates = [launch_template]
ec2_client.audit_config = {"detect_secrets_plugins": None}
with mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -482,6 +485,7 @@ class Test_ec2_launch_template_no_secrets:
launch_template_secrets,
launch_template_no_secrets,
]
ec2_client.audit_config = {"detect_secrets_plugins": None}
with mock.patch(
"prowler.providers.common.provider.Provider.get_global_provider",
@@ -27,6 +27,7 @@ class Test_ssm_documents_secrets:
document_name = "test-document"
document_arn = f"arn:aws:ssm:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:document/{document_name}"
ssm_client.audited_account = AWS_ACCOUNT_NUMBER
ssm_client.audit_config = {"detect_secrets_plugins": None}
ssm_client.documents = {
document_name: Document(
arn=document_arn,