Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(aws): key error for detect-secrets #6710

Merged
merged 4 commits into from
Feb 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import hashlib
import json

from prowler.lib.check.models import Check, Check_Report_AWS
Expand Down Expand Up @@ -28,19 +27,13 @@ def execute(self):
"detect_secrets_plugins",
),
)
original_env_vars = {}
original_env_vars = []
for name, value in function.environment.items():
original_env_vars.update(
{
hashlib.sha1( # nosec B324 SHA1 is used here for non-security-critical unique identifiers
value.encode("utf-8")
).hexdigest(): name
}
)
original_env_vars.append(name)
if detect_secrets_output:
secrets_string = ", ".join(
[
f"{secret['type']} in variable {original_env_vars[secret['hashed_secret']]}"
f"{secret['type']} in variable {original_env_vars[secret['line_number'] - 2]}"
for secret in detect_secrets_output
]
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import hashlib
from json import dumps

from prowler.lib.check.models import Check, Check_Report_AWS
Expand All @@ -25,16 +24,10 @@ def execute(self):

if container.environment:
dump_env_vars = {}
original_env_vars = {}
original_env_vars = []
for env_var in container.environment:
dump_env_vars.update({env_var.name: env_var.value})
original_env_vars.update(
{
hashlib.sha1( # nosec B324 SHA1 is used here for non-security-critical unique identifiers
env_var.value.encode("utf-8")
).hexdigest(): env_var.name
}
)
original_env_vars.append(env_var.name)

env_data = dumps(dump_env_vars, indent=2)
detect_secrets_output = detect_secrets_scan(
Expand All @@ -47,7 +40,7 @@ def execute(self):
if detect_secrets_output:
secrets_string = ", ".join(
[
f"{secret['type']} on the environment variable {original_env_vars[secret['hashed_secret']]}"
f"{secret['type']} on the environment variable {original_env_vars[secret['line_number'] - 2]}"
for secret in detect_secrets_output
]
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def test_function_no_variables(self):
)
assert result[0].resource_tags == []

def test_function_secrets_in_variables(self):
def test_function_secrets_in_keyword(self):
lambda_client = mock.MagicMock
function_name = "test-lambda"
function_runtime = "nodejs4.3"
Expand Down Expand Up @@ -121,6 +121,51 @@ def test_function_secrets_in_variables(self):
)
assert result[0].resource_tags == []

def test_function_secrets_in_keyword_and_variable(self):
lambda_client = mock.MagicMock
function_name = "test-lambda"
function_runtime = "nodejs4.3"
function_arn = f"arn:aws:lambda:{AWS_REGION_US_EAST_1}:{AWS_ACCOUNT_NUMBER}:function/{function_name}"

lambda_client.audit_config = {"secrets_ignore_patterns": []}

lambda_client.functions = {
"function_name": Function(
name=function_name,
security_groups=[],
arn=function_arn,
region=AWS_REGION_US_EAST_1,
runtime=function_runtime,
environment={"db_password": "srv://admin:pass@db"},
)
}

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_variables.awslambda_function_no_secrets_in_variables.awslambda_client",
new=lambda_client,
):
# Test Check
from prowler.providers.aws.services.awslambda.awslambda_function_no_secrets_in_variables.awslambda_function_no_secrets_in_variables import (
awslambda_function_no_secrets_in_variables,
)

check = awslambda_function_no_secrets_in_variables()
result = check.execute()

assert len(result) == 1
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_id == function_name
assert result[0].resource_arn == function_arn
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"Potential secret found in Lambda function {function_name} variables -> Secret Keyword in variable db_password, Basic Auth Credentials in variable db_password."
)
assert result[0].resource_tags == []

def test_function_secrets_in_variables_telegram_token(self):
lambda_client = mock.MagicMock
function_name = "test-lambda"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@

from boto3 import client
from moto import mock_aws

from tests.providers.aws.utils import AWS_REGION_US_EAST_1, set_mocked_aws_provider

