From cf28b814cba1d88fc16428220dc33cec81f12ff0 Mon Sep 17 00:00:00 2001 From: Sergio Garcia <38561120+sergargar@users.noreply.github.com> Date: Fri, 10 Mar 2023 08:11:35 +0100 Subject: [PATCH] fix(ec2): avoid terminated instances (#2063) --- .../ec2_instance_imdsv2_enabled.py | 33 +++++----- ...e_internet_facing_with_instance_profile.py | 23 +++---- .../ec2_instance_managed_by_ssm.py | 35 +++++----- .../ec2_instance_profile_attached.py | 23 +++---- .../ec2_instance_public_ip.py | 31 ++++----- .../ec2_instance_secrets_user_data.py | 65 ++++++++++--------- 6 files changed, 108 insertions(+), 102 deletions(-) diff --git a/prowler/providers/aws/services/ec2/ec2_instance_imdsv2_enabled/ec2_instance_imdsv2_enabled.py b/prowler/providers/aws/services/ec2/ec2_instance_imdsv2_enabled/ec2_instance_imdsv2_enabled.py index d996eb34..d9c9408a 100644 --- a/prowler/providers/aws/services/ec2/ec2_instance_imdsv2_enabled/ec2_instance_imdsv2_enabled.py +++ b/prowler/providers/aws/services/ec2/ec2_instance_imdsv2_enabled/ec2_instance_imdsv2_enabled.py @@ -6,24 +6,25 @@ class ec2_instance_imdsv2_enabled(Check): def execute(self): findings = [] for instance in ec2_client.instances: - report = Check_Report_AWS(self.metadata()) - report.region = instance.region - report.resource_id = instance.id - report.resource_arn = instance.arn - report.resource_tags = instance.tags - report.status = "FAIL" - report.status_extended = ( - f"EC2 Instance {instance.id} has IMDSv2 disabled or not required." - ) - if ( - instance.http_endpoint == "enabled" - and instance.http_tokens == "required" - ): - report.status = "PASS" + if instance.state != "terminated": + report = Check_Report_AWS(self.metadata()) + report.region = instance.region + report.resource_id = instance.id + report.resource_arn = instance.arn + report.resource_tags = instance.tags + report.status = "FAIL" report.status_extended = ( - f"EC2 Instance {instance.id} has IMDSv2 enabled and required." + f"EC2 Instance {instance.id} has IMDSv2 disabled or not required." ) + if ( + instance.http_endpoint == "enabled" + and instance.http_tokens == "required" + ): + report.status = "PASS" + report.status_extended = ( + f"EC2 Instance {instance.id} has IMDSv2 enabled and required." + ) - findings.append(report) + findings.append(report) return findings diff --git a/prowler/providers/aws/services/ec2/ec2_instance_internet_facing_with_instance_profile/ec2_instance_internet_facing_with_instance_profile.py b/prowler/providers/aws/services/ec2/ec2_instance_internet_facing_with_instance_profile/ec2_instance_internet_facing_with_instance_profile.py index 493cc9f6..8b18df75 100644 --- a/prowler/providers/aws/services/ec2/ec2_instance_internet_facing_with_instance_profile/ec2_instance_internet_facing_with_instance_profile.py +++ b/prowler/providers/aws/services/ec2/ec2_instance_internet_facing_with_instance_profile/ec2_instance_internet_facing_with_instance_profile.py @@ -6,17 +6,18 @@ class ec2_instance_internet_facing_with_instance_profile(Check): def execute(self): findings = [] for instance in ec2_client.instances: - report = Check_Report_AWS(self.metadata()) - report.region = instance.region - report.resource_id = instance.id - report.resource_arn = instance.arn - report.resource_tags = instance.tags - report.status = "PASS" - report.status_extended = f"EC2 Instance {instance.id} is not internet facing with an instance profile." - if instance.public_ip and instance.instance_profile: - report.status = "FAIL" - report.status_extended = f"EC2 Instance {instance.id} at IP {instance.public_ip} is internet-facing with Instance Profile {instance.instance_profile['Arn']}." + if instance.state != "terminated": + report = Check_Report_AWS(self.metadata()) + report.region = instance.region + report.resource_id = instance.id + report.resource_arn = instance.arn + report.resource_tags = instance.tags + report.status = "PASS" + report.status_extended = f"EC2 Instance {instance.id} is not internet facing with an instance profile." + if instance.public_ip and instance.instance_profile: + report.status = "FAIL" + report.status_extended = f"EC2 Instance {instance.id} at IP {instance.public_ip} is internet-facing with Instance Profile {instance.instance_profile['Arn']}." - findings.append(report) + findings.append(report) return findings diff --git a/prowler/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.py b/prowler/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.py index 99398e75..bb1b44e9 100644 --- a/prowler/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.py +++ b/prowler/providers/aws/services/ec2/ec2_instance_managed_by_ssm/ec2_instance_managed_by_ssm.py @@ -7,22 +7,23 @@ class ec2_instance_managed_by_ssm(Check): def execute(self): findings = [] for instance in ec2_client.instances: - report = Check_Report_AWS(self.metadata()) - report.region = instance.region - report.resource_arn = instance.arn - report.resource_tags = instance.tags - if not ssm_client.managed_instances.get(instance.id): - report.status = "FAIL" - report.status_extended = ( - f"EC2 Instance {instance.id} is not managed by Systems Manager." - ) - report.resource_id = instance.id - else: - report.status = "PASS" - report.status_extended = ( - f"EC2 Instance {instance.id} is managed by Systems Manager." - ) - report.resource_id = instance.id - findings.append(report) + if instance.state != "terminated": + report = Check_Report_AWS(self.metadata()) + report.region = instance.region + report.resource_arn = instance.arn + report.resource_tags = instance.tags + if not ssm_client.managed_instances.get(instance.id): + report.status = "FAIL" + report.status_extended = ( + f"EC2 Instance {instance.id} is not managed by Systems Manager." + ) + report.resource_id = instance.id + else: + report.status = "PASS" + report.status_extended = ( + f"EC2 Instance {instance.id} is managed by Systems Manager." + ) + report.resource_id = instance.id + findings.append(report) return findings diff --git a/prowler/providers/aws/services/ec2/ec2_instance_profile_attached/ec2_instance_profile_attached.py b/prowler/providers/aws/services/ec2/ec2_instance_profile_attached/ec2_instance_profile_attached.py index b50c343b..c6a52763 100644 --- a/prowler/providers/aws/services/ec2/ec2_instance_profile_attached/ec2_instance_profile_attached.py +++ b/prowler/providers/aws/services/ec2/ec2_instance_profile_attached/ec2_instance_profile_attached.py @@ -6,17 +6,18 @@ class ec2_instance_profile_attached(Check): def execute(self): findings = [] for instance in ec2_client.instances: - report = Check_Report_AWS(self.metadata()) - report.region = instance.region - report.resource_id = instance.id - report.resource_arn = instance.arn - report.resource_tags = instance.tags - report.status = "FAIL" - report.status_extended = f"EC2 Instance {instance.id} not associated with an Instance Profile Role." - if instance.instance_profile: - report.status = "PASS" - report.status_extended = f"EC2 Instance {instance.id} associated with Instance Profile Role {instance.instance_profile['Arn']}." + if instance.state != "terminated": + report = Check_Report_AWS(self.metadata()) + report.region = instance.region + report.resource_id = instance.id + report.resource_arn = instance.arn + report.resource_tags = instance.tags + report.status = "FAIL" + report.status_extended = f"EC2 Instance {instance.id} not associated with an Instance Profile Role." + if instance.instance_profile: + report.status = "PASS" + report.status_extended = f"EC2 Instance {instance.id} associated with Instance Profile Role {instance.instance_profile['Arn']}." - findings.append(report) + findings.append(report) return findings diff --git a/prowler/providers/aws/services/ec2/ec2_instance_public_ip/ec2_instance_public_ip.py b/prowler/providers/aws/services/ec2/ec2_instance_public_ip/ec2_instance_public_ip.py index 8a477828..3eb7fec9 100644 --- a/prowler/providers/aws/services/ec2/ec2_instance_public_ip/ec2_instance_public_ip.py +++ b/prowler/providers/aws/services/ec2/ec2_instance_public_ip/ec2_instance_public_ip.py @@ -6,20 +6,21 @@ class ec2_instance_public_ip(Check): def execute(self): findings = [] for instance in ec2_client.instances: - report = Check_Report_AWS(self.metadata()) - report.region = instance.region - report.resource_arn = instance.arn - report.resource_tags = instance.tags - if instance.public_ip: - report.status = "FAIL" - report.status_extended = f"EC2 Instance {instance.id} has a Public IP: {instance.public_ip} ({instance.public_dns})." - report.resource_id = instance.id - else: - report.status = "PASS" - report.status_extended = ( - f"EC2 Instance {instance.id} has not a Public IP." - ) - report.resource_id = instance.id - findings.append(report) + if instance.state != "terminated": + report = Check_Report_AWS(self.metadata()) + report.region = instance.region + report.resource_arn = instance.arn + report.resource_tags = instance.tags + if instance.public_ip: + report.status = "FAIL" + report.status_extended = f"EC2 Instance {instance.id} has a Public IP: {instance.public_ip} ({instance.public_dns})." + report.resource_id = instance.id + else: + report.status = "PASS" + report.status_extended = ( + f"EC2 Instance {instance.id} has not a Public IP." + ) + report.resource_id = instance.id + findings.append(report) return findings diff --git a/prowler/providers/aws/services/ec2/ec2_instance_secrets_user_data/ec2_instance_secrets_user_data.py b/prowler/providers/aws/services/ec2/ec2_instance_secrets_user_data/ec2_instance_secrets_user_data.py index 990f7aa5..0413b1f1 100644 --- a/prowler/providers/aws/services/ec2/ec2_instance_secrets_user_data/ec2_instance_secrets_user_data.py +++ b/prowler/providers/aws/services/ec2/ec2_instance_secrets_user_data/ec2_instance_secrets_user_data.py @@ -14,43 +14,44 @@ class ec2_instance_secrets_user_data(Check): def execute(self): findings = [] for instance in ec2_client.instances: - report = Check_Report_AWS(self.metadata()) - report.region = instance.region - report.resource_id = instance.id - report.resource_arn = instance.arn - report.resource_tags = instance.tags - if instance.user_data: - temp_user_data_file = tempfile.NamedTemporaryFile(delete=False) - user_data = b64decode(instance.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" + if instance.state != "terminated": + report = Check_Report_AWS(self.metadata()) + report.region = instance.region + report.resource_id = instance.id + report.resource_arn = instance.arn + report.resource_tags = instance.tags + if instance.user_data: + temp_user_data_file = tempfile.NamedTemporaryFile(delete=False) + user_data = b64decode(instance.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") + else: + user_data = user_data.decode("utf-8") + + temp_user_data_file.write( + bytes(user_data, encoding="raw_unicode_escape") ) - else: - user_data = user_data.decode("utf-8") + temp_user_data_file.close() + secrets = SecretsCollection() + with default_settings(): + secrets.scan_file(temp_user_data_file.name) - temp_user_data_file.write( - bytes(user_data, encoding="raw_unicode_escape") - ) - temp_user_data_file.close() - secrets = SecretsCollection() - with default_settings(): - secrets.scan_file(temp_user_data_file.name) + if secrets.json(): + report.status = "FAIL" + report.status_extended = f"Potential secret found in EC2 instance {instance.id} User Data." + else: + report.status = "PASS" + report.status_extended = ( + f"No secrets found in EC2 instance {instance.id} User Data." + ) - if secrets.json(): - report.status = "FAIL" - report.status_extended = f"Potential secret found in EC2 instance {instance.id} User Data." + os.remove(temp_user_data_file.name) else: report.status = "PASS" - report.status_extended = ( - f"No secrets found in EC2 instance {instance.id} User Data." - ) + report.status_extended = f"No secrets found in EC2 instance {instance.id} since User Data is empty." - os.remove(temp_user_data_file.name) - else: - report.status = "PASS" - report.status_extended = f"No secrets found in EC2 instance {instance.id} since User Data is empty." - - findings.append(report) + findings.append(report) return findings