mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-11-02 01:15:31 +00:00
feat(sdk): replace detect-secrets library with kingfisher (#11694)
This commit is contained in:
1 parent
ed1fec8866
commit
5dac8a0a53
60 files changed
+2969
-881
No files matched your search
+187
-14
@@ -1,6 +1,10 @@
|
||||
from unittest import mock
|
||||
|
||||
from tests.providers.aws.utils import AWS_ACCOUNT_NUMBER, AWS_REGION_US_EAST_1
|
||||
from tests.providers.aws.utils import (
|
||||
AWS_ACCOUNT_NUMBER,
|
||||
AWS_REGION_US_EAST_1,
|
||||
set_mocked_aws_provider,
|
||||
)
|
||||
|
||||
|
||||
class Test_codebuild_project_no_secrets_in_variables:
|
||||
@@ -202,7 +206,11 @@ class Test_codebuild_project_no_secrets_in_variables:
|
||||
environment_variables=[
|
||||
{
|
||||
"name": "AWS_ACCESS_KEY_ID",
|
||||
"value": "AKIAIOSFODNN7EXAMPLE",
|
||||
# Realistic fake secret that Kingfisher detects. The classic
|
||||
# "AKIAIOSFODNN7EXAMPLE" placeholder is suppressed by
|
||||
# Kingfisher and its AWS Access Key rule is not enabled, so a
|
||||
# detectable provider secret is used instead.
|
||||
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
|
||||
"type": "PLAINTEXT",
|
||||
}
|
||||
],
|
||||
@@ -231,15 +239,100 @@ class Test_codebuild_project_no_secrets_in_variables:
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
# The JWT paired with a "KEY" variable name yields both a
|
||||
# JWT and a Generic API Key finding; order is non-deterministic.
|
||||
assert result[0].status_extended.startswith(
|
||||
"CodeBuild project SensitiveProject has sensitive environment plaintext credentials in variables:"
|
||||
)
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "CodeBuild project SensitiveProject has sensitive environment plaintext credentials in variables: AWS Access Key in variable AWS_ACCESS_KEY_ID."
|
||||
"JSON Web Token (base64url-encoded) in variable AWS_ACCESS_KEY_ID"
|
||||
in result[0].status_extended
|
||||
)
|
||||
assert (
|
||||
"Generic API Key in variable AWS_ACCESS_KEY_ID"
|
||||
in result[0].status_extended
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_id == "SensitiveProject"
|
||||
assert result[0].resource_arn == project_arn
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
def test_project_with_verified_secret(self):
|
||||
from prowler.lib.check.models import Severity
|
||||
|
||||
codebuild_client = mock.MagicMock()
|
||||
|
||||
from prowler.providers.aws.services.codebuild.codebuild_service import Project
|
||||
|
||||
project_arn = f"arn:aws:codebuild:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:project/SensitiveProject"
|
||||
codebuild_client.projects = {
|
||||
project_arn: Project(
|
||||
name="SensitiveProject",
|
||||
arn=project_arn,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
last_invoked_time=None,
|
||||
buildspec=None,
|
||||
environment_variables=[
|
||||
{
|
||||
"name": "EXAMPLE_VAR",
|
||||
"value": "ExampleValue",
|
||||
"type": "PLAINTEXT",
|
||||
}
|
||||
],
|
||||
tags=[],
|
||||
)
|
||||
}
|
||||
|
||||
codebuild_client.audit_config = {
|
||||
"excluded_sensitive_environment_variables": [],
|
||||
"secrets_validate": True,
|
||||
}
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_aws_provider(
|
||||
audit_config={"secrets_validate": True}
|
||||
),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_service.Codebuild",
|
||||
codebuild_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_project_no_secrets_in_variables.codebuild_project_no_secrets_in_variables.codebuild_client",
|
||||
codebuild_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_project_no_secrets_in_variables.codebuild_project_no_secrets_in_variables.detect_secrets_scan_batch",
|
||||
return_value={
|
||||
(0, 0): [
|
||||
{
|
||||
"type": "JSON Web Token (base64url-encoded)",
|
||||
"line_number": 1,
|
||||
"filename": "data",
|
||||
"hashed_secret": "x",
|
||||
"is_verified": True,
|
||||
}
|
||||
]
|
||||
},
|
||||
) as mock_scan,
|
||||
):
|
||||
from prowler.providers.aws.services.codebuild.codebuild_project_no_secrets_in_variables.codebuild_project_no_secrets_in_variables import (
|
||||
codebuild_project_no_secrets_in_variables,
|
||||
)
|
||||
|
||||
check = codebuild_project_no_secrets_in_variables()
|
||||
result = check.execute()
|
||||
|
||||
# The check must forward secrets_validate from the config to the scan.
|
||||
assert mock_scan.call_args.kwargs.get("validate") is True
|
||||
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 result[0].resource_id == "SensitiveProject"
|
||||
|
||||
def test_project_with_sensitive_plaintext_credentials_exluded(self):
|
||||
codebuild_client = mock.MagicMock
|
||||
|
||||
@@ -373,12 +466,12 @@ class Test_codebuild_project_no_secrets_in_variables:
|
||||
environment_variables=[
|
||||
{
|
||||
"name": "AWS_DUMB_ACCESS_KEY",
|
||||
"value": "AKIAIOSFODNN7EXAMPLE",
|
||||
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
|
||||
"type": "PLAINTEXT",
|
||||
},
|
||||
{
|
||||
"name": "AWS_ACCESS_KEY_ID",
|
||||
"value": "AKIAIOSFODNN7EXAMPLE",
|
||||
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
|
||||
"type": "PLAINTEXT",
|
||||
},
|
||||
],
|
||||
@@ -409,10 +502,21 @@ class Test_codebuild_project_no_secrets_in_variables:
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "CodeBuild project SensitiveProject has sensitive environment plaintext credentials in variables: AWS Access Key in variable AWS_ACCESS_KEY_ID."
|
||||
# AWS_DUMB_ACCESS_KEY is excluded, so only AWS_ACCESS_KEY_ID is
|
||||
# scanned; its JWT + "KEY" name yields both a JWT and a
|
||||
# Generic API Key finding with non-deterministic order.
|
||||
assert result[0].status_extended.startswith(
|
||||
"CodeBuild project SensitiveProject has sensitive environment plaintext credentials in variables:"
|
||||
)
|
||||
assert (
|
||||
"JSON Web Token (base64url-encoded) in variable AWS_ACCESS_KEY_ID"
|
||||
in result[0].status_extended
|
||||
)
|
||||
assert (
|
||||
"Generic API Key in variable AWS_ACCESS_KEY_ID"
|
||||
in result[0].status_extended
|
||||
)
|
||||
assert "AWS_DUMB_ACCESS_KEY" not in result[0].status_extended
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_id == "SensitiveProject"
|
||||
assert result[0].resource_arn == project_arn
|
||||
@@ -434,12 +538,12 @@ class Test_codebuild_project_no_secrets_in_variables:
|
||||
environment_variables=[
|
||||
{
|
||||
"name": "AWS_DUMB_ACCESS_KEY",
|
||||
"value": "AKIAIOSFODNN7EXAMPLE",
|
||||
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
|
||||
"type": "PLAINTEXT",
|
||||
},
|
||||
{
|
||||
"name": "AWS_ACCESS_KEY_ID",
|
||||
"value": "AKIAIOSFODNN7EXAMPLE",
|
||||
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
|
||||
"type": "PLAINTEXT",
|
||||
},
|
||||
],
|
||||
@@ -468,11 +572,80 @@ class Test_codebuild_project_no_secrets_in_variables:
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "CodeBuild project SensitiveProject has sensitive environment plaintext credentials in variables: AWS Access Key in variable AWS_DUMB_ACCESS_KEY, AWS Access Key in variable AWS_ACCESS_KEY_ID."
|
||||
# Both variables hold a JWT and have "KEY" in their name, so
|
||||
# each yields a JWT and a Generic API Key finding; order is
|
||||
# non-deterministic.
|
||||
assert result[0].status_extended.startswith(
|
||||
"CodeBuild project SensitiveProject has sensitive environment plaintext credentials in variables:"
|
||||
)
|
||||
for var_name in ("AWS_DUMB_ACCESS_KEY", "AWS_ACCESS_KEY_ID"):
|
||||
assert (
|
||||
f"JSON Web Token (base64url-encoded) in variable {var_name}"
|
||||
in result[0].status_extended
|
||||
)
|
||||
assert (
|
||||
f"Generic API Key in variable {var_name}"
|
||||
in result[0].status_extended
|
||||
)
|
||||
assert result[0].region == AWS_REGION_US_EAST_1
|
||||
assert result[0].resource_id == "SensitiveProject"
|
||||
assert result[0].resource_arn == project_arn
|
||||
assert result[0].resource_tags == []
|
||||
|
||||
def test_scan_failure_reports_manual(self):
|
||||
from prowler.lib.utils.utils import SecretsScanError
|
||||
|
||||
codebuild_client = mock.MagicMock()
|
||||
from prowler.providers.aws.services.codebuild.codebuild_service import Project
|
||||
|
||||
project_arn = f"arn:aws:codebuild:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:project/SensitiveProject"
|
||||
codebuild_client.projects = {
|
||||
project_arn: Project(
|
||||
name="SensitiveProject",
|
||||
arn=project_arn,
|
||||
region=AWS_REGION_US_EAST_1,
|
||||
last_invoked_time=None,
|
||||
buildspec=None,
|
||||
environment_variables=[
|
||||
{
|
||||
"name": "EXAMPLE_VAR",
|
||||
"value": "ExampleValue",
|
||||
"type": "PLAINTEXT",
|
||||
}
|
||||
],
|
||||
tags=[],
|
||||
)
|
||||
}
|
||||
codebuild_client.audit_config = {
|
||||
"excluded_sensitive_environment_variables": [],
|
||||
"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.codebuild.codebuild_service.Codebuild",
|
||||
codebuild_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_project_no_secrets_in_variables.codebuild_project_no_secrets_in_variables.codebuild_client",
|
||||
codebuild_client,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.codebuild.codebuild_project_no_secrets_in_variables.codebuild_project_no_secrets_in_variables.detect_secrets_scan_batch",
|
||||
side_effect=SecretsScanError("Kingfisher exited with code 1"),
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.codebuild.codebuild_project_no_secrets_in_variables.codebuild_project_no_secrets_in_variables import (
|
||||
codebuild_project_no_secrets_in_variables,
|
||||
)
|
||||
|
||||
check = codebuild_project_no_secrets_in_variables()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "MANUAL"
|
||||
assert "Could not scan" in result[0].status_extended
|
||||
Reference in new issue
Block a user