TASK_NAME = "test-task"
TASK_REVISION = "1"
CONTAINER_NAME = "test-container"
ENV_VAR_NAME_NO_SECRETS = "host"
ENV_VAR_VALUE_NO_SECRETS = "localhost:1234"
ENV_VAR_NAME_WITH_SECRETS = "DB_PASSWORD"
ENV_VAR_VALUE_WITH_SECRETS = "pass-12343"
ENV_VAR_NAME_WITH_KEYWORD = "DB_PASSWORD"
ENV_VAR_VALUE_WITH_SECRETS = "srv://admin:pass@db"
ENV_VAR_NAME_WITH_KEYWORD2 = "DATABASE_PASSWORD"
ENV_VAR_VALUE_WITH_SECRETS2 = "srv://admin:password@database"


class Test_ecs_task_definitions_no_environment_secrets:
Expand Down Expand Up @@ -88,7 +89,7 @@ def test_container_env_var_no_secrets(self):
assert result[0].resource_tags == []

@mock_aws
def test_container_env_var_with_secrets(self):
def test_container_env_var_with_secret(self):
ecs_client = client("ecs", region_name=AWS_REGION_US_EAST_1)

task_arn = ecs_client.register_task_definition(
Expand All @@ -103,7 +104,7 @@ def test_container_env_var_with_secrets(self):
"user": "appuser",
"environment": [
{
"name": ENV_VAR_NAME_WITH_SECRETS,
"name": ENV_VAR_NAME_NO_SECRETS,
"value": ENV_VAR_VALUE_WITH_SECRETS,
}
],
Expand All @@ -115,6 +116,58 @@ def test_container_env_var_with_secrets(self):

mocked_aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])

with patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mocked_aws_provider,
), patch(
"prowler.providers.aws.services.ecs.ecs_task_definitions_no_environment_secrets.ecs_task_definitions_no_environment_secrets.ecs_client",
new=ECS(mocked_aws_provider),
):
from prowler.providers.aws.services.ecs.ecs_task_definitions_no_environment_secrets.ecs_task_definitions_no_environment_secrets import (
ecs_task_definitions_no_environment_secrets,
)

check = ecs_task_definitions_no_environment_secrets()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"Potential secrets found in ECS task definition {TASK_NAME} with revision {TASK_REVISION}: Secrets in container test-container -> Basic Auth Credentials on the environment variable host."
)
assert result[0].resource_id == f"{TASK_NAME}:{TASK_REVISION}"
assert result[0].resource_arn == task_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []

@mock_aws
def test_container_env_var_with_keyword(self):
ecs_client = client("ecs", region_name=AWS_REGION_US_EAST_1)

task_arn = ecs_client.register_task_definition(
family=TASK_NAME,
containerDefinitions=[
{
"name": CONTAINER_NAME,
"image": "ubuntu",
"memory": 128,
"readonlyRootFilesystem": True,
"privileged": False,
"user": "appuser",
"environment": [
{
"name": ENV_VAR_NAME_WITH_KEYWORD,
"value": ENV_VAR_VALUE_NO_SECRETS,
}
],
}
],
)["taskDefinition"]["taskDefinitionArn"]

from prowler.providers.aws.services.ecs.ecs_service import ECS

mocked_aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])

with patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mocked_aws_provider,
Expand All @@ -138,3 +191,167 @@ def test_container_env_var_with_secrets(self):
assert result[0].resource_arn == task_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []

@mock_aws
def test_container_env_var_with_keyword_and_secret(self):
ecs_client = client("ecs", region_name=AWS_REGION_US_EAST_1)

task_arn = ecs_client.register_task_definition(
family=TASK_NAME,
containerDefinitions=[
{
"name": CONTAINER_NAME,
"image": "ubuntu",
"memory": 128,
"readonlyRootFilesystem": True,
"privileged": False,
"user": "appuser",
"environment": [
{
"name": ENV_VAR_NAME_WITH_KEYWORD,
"value": ENV_VAR_VALUE_WITH_SECRETS,
}
],
}
],
)["taskDefinition"]["taskDefinitionArn"]

from prowler.providers.aws.services.ecs.ecs_service import ECS

mocked_aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])

with patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mocked_aws_provider,
), patch(
"prowler.providers.aws.services.ecs.ecs_task_definitions_no_environment_secrets.ecs_task_definitions_no_environment_secrets.ecs_client",
new=ECS(mocked_aws_provider),
):
from prowler.providers.aws.services.ecs.ecs_task_definitions_no_environment_secrets.ecs_task_definitions_no_environment_secrets import (
ecs_task_definitions_no_environment_secrets,
)

