mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-05-19 18:53:33 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ad2008ae5 | |||
| c6d2ef03e1 | |||
| c7792727ea | |||
| 08566aeaf7 | |||
| 1d05990878 | |||
| 5eb5825bab |
@@ -2,6 +2,14 @@
|
||||
|
||||
All notable changes to the **Prowler SDK** are documented in this file.
|
||||
|
||||
## [5.28.0] (Prowler v5.28.0)
|
||||
|
||||
### 🔄 Changed
|
||||
|
||||
- `awslambda_function_no_secrets_in_code` now supports a `secrets_ignore_files` audit-config option to skip files inside the deployment package by glob pattern (e.g. `*.deps.json`), suppressing .NET dependency-manifest false positives without masking real secrets [(#11222)](https://github.com/prowler-cloud/prowler/pull/11222)
|
||||
|
||||
---
|
||||
|
||||
## [5.27.0] (Prowler v5.27.0)
|
||||
|
||||
### 🚀 Added
|
||||
|
||||
@@ -390,6 +390,20 @@ aws:
|
||||
# Patterns to ignore in the secrets checks
|
||||
secrets_ignore_patterns: []
|
||||
|
||||
# aws.awslambda_function_no_secrets_in_code
|
||||
# Glob patterns of file names inside the Lambda deployment package to skip
|
||||
# when scanning for secrets. Useful to suppress known false positives such
|
||||
# as .NET dependency manifests.
|
||||
# Example:
|
||||
# secrets_ignore_files:
|
||||
# - "*.deps.json"
|
||||
# WARNING: use at your own risk. Any file whose name matches one of these
|
||||
# patterns is fully excluded from secret scanning, so a real secret placed
|
||||
# in such a file will NOT be detected. Keep patterns as narrow and specific
|
||||
# as possible; this is not recommended unless you have confirmed the matched
|
||||
# files only ever contain false positives.
|
||||
secrets_ignore_files: []
|
||||
|
||||
# AWS Secrets Manager Configuration
|
||||
# aws.secretsmanager_secret_unused
|
||||
# Maximum number of days a secret can be unused
|
||||
|
||||
+14
@@ -1,3 +1,4 @@
|
||||
import fnmatch
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
@@ -13,6 +14,11 @@ class awslambda_function_no_secrets_in_code(Check):
|
||||
secrets_ignore_patterns = awslambda_client.audit_config.get(
|
||||
"secrets_ignore_patterns", []
|
||||
)
|
||||
# Glob patterns of file names inside the deployment package to skip
|
||||
# when scanning for secrets (e.g. "*.deps.json" for .NET Lambdas).
|
||||
secrets_ignore_files = awslambda_client.audit_config.get(
|
||||
"secrets_ignore_files", []
|
||||
)
|
||||
for function, function_code in awslambda_client._get_function_code():
|
||||
if function_code:
|
||||
report = Check_Report_AWS(
|
||||
@@ -29,6 +35,14 @@ class awslambda_function_no_secrets_in_code(Check):
|
||||
files_in_zip = next(os.walk(tmp_dir_name))[2]
|
||||
secrets_findings = []
|
||||
for file in files_in_zip:
|
||||
# Skip files whose name matches an ignore pattern
|
||||
# so known false-positive files (e.g. .NET
|
||||
# *.deps.json) do not raise spurious findings.
|
||||
if any(
|
||||
fnmatch.fnmatch(file, pattern)
|
||||
for pattern in secrets_ignore_files
|
||||
):
|
||||
continue
|
||||
detect_secrets_output = detect_secrets_scan(
|
||||
file=f"{tmp_dir_name}/{file}",
|
||||
excluded_secrets=secrets_ignore_patterns,
|
||||
|
||||
+101
@@ -53,6 +53,43 @@ def get_lambda_code_with_secrets(code):
|
||||
)
|
||||
|
||||
|
||||
LAMBDA_DEPS_JSON_WITH_SECRET = """
|
||||
{
|
||||
"runtimeTarget": { "name": ".NETCoreApp,Version=v8.0" },
|
||||
"libraries": {
|
||||
"AWSSDK.SecretsManager/3.7.0": {
|
||||
"type": "package",
|
||||
"password": "test-deps-json-password"
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def get_lambda_code_from_files(files: dict) -> LambdaCode:
|
||||
# The check only calls code_zip.extractall(dir); mock it to drop the
|
||||
# given files into the temporary directory the check creates, so no
|
||||
# real archive needs to be built.
|
||||
code_zip = mock.MagicMock()
|
||||
|
||||
def _extractall(path):
|
||||
for name, content in files.items():
|
||||
with open(f"{path}/{name}", "w") as fd:
|
||||
fd.write(content)
|
||||
|
||||
code_zip.extractall.side_effect = _extractall
|
||||
return LambdaCode(location="", code_zip=code_zip)
|
||||
|
||||
|
||||
def mock_get_function_code_with_deps_json_secret():
|
||||
yield create_lambda_function(), get_lambda_code_from_files(
|
||||
{
|
||||
"lambda_function.py": LAMBDA_FUNCTION_CODE_WITHOUT_SECRETS,
|
||||
"myapp.deps.json": LAMBDA_DEPS_JSON_WITH_SECRET,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def mock_get_function_codewith_secrets():
|
||||
yield create_lambda_function(), get_lambda_code_with_secrets(
|
||||
LAMBDA_FUNCTION_CODE_WITH_SECRETS
|
||||
@@ -201,3 +238,67 @@ class Test_awslambda_function_no_secrets_in_code:
|
||||
== f"No secrets found in Lambda function {LAMBDA_FUNCTION_NAME} code."
|
||||
)
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
def test_function_code_deps_json_secret_not_ignored(self):
|
||||
lambda_client = mock.MagicMock
|
||||
lambda_client.functions = {LAMBDA_FUNCTION_ARN: create_lambda_function()}
|
||||
lambda_client._get_function_code = mock_get_function_code_with_deps_json_secret
|
||||
lambda_client.audit_config = {"secrets_ignore_patterns": []}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.awslambda.awslambda_function_no_secrets_in_code.awslambda_function_no_secrets_in_code.awslambda_client",
|
||||
new=lambda_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.awslambda.awslambda_function_no_secrets_in_code.awslambda_function_no_secrets_in_code import (
|
||||
awslambda_function_no_secrets_in_code,
|
||||
)
|
||||
|
||||
check = awslambda_function_no_secrets_in_code()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert "myapp.deps.json" in result[0].status_extended
|
||||
|
||||
def test_function_code_deps_json_secret_ignored_by_file_pattern(self):
|
||||
lambda_client = mock.MagicMock
|
||||
lambda_client.functions = {LAMBDA_FUNCTION_ARN: create_lambda_function()}
|
||||
lambda_client._get_function_code = mock_get_function_code_with_deps_json_secret
|
||||
lambda_client.audit_config = {
|
||||
"secrets_ignore_patterns": [],
|
||||
"secrets_ignore_files": ["*.deps.json"],
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.awslambda.awslambda_function_no_secrets_in_code.awslambda_function_no_secrets_in_code.awslambda_client",
|
||||
new=lambda_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.awslambda.awslambda_function_no_secrets_in_code.awslambda_function_no_secrets_in_code import (
|
||||
awslambda_function_no_secrets_in_code,
|
||||
)
|
||||
|
||||
check = awslambda_function_no_secrets_in_code()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_id == LAMBDA_FUNCTION_NAME
|
||||
assert result[0].resource_arn == LAMBDA_FUNCTION_ARN
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"No secrets found in Lambda function {LAMBDA_FUNCTION_NAME} code."
|
||||
)
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
Reference in New Issue
Block a user