fix(autoscaling): Add exception manage while decoding UserData (#4675)

Co-authored-by: Rubén De la Torre Vico <rubendltv22@gmail.com>
Co-authored-by: Pepe Fagoaga <pepe@prowler.com>
Co-authored-by: Sergio <sergio@prowler.com>
This commit is contained in:
github-actions[bot]
2024-08-07 17:47:48 -04:00
committed by GitHub
parent 318d2b1e1a
commit b7c22d18ab
8 changed files with 112 additions and 14 deletions
+2 -2
View File
@@ -61,6 +61,7 @@ html_file_suffix = ".html"
default_config_file_path = (
f"{pathlib.Path(os.path.dirname(os.path.realpath(__file__)))}/config.yaml"
)
encoding_format_utf_8 = "utf-8"
def check_current_version():
@@ -102,8 +103,7 @@ def load_and_validate_config_file(provider: str, config_file_path: str) -> dict:
load_and_validate_config_file reads the Prowler config file in YAML format from the default location or the file passed with the --config-file flag
"""
try:
with open(config_file_path) as f:
config = {}
with open(config_file_path, "r", encoding=encoding_format_utf_8) as f:
config_file = yaml.safe_load(f)
# Not to introduce a breaking change we have to allow the old format config file without any provider keys
+3 -2
View File
@@ -12,13 +12,14 @@ from time import mktime
from detect_secrets import SecretsCollection
from detect_secrets.settings import default_settings
from prowler.config.config import encoding_format_utf_8
from prowler.lib.logger import logger
def open_file(input_file: str, mode: str = "r") -> TextIOWrapper:
"""open_file returns a handler to the file using the specified mode."""
try:
f = open(input_file, mode)
f = open(input_file, mode, encoding=encoding_format_utf_8)
except OSError as os_error:
if os_error.strerror == "Too many open files":
logger.critical(
@@ -66,7 +67,7 @@ def file_exists(filename: str):
def hash_sha512(string: str) -> str:
"""hash_sha512 returns the first 9 bytes of the SHA512 representation for the given string."""
return sha512(string.encode("utf-8")).hexdigest()[0:9]
return sha512(string.encode(encoding_format_utf_8)).hexdigest()[0:9]
def detect_secrets_scan(data):
@@ -6,7 +6,9 @@ from base64 import b64decode
from detect_secrets import SecretsCollection
from detect_secrets.settings import default_settings
from prowler.config.config import encoding_format_utf_8
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.lib.logger import logger
from prowler.providers.aws.services.autoscaling.autoscaling_client import (
autoscaling_client,
)
@@ -25,12 +27,23 @@ class autoscaling_find_secrets_ec2_launch_configuration(Check):
temp_user_data_file = tempfile.NamedTemporaryFile(delete=False)
user_data = b64decode(configuration.user_data)
if user_data[0:2] == b"\x1f\x8b": # GZIP magic number
user_data = zlib.decompress(user_data, zlib.MAX_WBITS | 32).decode(
"utf-8"
try:
if user_data[0:2] == b"\x1f\x8b": # GZIP magic number
user_data = zlib.decompress(
user_data, zlib.MAX_WBITS | 32
).decode(encoding_format_utf_8)
else:
user_data = user_data.decode(encoding_format_utf_8)
except UnicodeDecodeError as error:
logger.warning(
f"{configuration.region} -- Unable to decode user data in autoscaling launch configuration {configuration.name}: {error}"
)
else:
user_data = user_data.decode("utf-8")
continue
except Exception as error:
logger.warning(
f"{configuration.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
continue
temp_user_data_file.write(
bytes(user_data, encoding="raw_unicode_escape")
@@ -6,6 +6,7 @@ from base64 import b64decode
from detect_secrets import SecretsCollection
from detect_secrets.settings import default_settings
from prowler.config.config import encoding_format_utf_8
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.ec2.ec2_client import ec2_client
@@ -26,9 +27,9 @@ class ec2_instance_secrets_user_data(Check):
if user_data[0:2] == b"\x1f\x8b": # GZIP magic number
user_data = zlib.decompress(
user_data, zlib.MAX_WBITS | 32
).decode("utf-8")
).decode(encoding_format_utf_8)
else:
user_data = user_data.decode("utf-8")
user_data = user_data.decode(encoding_format_utf_8)
temp_user_data_file.write(
bytes(user_data, encoding="raw_unicode_escape")
@@ -5,6 +5,7 @@ from typing import Optional
from botocore.client import ClientError
from pydantic import BaseModel
from prowler.config.config import encoding_format_utf_8
from prowler.lib.logger import logger
from prowler.lib.scan_filters.scan_filters import is_resource_filtered
from prowler.providers.aws.lib.service.service import AWSService
@@ -144,7 +145,9 @@ class IAM(AWSService):
if report_status["State"] == "COMPLETE":
report_is_completed = True
# Convert credential report to list of dictionaries
credential = self.client.get_credential_report()["Content"].decode("utf-8")
credential = self.client.get_credential_report()["Content"].decode(
encoding_format_utf_8
)
credential_lines = credential.split("\n")
csv_reader = csv.DictReader(credential_lines, delimiter=",")
credential_list = list(csv_reader)
@@ -287,3 +287,77 @@ class Test_autoscaling_find_secrets_ec2_launch_configuration:
assert result[0].resource_id == launch_configuration_name
assert result[0].resource_arn == launch_configuration_arn
assert result[0].region == AWS_REGION_US_EAST_1
@mock_aws
def test_one_autoscaling_file_with_unicode_error(self):
# Include launch_configurations to check
invalid_utf8_bytes = b"\xc0\xaf"
launch_configuration_name = "tester"
autoscaling_client = client("autoscaling", region_name=AWS_REGION_US_EAST_1)
autoscaling_client.create_launch_configuration(
LaunchConfigurationName=launch_configuration_name,
ImageId="ami-12c6146b",
InstanceType="t1.micro",
KeyName="the_keys",
SecurityGroups=["default", "default2"],
UserData=invalid_utf8_bytes,
)
from prowler.providers.aws.services.autoscaling.autoscaling_service import (
AutoScaling,
)
current_audit_info = set_mocked_aws_audit_info([AWS_REGION_US_EAST_1])
with mock.patch(
"prowler.providers.aws.lib.audit_info.audit_info.current_audit_info",
new=current_audit_info,
), mock.patch(
"prowler.providers.aws.services.autoscaling.autoscaling_find_secrets_ec2_launch_configuration.autoscaling_find_secrets_ec2_launch_configuration.autoscaling_client",
new=AutoScaling(current_audit_info),
):
from prowler.providers.aws.services.autoscaling.autoscaling_find_secrets_ec2_launch_configuration.autoscaling_find_secrets_ec2_launch_configuration import (
autoscaling_find_secrets_ec2_launch_configuration,
)
check = autoscaling_find_secrets_ec2_launch_configuration()
result = check.execute()
assert len(result) == 0
@mock_aws
def test_one_autoscaling_file_invalid_gzip_error(self):
# Include launch_configurations to check
invalid_gzip_bytes = b"\x1f\x8b\xc0\xaf"
launch_configuration_name = "tester"
autoscaling_client = client("autoscaling", region_name=AWS_REGION_US_EAST_1)
autoscaling_client.create_launch_configuration(
LaunchConfigurationName=launch_configuration_name,
ImageId="ami-12c6146b",
InstanceType="t1.micro",
KeyName="the_keys",
SecurityGroups=["default", "default2"],
UserData=invalid_gzip_bytes,
)
from prowler.providers.aws.services.autoscaling.autoscaling_service import (
AutoScaling,
)
current_audit_info = set_mocked_aws_audit_info([AWS_REGION_US_EAST_1])
with mock.patch(
"prowler.providers.aws.lib.audit_info.audit_info.current_audit_info",
new=current_audit_info,
), mock.patch(
"prowler.providers.aws.services.autoscaling.autoscaling_find_secrets_ec2_launch_configuration.autoscaling_find_secrets_ec2_launch_configuration.autoscaling_client",
new=AutoScaling(current_audit_info),
):
from prowler.providers.aws.services.autoscaling.autoscaling_find_secrets_ec2_launch_configuration.autoscaling_find_secrets_ec2_launch_configuration import (
autoscaling_find_secrets_ec2_launch_configuration,
)
check = autoscaling_find_secrets_ec2_launch_configuration()
result = check.execute()
assert len(result) == 0
@@ -3,6 +3,7 @@ from base64 import b64decode
from boto3 import client
from moto import mock_aws
from prowler.config.config import encoding_format_utf_8
from prowler.providers.aws.services.autoscaling.autoscaling_service import AutoScaling
from tests.providers.aws.audit_info_utils import (
AWS_ACCOUNT_NUMBER,
@@ -72,7 +73,9 @@ class Test_AutoScaling_Service:
assert len(autoscaling.launch_configurations) == 2
assert autoscaling.launch_configurations[0].name == "tester1"
assert (
b64decode(autoscaling.launch_configurations[0].user_data).decode("utf-8")
b64decode(autoscaling.launch_configurations[0].user_data).decode(
encoding_format_utf_8
)
== "DB_PASSWORD=foobar123"
)
assert autoscaling.launch_configurations[0].image_id == "ami-12c6146b"
@@ -8,6 +8,7 @@ from dateutil.tz import tzutc
from freezegun import freeze_time
from moto import mock_aws
from prowler.config.config import encoding_format_utf_8
from prowler.providers.aws.services.ec2.ec2_service import EC2
from tests.providers.aws.audit_info_utils import (
AWS_ACCOUNT_NUMBER,
@@ -316,7 +317,9 @@ class Test_EC2_Service:
[AWS_REGION_EU_WEST_1, AWS_REGION_US_EAST_1]
)
ec2 = EC2(audit_info)
assert user_data == b64decode(ec2.instances[0].user_data).decode("utf-8")
assert user_data == b64decode(ec2.instances[0].user_data).decode(
encoding_format_utf_8
)
# Test EC2 Get EBS Encryption by default
@mock_aws