check = ecs_task_definitions_no_environment_secrets()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"Potential secrets found in ECS task definition {TASK_NAME} with revision {TASK_REVISION}: Secrets in container test-container -> Secret Keyword on the environment variable DB_PASSWORD, Basic Auth Credentials on the environment variable DB_PASSWORD."
)
assert result[0].resource_id == f"{TASK_NAME}:{TASK_REVISION}"
assert result[0].resource_arn == task_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []

@mock_aws
def test_container_multiple_env_vars_with_keyword_and_secret(self):
ecs_client = client("ecs", region_name=AWS_REGION_US_EAST_1)

task_arn = ecs_client.register_task_definition(
family=TASK_NAME,
containerDefinitions=[
{
"name": CONTAINER_NAME,
"image": "ubuntu",
"memory": 128,
"readonlyRootFilesystem": True,
"privileged": False,
"user": "appuser",
"environment": [
{
"name": ENV_VAR_NAME_WITH_KEYWORD,
"value": ENV_VAR_VALUE_WITH_SECRETS,
},
{
"name": ENV_VAR_NAME_NO_SECRETS,
"value": ENV_VAR_VALUE_WITH_SECRETS2,
},
],
}
],
)["taskDefinition"]["taskDefinitionArn"]

from prowler.providers.aws.services.ecs.ecs_service import ECS

mocked_aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])

with patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mocked_aws_provider,
), patch(
"prowler.providers.aws.services.ecs.ecs_task_definitions_no_environment_secrets.ecs_task_definitions_no_environment_secrets.ecs_client",
new=ECS(mocked_aws_provider),
):
from prowler.providers.aws.services.ecs.ecs_task_definitions_no_environment_secrets.ecs_task_definitions_no_environment_secrets import (
ecs_task_definitions_no_environment_secrets,
)

check = ecs_task_definitions_no_environment_secrets()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"Potential secrets found in ECS task definition {TASK_NAME} with revision {TASK_REVISION}: Secrets in container test-container -> Secret Keyword on the environment variable DB_PASSWORD, Basic Auth Credentials on the environment variable DB_PASSWORD, Basic Auth Credentials on the environment variable host."
)
assert result[0].resource_id == f"{TASK_NAME}:{TASK_REVISION}"
assert result[0].resource_arn == task_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []

@mock_aws
def test_container_all_env_vars_with_keyword_and_secret(self):
ecs_client = client("ecs", region_name=AWS_REGION_US_EAST_1)

task_arn = ecs_client.register_task_definition(
family=TASK_NAME,
containerDefinitions=[
{
"name": CONTAINER_NAME,
"image": "ubuntu",
"memory": 128,
"readonlyRootFilesystem": True,
"privileged": False,
"user": "appuser",
"environment": [
{
"name": ENV_VAR_NAME_WITH_KEYWORD,
"value": ENV_VAR_VALUE_WITH_SECRETS,
},
{
"name": ENV_VAR_NAME_WITH_KEYWORD2,
"value": ENV_VAR_VALUE_WITH_SECRETS2,
},
],
}
],
)["taskDefinition"]["taskDefinitionArn"]

from prowler.providers.aws.services.ecs.ecs_service import ECS

mocked_aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])

with patch(
"prowler.providers.common.provider.Provider.get_global_provider",
return_value=mocked_aws_provider,
), patch(
"prowler.providers.aws.services.ecs.ecs_task_definitions_no_environment_secrets.ecs_task_definitions_no_environment_secrets.ecs_client",
new=ECS(mocked_aws_provider),
):
from prowler.providers.aws.services.ecs.ecs_task_definitions_no_environment_secrets.ecs_task_definitions_no_environment_secrets import (
ecs_task_definitions_no_environment_secrets,
)

check = ecs_task_definitions_no_environment_secrets()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"Potential secrets found in ECS task definition {TASK_NAME} with revision {TASK_REVISION}: Secrets in container test-container -> Secret Keyword on the environment variable DB_PASSWORD, Basic Auth Credentials on the environment variable DB_PASSWORD, Basic Auth Credentials on the environment variable DATABASE_PASSWORD, Secret Keyword on the environment variable DATABASE_PASSWORD."
)
assert result[0].resource_id == f"{TASK_NAME}:{TASK_REVISION}"
assert result[0].resource_arn == task_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []
Loading