diff --git a/prowler/providers/aws/services/ec2/ec2_ami_public/ec2_ami_public.py b/prowler/providers/aws/services/ec2/ec2_ami_public/ec2_ami_public.py index 5dabcf60..50979265 100644 --- a/prowler/providers/aws/services/ec2/ec2_ami_public/ec2_ami_public.py +++ b/prowler/providers/aws/services/ec2/ec2_ami_public/ec2_ami_public.py @@ -10,6 +10,7 @@ class ec2_ami_public(Check): report.region = image.region report.resource_id = image.id report.resource_arn = image.arn + report.resource_tags = image.tags report.status = "PASS" report.status_extended = f"EC2 AMI {image.id} is not public." if image.public: diff --git a/prowler/providers/aws/services/ec2/ec2_ebs_public_snapshot/ec2_ebs_public_snapshot.py b/prowler/providers/aws/services/ec2/ec2_ebs_public_snapshot/ec2_ebs_public_snapshot.py index 659f6b45..0b6d9390 100644 --- a/prowler/providers/aws/services/ec2/ec2_ebs_public_snapshot/ec2_ebs_public_snapshot.py +++ b/prowler/providers/aws/services/ec2/ec2_ebs_public_snapshot/ec2_ebs_public_snapshot.py @@ -9,6 +9,7 @@ class ec2_ebs_public_snapshot(Check): report = Check_Report_AWS(self.metadata()) report.region = snapshot.region report.resource_arn = snapshot.arn + report.resource_tags = snapshot.tags if not snapshot.public: report.status = "PASS" report.status_extended = f"EBS Snapshot {snapshot.id} is not Public." diff --git a/prowler/providers/aws/services/ec2/ec2_ebs_snapshots_encrypted/ec2_ebs_snapshots_encrypted.py b/prowler/providers/aws/services/ec2/ec2_ebs_snapshots_encrypted/ec2_ebs_snapshots_encrypted.py index c1ecc6ff..acd8885b 100644 --- a/prowler/providers/aws/services/ec2/ec2_ebs_snapshots_encrypted/ec2_ebs_snapshots_encrypted.py +++ b/prowler/providers/aws/services/ec2/ec2_ebs_snapshots_encrypted/ec2_ebs_snapshots_encrypted.py @@ -9,6 +9,7 @@ class ec2_ebs_snapshots_encrypted(Check): report = Check_Report_AWS(self.metadata()) report.region = snapshot.region report.resource_arn = snapshot.arn + report.resource_tags = snapshot.tags if snapshot.encrypted: report.status = "PASS" report.status_extended = f"EBS Snapshot {snapshot.id} is encrypted." diff --git a/prowler/providers/aws/services/ec2/ec2_ebs_volume_encryption/ec2_ebs_volume_encryption.py b/prowler/providers/aws/services/ec2/ec2_ebs_volume_encryption/ec2_ebs_volume_encryption.py index 9a86178d..e0dd419f 100644 --- a/prowler/providers/aws/services/ec2/ec2_ebs_volume_encryption/ec2_ebs_volume_encryption.py +++ b/prowler/providers/aws/services/ec2/ec2_ebs_volume_encryption/ec2_ebs_volume_encryption.py @@ -10,6 +10,7 @@ class ec2_ebs_volume_encryption(Check): report.region = volume.region report.resource_id = volume.id report.resource_arn = volume.arn + report.resource_tags = volume.tags if volume.encrypted: report.status = "PASS" report.status_extended = f"EBS Snapshot {volume.id} is encrypted." diff --git a/prowler/providers/aws/services/ec2/ec2_elastic_ip_shodan/ec2_elastic_ip_shodan.py b/prowler/providers/aws/services/ec2/ec2_elastic_ip_shodan/ec2_elastic_ip_shodan.py index b15728e7..12b48a2e 100644 --- a/prowler/providers/aws/services/ec2/ec2_elastic_ip_shodan/ec2_elastic_ip_shodan.py +++ b/prowler/providers/aws/services/ec2/ec2_elastic_ip_shodan/ec2_elastic_ip_shodan.py @@ -16,6 +16,7 @@ class ec2_elastic_ip_shodan(Check): report = Check_Report_AWS(self.metadata()) report.region = eip.region report.resource_arn = eip.arn + report.resource_tags = eip.tags if eip.public_ip: try: shodan_info = api.host(eip.public_ip) diff --git a/prowler/providers/aws/services/ec2/ec2_elastic_ip_unassgined/ec2_elastic_ip_unassgined.py b/prowler/providers/aws/services/ec2/ec2_elastic_ip_unassgined/ec2_elastic_ip_unassgined.py index 9472afcd..f6a26a92 100644 --- a/prowler/providers/aws/services/ec2/ec2_elastic_ip_unassgined/ec2_elastic_ip_unassgined.py +++ b/prowler/providers/aws/services/ec2/ec2_elastic_ip_unassgined/ec2_elastic_ip_unassgined.py @@ -11,6 +11,7 @@ class ec2_elastic_ip_unassgined(Check): if eip.public_ip: report.resource_id = eip.public_ip report.resource_arn = eip.arn + report.resource_tags = eip.tags report.status = "FAIL" report.status_extended = f"Elastic IP {eip.public_ip} is not associated with an instance or network interface." if eip.association_id: 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 b8e70d78..d996eb34 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 @@ -10,6 +10,7 @@ class ec2_instance_imdsv2_enabled(Check): 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." 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 9cfb6dca..493cc9f6 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 @@ -10,6 +10,7 @@ class ec2_instance_internet_facing_with_instance_profile(Check): 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: 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 1cad1a55..99398e75 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 @@ -10,6 +10,7 @@ class ec2_instance_managed_by_ssm(Check): 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 = ( diff --git a/prowler/providers/aws/services/ec2/ec2_instance_older_than_specific_days/ec2_instance_older_than_specific_days.py b/prowler/providers/aws/services/ec2/ec2_instance_older_than_specific_days/ec2_instance_older_than_specific_days.py index b5b14795..049ea4d8 100644 --- a/prowler/providers/aws/services/ec2/ec2_instance_older_than_specific_days/ec2_instance_older_than_specific_days.py +++ b/prowler/providers/aws/services/ec2/ec2_instance_older_than_specific_days/ec2_instance_older_than_specific_days.py @@ -14,6 +14,7 @@ class ec2_instance_older_than_specific_days(Check): 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 running." if instance.state == "running": 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 601aaa7b..b50c343b 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 @@ -10,6 +10,7 @@ class ec2_instance_profile_attached(Check): 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: 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 c1689544..8a477828 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 @@ -9,6 +9,7 @@ class ec2_instance_public_ip(Check): 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})." 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 cd73ac4b..990f7aa5 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 @@ -18,7 +18,7 @@ class ec2_instance_secrets_user_data(Check): 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) diff --git a/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_any_port/ec2_networkacl_allow_ingress_any_port.py b/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_any_port/ec2_networkacl_allow_ingress_any_port.py index 8a29f087..2ca4b1ff 100644 --- a/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_any_port/ec2_networkacl_allow_ingress_any_port.py +++ b/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_any_port/ec2_networkacl_allow_ingress_any_port.py @@ -13,6 +13,7 @@ class ec2_networkacl_allow_ingress_any_port(Check): report.region = network_acl.region report.resource_id = network_acl.id report.resource_arn = network_acl.arn + report.resource_tags = network_acl.tags # If some entry allows it, that ACL is not securely configured if not check_network_acl(network_acl.entries, tcp_protocol, check_port): report.status = "PASS" diff --git a/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_tcp_port_22/ec2_networkacl_allow_ingress_tcp_port_22.py b/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_tcp_port_22/ec2_networkacl_allow_ingress_tcp_port_22.py index 12b61605..d9d9d9b5 100644 --- a/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_tcp_port_22/ec2_networkacl_allow_ingress_tcp_port_22.py +++ b/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_tcp_port_22/ec2_networkacl_allow_ingress_tcp_port_22.py @@ -12,6 +12,7 @@ class ec2_networkacl_allow_ingress_tcp_port_22(Check): report = Check_Report_AWS(self.metadata()) report.region = network_acl.region report.resource_arn = network_acl.arn + report.resource_tags = network_acl.tags # If some entry allows it, that ACL is not securely configured if not check_network_acl(network_acl.entries, tcp_protocol, check_port): report.status = "PASS" diff --git a/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_tcp_port_3389/ec2_networkacl_allow_ingress_tcp_port_3389.py b/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_tcp_port_3389/ec2_networkacl_allow_ingress_tcp_port_3389.py index c2bb1777..ac1f561c 100644 --- a/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_tcp_port_3389/ec2_networkacl_allow_ingress_tcp_port_3389.py +++ b/prowler/providers/aws/services/ec2/ec2_networkacl_allow_ingress_tcp_port_3389/ec2_networkacl_allow_ingress_tcp_port_3389.py @@ -12,6 +12,7 @@ class ec2_networkacl_allow_ingress_tcp_port_3389(Check): report = Check_Report_AWS(self.metadata()) report.region = network_acl.region report.resource_arn = network_acl.arn + report.resource_tags = network_acl.tags # If some entry allows it, that ACL is not securely configured if not check_network_acl(network_acl.entries, tcp_protocol, check_port): report.status = "PASS" diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_any_port/ec2_securitygroup_allow_ingress_from_internet_to_any_port.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_any_port/ec2_securitygroup_allow_ingress_from_internet_to_any_port.py index 6fb355a5..448e37ac 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_any_port/ec2_securitygroup_allow_ingress_from_internet_to_any_port.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_any_port/ec2_securitygroup_allow_ingress_from_internet_to_any_port.py @@ -13,6 +13,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_any_port(Check): report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not all ports open to the Internet." report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: if check_security_group(ingress_rule, "-1", any_address=True): diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018.py index 2c10c917..169a76d6 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018/ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018.py @@ -12,6 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018( report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not MongoDB ports 27017 and 27018 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21.py index 55649890..cd00b33e 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21/ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21.py @@ -14,6 +14,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21(Check) report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not FTP ports 20 and 21 open to the Internet." report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: if check_security_group( diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22.py index e0e336ff..dc9a0fc5 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22.py @@ -14,6 +14,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22(Check): report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not SSH port 22 open to the Internet." report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: if check_security_group( diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389.py index d6a8daf1..9fb2d8ee 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389.py @@ -14,6 +14,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389(Check): report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Microsoft RDP port 3389 open to the Internet." report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags # Loop through every security group's ingress rule and check it for ingress_rule in security_group.ingress_rules: if check_security_group( diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888.py index b29cda3a..c5e63622 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888.py @@ -14,6 +14,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9 report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Casandra ports 7199, 8888 and 9160 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601.py index e980ecbc..53c90b41 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601.py @@ -14,6 +14,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_ki report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Elasticsearch/Kibana ports 9200, 9300 and 5601 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092.py index 8cf5fed2..7b0aa892 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092.py @@ -12,6 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092(Check report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Kafka port 9092 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211.py index 8ad741c3..b63c6d39 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211.py @@ -12,6 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211( report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Memcached port 11211 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306.py index c299d66a..85a6f6c5 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306.py @@ -12,6 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306(Check report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not MySQL port 3306 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483.py index f2eecf3a..75bb4713 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483.py @@ -12,6 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483 report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Oracle ports 1521 and 2483 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432.py index 218e6707..112febdd 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432.py @@ -12,6 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432(Ch report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Postgres port 5432 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379.py index 4430f845..023063c8 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379.py @@ -12,6 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379(Check report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Redis port 6379 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434.py index 493b8ea2..12a34c60 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434.py @@ -14,6 +14,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_ report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Microsoft SQL Server ports 1433 and 1434 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23.py index 413a227c..699f8ef9 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23/ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23.py @@ -12,6 +12,7 @@ class ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23(Check) report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has not Telnet port 23 open to the Internet." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_wide_open_public_ipv4/ec2_securitygroup_allow_wide_open_public_ipv4.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_wide_open_public_ipv4/ec2_securitygroup_allow_wide_open_public_ipv4.py index 92c17e90..4a7cb98c 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_wide_open_public_ipv4/ec2_securitygroup_allow_wide_open_public_ipv4.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_allow_wide_open_public_ipv4/ec2_securitygroup_allow_wide_open_public_ipv4.py @@ -13,6 +13,7 @@ class ec2_securitygroup_allow_wide_open_public_ipv4(Check): report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has no potential wide-open non-RFC1918 address." # Loop through every security group's ingress rule and check it diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_default_restrict_traffic/ec2_securitygroup_default_restrict_traffic.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_default_restrict_traffic/ec2_securitygroup_default_restrict_traffic.py index 3346f3e3..18d5a882 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_default_restrict_traffic/ec2_securitygroup_default_restrict_traffic.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_default_restrict_traffic/ec2_securitygroup_default_restrict_traffic.py @@ -11,6 +11,7 @@ class ec2_securitygroup_default_restrict_traffic(Check): report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags # Find default security group if security_group.name == "default": report.status = "PASS" diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_from_launch_wizard/ec2_securitygroup_from_launch_wizard.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_from_launch_wizard/ec2_securitygroup_from_launch_wizard.py index f447b2fb..4287949a 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_from_launch_wizard/ec2_securitygroup_from_launch_wizard.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_from_launch_wizard/ec2_securitygroup_from_launch_wizard.py @@ -10,6 +10,7 @@ class ec2_securitygroup_from_launch_wizard(Check): report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) was not created using the EC2 Launch Wizard." if "launch-wizard" in security_group.name: diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_in_use_without_ingress_filtering/ec2_securitygroup_in_use_without_ingress_filtering.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_in_use_without_ingress_filtering/ec2_securitygroup_in_use_without_ingress_filtering.py index cb658d7c..134df7d7 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_in_use_without_ingress_filtering/ec2_securitygroup_in_use_without_ingress_filtering.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_in_use_without_ingress_filtering/ec2_securitygroup_in_use_without_ingress_filtering.py @@ -11,6 +11,7 @@ class ec2_securitygroup_in_use_without_ingress_filtering(Check): report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has ingress filtering." for ingress_rule in security_group.ingress_rules: diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_not_used/ec2_securitygroup_not_used.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_not_used/ec2_securitygroup_not_used.py index 209d9b9f..53012ebf 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_not_used/ec2_securitygroup_not_used.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_not_used/ec2_securitygroup_not_used.py @@ -12,6 +12,7 @@ class ec2_securitygroup_not_used(Check): report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) it is being used." if len(security_group.network_interfaces) == 0: diff --git a/prowler/providers/aws/services/ec2/ec2_securitygroup_with_many_ingress_egress_rules/ec2_securitygroup_with_many_ingress_egress_rules.py b/prowler/providers/aws/services/ec2/ec2_securitygroup_with_many_ingress_egress_rules/ec2_securitygroup_with_many_ingress_egress_rules.py index cdd1d96d..c12e190a 100644 --- a/prowler/providers/aws/services/ec2/ec2_securitygroup_with_many_ingress_egress_rules/ec2_securitygroup_with_many_ingress_egress_rules.py +++ b/prowler/providers/aws/services/ec2/ec2_securitygroup_with_many_ingress_egress_rules/ec2_securitygroup_with_many_ingress_egress_rules.py @@ -12,6 +12,7 @@ class ec2_securitygroup_with_many_ingress_egress_rules(Check): report.region = security_group.region report.resource_id = security_group.id report.resource_arn = security_group.arn + report.resource_tags = security_group.tags report.status = "PASS" report.status_extended = f"Security group {security_group.name} ({security_group.id}) has {len(security_group.ingress_rules)} inbound rules and {len(security_group.egress_rules)} outbound rules" if ( diff --git a/prowler/providers/aws/services/ec2/ec2_service.py b/prowler/providers/aws/services/ec2/ec2_service.py index f59863d0..4fb32a21 100644 --- a/prowler/providers/aws/services/ec2/ec2_service.py +++ b/prowler/providers/aws/services/ec2/ec2_service.py @@ -1,7 +1,9 @@ import threading -from dataclasses import dataclass +from datetime import datetime +from typing import Optional from botocore.client import ClientError +from pydantic import BaseModel from prowler.lib.logger import logger from prowler.lib.scan_filters.scan_filters import is_resource_filtered @@ -86,20 +88,21 @@ class EC2: self.instances.append( Instance( - instance["InstanceId"], - arn, - instance["State"]["Name"], - regional_client.region, - instance["InstanceType"], - instance["ImageId"], - instance["LaunchTime"], - instance["PrivateDnsName"], - private_ip, - public_dns, - public_ip, - http_tokens, - http_endpoint, - instance_profile, + id=instance["InstanceId"], + arn=arn, + state=instance["State"]["Name"], + region=regional_client.region, + type=instance["InstanceType"], + image_id=instance["ImageId"], + launch_time=instance["LaunchTime"], + private_dns=instance["PrivateDnsName"], + private_ip=private_ip, + public_dns=public_dns, + public_ip=public_ip, + http_tokens=http_tokens, + http_endpoint=http_endpoint, + instance_profile=instance_profile, + tags=instance.get("Tags"), ) ) except Exception as error: @@ -121,12 +124,13 @@ class EC2: ): self.security_groups.append( SecurityGroup( - sg["GroupName"], - arn, - regional_client.region, - sg["GroupId"], - sg["IpPermissions"], - sg["IpPermissionsEgress"], + name=sg["GroupName"], + arn=arn, + region=regional_client.region, + id=sg["GroupId"], + ingress_rules=sg["IpPermissions"], + egress_rules=sg["IpPermissionsEgress"], + tags=sg.get("Tags"), ) ) except Exception as error: @@ -148,10 +152,11 @@ class EC2: ): self.network_acls.append( NetworkACL( - nacl["NetworkAclId"], - arn, - regional_client.region, - nacl["Entries"], + id=nacl["NetworkAclId"], + arn=arn, + region=regional_client.region, + entries=nacl["Entries"], + tags=nacl.get("Tags"), ) ) except Exception as error: @@ -176,10 +181,11 @@ class EC2: encrypted = True self.snapshots.append( Snapshot( - snapshot["SnapshotId"], - arn, - regional_client.region, - encrypted, + id=snapshot["SnapshotId"], + arn=arn, + region=regional_client.region, + encrypted=encrypted, + tags=snapshot.get("Tags"), ) ) except Exception as error: @@ -264,11 +270,12 @@ class EC2: public = True self.images.append( Image( - image["ImageId"], - arn, - image["Name"], - public, - regional_client.region, + id=image["ImageId"], + arn=arn, + name=image["Name"], + public=public, + region=regional_client.region, + tags=image.get("Tags"), ) ) except Exception as error: @@ -290,10 +297,11 @@ class EC2: ): self.volumes.append( Volume( - volume["VolumeId"], - arn, - regional_client.region, - volume["Encrypted"], + id=volume["VolumeId"], + arn=arn, + region=regional_client.region, + encrypted=volume["Encrypted"], + tags=volume.get("Tags"), ) ) except Exception as error: @@ -320,11 +328,12 @@ class EC2: ): self.elastic_ips.append( ElasticIP( - public_ip, - association_id, - allocation_id, - elastic_ip_arn, - regional_client.region, + public_ip=public_ip, + association_id=association_id, + allocation_id=allocation_id, + arn=elastic_ip_arn, + region=regional_client.region, + tags=address.get("Tags"), ) ) except Exception as error: @@ -337,10 +346,10 @@ class EC2: try: self.ebs_encryption_by_default.append( EbsEncryptionByDefault( - regional_client.get_ebs_encryption_by_default()[ + status=regional_client.get_ebs_encryption_by_default()[ "EbsEncryptionByDefault" ], - regional_client.region, + region=regional_client.region, ) ) except Exception as error: @@ -349,159 +358,79 @@ class EC2: ) -@dataclass -class Instance: +class Instance(BaseModel): id: str arn: str state: str region: str type: str image_id: str - launch_time: str + launch_time: datetime private_dns: str - private_ip: str - public_dns: str - public_ip: str - user_data: str - http_tokens: str - http_endpoint: str - instance_profile: str - - def __init__( - self, - id, - arn, - state, - region, - type, - image_id, - launch_time, - private_dns, - private_ip, - public_dns, - public_ip, - http_tokens, - http_endpoint, - instance_profile, - ): - self.id = id - self.arn = arn - self.state = state - self.region = region - self.type = type - self.image_id = image_id - self.launch_time = launch_time - self.private_dns = private_dns - self.private_ip = private_ip - self.public_dns = public_dns - self.public_ip = public_ip - self.http_tokens = http_tokens - self.http_endpoint = http_endpoint - self.user_data = None - self.instance_profile = instance_profile + private_ip: Optional[str] + public_dns: Optional[str] + public_ip: Optional[str] + user_data: Optional[str] + http_tokens: Optional[str] + http_endpoint: Optional[str] + instance_profile: Optional[dict] + tags: Optional[list] = [] -@dataclass -class Snapshot: +class Snapshot(BaseModel): id: str arn: str region: str encrypted: bool - public: bool - - def __init__(self, id, arn, region, encrypted): - self.id = id - self.arn = arn - self.region = region - self.encrypted = encrypted - self.public = False + public: bool = False + tags: Optional[list] = [] -@dataclass -class Volume: +class Volume(BaseModel): id: str arn: str region: str encrypted: bool - - def __init__(self, id, arn, region, encrypted): - self.id = id - self.arn = arn - self.region = region - self.encrypted = encrypted + tags: Optional[list] = [] -@dataclass -class SecurityGroup: +class SecurityGroup(BaseModel): name: str arn: str region: str id: str - network_interfaces: list[str] + network_interfaces: list[str] = [] ingress_rules: list[dict] egress_rules: list[dict] - - def __init__(self, name, arn, region, id, ingress_rules, egress_rules): - self.name = name - self.arn = arn - self.region = region - self.id = id - self.ingress_rules = ingress_rules - self.egress_rules = egress_rules - self.network_interfaces = [] + tags: Optional[list] = [] -@dataclass -class NetworkACL: +class NetworkACL(BaseModel): id: str arn: str region: str entries: list[dict] - - def __init__(self, id, arn, region, entries): - self.id = id - self.arn = arn - self.region = region - self.entries = entries + tags: Optional[list] = [] -@dataclass -class ElasticIP: - public_ip: str - association_id: str +class ElasticIP(BaseModel): + public_ip: Optional[str] + association_id: Optional[str] arn: str - allocation_id: str + allocation_id: Optional[str] region: str - - def __init__(self, public_ip, association_id, allocation_id, arn, region): - self.public_ip = public_ip - self.association_id = association_id - self.allocation_id = allocation_id - self.arn = arn - self.region = region + tags: Optional[list] = [] -@dataclass -class Image: +class Image(BaseModel): id: str arn: str name: str public: bool region: str - - def __init__(self, id, arn, name, public, region): - self.id = id - self.arn = arn - self.name = name - self.public = public - self.region = region + tags: Optional[list] = [] -@dataclass -class EbsEncryptionByDefault: +class EbsEncryptionByDefault(BaseModel): status: bool region: str - - def __init__(self, status, region): - self.status = status - self.region = region diff --git a/prowler/providers/aws/services/ecr/ecr_repositories_lifecycle_policy_enabled/ecr_repositories_lifecycle_policy_enabled.py b/prowler/providers/aws/services/ecr/ecr_repositories_lifecycle_policy_enabled/ecr_repositories_lifecycle_policy_enabled.py index 3bf13af5..82542e4a 100644 --- a/prowler/providers/aws/services/ecr/ecr_repositories_lifecycle_policy_enabled/ecr_repositories_lifecycle_policy_enabled.py +++ b/prowler/providers/aws/services/ecr/ecr_repositories_lifecycle_policy_enabled/ecr_repositories_lifecycle_policy_enabled.py @@ -10,6 +10,7 @@ class ecr_repositories_lifecycle_policy_enabled(Check): report.region = repository.region report.resource_id = repository.name report.resource_arn = repository.arn + report.resource_tags = repository.tags report.status = "FAIL" report.status_extended = ( f"Repository {repository.name} has no lifecycle policy" diff --git a/prowler/providers/aws/services/ecr/ecr_repositories_not_publicly_accessible/ecr_repositories_not_publicly_accessible.py b/prowler/providers/aws/services/ecr/ecr_repositories_not_publicly_accessible/ecr_repositories_not_publicly_accessible.py index 90d341f9..e92bc6e2 100644 --- a/prowler/providers/aws/services/ecr/ecr_repositories_not_publicly_accessible/ecr_repositories_not_publicly_accessible.py +++ b/prowler/providers/aws/services/ecr/ecr_repositories_not_publicly_accessible/ecr_repositories_not_publicly_accessible.py @@ -10,6 +10,7 @@ class ecr_repositories_not_publicly_accessible(Check): report.region = repository.region report.resource_id = repository.name report.resource_arn = repository.arn + report.resource_tags = repository.tags report.status = "PASS" report.status_extended = f"Repository {repository.name} is not open" if repository.policy: diff --git a/prowler/providers/aws/services/ecr/ecr_repositories_scan_images_on_push_enabled/ecr_repositories_scan_images_on_push_enabled.py b/prowler/providers/aws/services/ecr/ecr_repositories_scan_images_on_push_enabled/ecr_repositories_scan_images_on_push_enabled.py index f82876a4..f35b91f2 100644 --- a/prowler/providers/aws/services/ecr/ecr_repositories_scan_images_on_push_enabled/ecr_repositories_scan_images_on_push_enabled.py +++ b/prowler/providers/aws/services/ecr/ecr_repositories_scan_images_on_push_enabled/ecr_repositories_scan_images_on_push_enabled.py @@ -10,6 +10,7 @@ class ecr_repositories_scan_images_on_push_enabled(Check): report.region = repository.region report.resource_id = repository.name report.resource_arn = repository.arn + report.resource_tags = repository.tags report.status = "PASS" report.status_extended = ( f"ECR repository {repository.name} has scan on push enabled" diff --git a/prowler/providers/aws/services/ecr/ecr_repositories_scan_vulnerabilities_in_latest_image/ecr_repositories_scan_vulnerabilities_in_latest_image.py b/prowler/providers/aws/services/ecr/ecr_repositories_scan_vulnerabilities_in_latest_image/ecr_repositories_scan_vulnerabilities_in_latest_image.py index 8cea6b04..8cd62167 100644 --- a/prowler/providers/aws/services/ecr/ecr_repositories_scan_vulnerabilities_in_latest_image/ecr_repositories_scan_vulnerabilities_in_latest_image.py +++ b/prowler/providers/aws/services/ecr/ecr_repositories_scan_vulnerabilities_in_latest_image/ecr_repositories_scan_vulnerabilities_in_latest_image.py @@ -11,6 +11,7 @@ class ecr_repositories_scan_vulnerabilities_in_latest_image(Check): report.region = repository.region report.resource_id = repository.name report.resource_arn = repository.arn + report.resource_tags = repository.tags report.status = "PASS" report.status_extended = f"ECR repository {repository.name} has imageTag {image.latest_tag} scanned without findings" if not image.scan_findings_status: diff --git a/prowler/providers/aws/services/ecr/ecr_service.py b/prowler/providers/aws/services/ecr/ecr_service.py index 87d96695..97946185 100644 --- a/prowler/providers/aws/services/ecr/ecr_service.py +++ b/prowler/providers/aws/services/ecr/ecr_service.py @@ -1,6 +1,8 @@ import threading -from dataclasses import dataclass from json import loads +from typing import Optional + +from pydantic import BaseModel from prowler.lib.logger import logger from prowler.lib.scan_filters.scan_filters import is_resource_filtered @@ -19,6 +21,7 @@ class ECR: self.__describe_repository_policies__() self.__get_image_details__() self.__get_repository_lifecycle_policy__() + self.__list_tags_for_resource__() def __get_session__(self): return self.session @@ -104,7 +107,6 @@ class ECR: for page in describe_images_paginator.paginate( repositoryName=repository.name ): - for image in page["imageDetails"]: severity_counts = None last_scan_status = None @@ -147,61 +149,40 @@ class ECR: f"-- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + def __list_tags_for_resource__(self): + logger.info("ECR - List Tags...") + try: + for repository in self.repositories: + regional_client = self.regional_clients[repository.region] + response = regional_client.list_tags_for_resource( + resourceArn=repository.arn + )["tags"] + repository.tags = response + except Exception as error: + logger.error( + f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) -@dataclass -class FindingSeverityCounts: + +class FindingSeverityCounts(BaseModel): critical: int high: int medium: int - def __init__( - self, - critical, - high, - medium, - ): - self.critical = critical - self.high = high - self.medium = medium - -@dataclass -class ImageDetails: +class ImageDetails(BaseModel): latest_tag: str latest_digest: str - scan_findings_status: str - scan_findings_severity_count: FindingSeverityCounts - - def __init__( - self, - latest_tag, - latest_digest, - scan_findings_status, - scan_findings_severity_count, - ): - self.latest_tag = latest_tag - self.latest_digest = latest_digest - self.scan_findings_status = scan_findings_status - self.scan_findings_severity_count = scan_findings_severity_count + scan_findings_status: Optional[str] + scan_findings_severity_count: Optional[FindingSeverityCounts] -@dataclass -class Repository: +class Repository(BaseModel): name: str arn: str region: str scan_on_push: bool - policy: dict - images_details: list[ImageDetails] - lyfecicle_policy: str - - def __init__( - self, name, arn, region, scan_on_push, policy, images_details, lyfecicle_policy - ): - self.name = name - self.arn = arn - self.region = region - self.scan_on_push = scan_on_push - self.policy = policy - self.images_details = images_details - self.lyfecicle_policy = lyfecicle_policy + policy: Optional[dict] + images_details: Optional[list[ImageDetails]] + lyfecicle_policy: Optional[str] + tags: Optional[list] = [] diff --git a/prowler/providers/aws/services/ecs/ecs_service.py b/prowler/providers/aws/services/ecs/ecs_service.py index 84e07571..55c4c169 100644 --- a/prowler/providers/aws/services/ecs/ecs_service.py +++ b/prowler/providers/aws/services/ecs/ecs_service.py @@ -1,5 +1,6 @@ import threading from re import sub +from typing import Optional from pydantic import BaseModel @@ -34,7 +35,6 @@ class ECS: def __list_task_definitions__(self, regional_client): logger.info("ECS - Listing Task Definitions...") try: - list_ecs_paginator = regional_client.get_paginator("list_task_definitions") for page in list_ecs_paginator.paginate(): for task_definition in page["taskDefinitionArns"]: @@ -61,9 +61,15 @@ class ECS: try: for task_definition in self.task_definitions: client = self.regional_clients[task_definition.region] - container_definitions = client.describe_task_definition( - taskDefinition=task_definition.arn - )["taskDefinition"]["containerDefinitions"] + response = client.describe_task_definition( + taskDefinition=task_definition.arn, + include=[ + "TAGS", + ], + ) + container_definitions = response["taskDefinition"][ + "containerDefinitions" + ] for container in container_definitions: if "environment" in container: for env_var in container["environment"]: @@ -72,6 +78,7 @@ class ECS: name=env_var["name"], value=env_var["value"] ) ) + task_definition.tags = response.get("tags") except Exception as error: logger.error( f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" @@ -89,3 +96,4 @@ class TaskDefinition(BaseModel): revision: str region: str environment_variables: list[ContainerEnvVariable] + tags: Optional[list] = [] diff --git a/prowler/providers/aws/services/ecs/ecs_task_definitions_no_environment_secrets/ecs_task_definitions_no_environment_secrets.py b/prowler/providers/aws/services/ecs/ecs_task_definitions_no_environment_secrets/ecs_task_definitions_no_environment_secrets.py index 908dd520..4d55f612 100644 --- a/prowler/providers/aws/services/ecs/ecs_task_definitions_no_environment_secrets/ecs_task_definitions_no_environment_secrets.py +++ b/prowler/providers/aws/services/ecs/ecs_task_definitions_no_environment_secrets/ecs_task_definitions_no_environment_secrets.py @@ -17,6 +17,7 @@ class ecs_task_definitions_no_environment_secrets(Check): report.region = task_definition.region report.resource_id = f"{task_definition.name}:{task_definition.revision}" report.resource_arn = task_definition.arn + report.resource_tags = task_definition.tags report.status = "PASS" report.status_extended = f"No secrets found in variables of ECS task definition {task_definition.name} with revision {task_definition.revision}" if task_definition.environment_variables: diff --git a/prowler/providers/aws/services/efs/efs_encryption_at_rest_enabled/efs_encryption_at_rest_enabled.py b/prowler/providers/aws/services/efs/efs_encryption_at_rest_enabled/efs_encryption_at_rest_enabled.py index 38b9a34d..d503af15 100644 --- a/prowler/providers/aws/services/efs/efs_encryption_at_rest_enabled/efs_encryption_at_rest_enabled.py +++ b/prowler/providers/aws/services/efs/efs_encryption_at_rest_enabled/efs_encryption_at_rest_enabled.py @@ -9,6 +9,7 @@ class efs_encryption_at_rest_enabled(Check): report = Check_Report_AWS(self.metadata()) report.region = fs.region report.resource_id = fs.id + report.resource_tags = fs.tags report.resource_arn = "" report.status = "FAIL" report.status_extended = ( diff --git a/prowler/providers/aws/services/efs/efs_have_backup_enabled/efs_have_backup_enabled.py b/prowler/providers/aws/services/efs/efs_have_backup_enabled/efs_have_backup_enabled.py index 81473c0b..158e8ebe 100644 --- a/prowler/providers/aws/services/efs/efs_have_backup_enabled/efs_have_backup_enabled.py +++ b/prowler/providers/aws/services/efs/efs_have_backup_enabled/efs_have_backup_enabled.py @@ -10,6 +10,7 @@ class efs_have_backup_enabled(Check): report.region = fs.region report.resource_id = fs.id report.resource_arn = "" + report.resource_tags = fs.tags report.status = "PASS" report.status_extended = f"EFS {fs.id} has backup enabled" if fs.backup_policy == "DISABLED" or fs.backup_policy == "DISABLING": diff --git a/prowler/providers/aws/services/efs/efs_not_publicly_accessible/efs_not_publicly_accessible.py b/prowler/providers/aws/services/efs/efs_not_publicly_accessible/efs_not_publicly_accessible.py index 2b2d3437..5200fd51 100644 --- a/prowler/providers/aws/services/efs/efs_not_publicly_accessible/efs_not_publicly_accessible.py +++ b/prowler/providers/aws/services/efs/efs_not_publicly_accessible/efs_not_publicly_accessible.py @@ -10,6 +10,7 @@ class efs_not_publicly_accessible(Check): report.region = fs.region report.resource_id = fs.id report.resource_arn = "" + report.resource_tags = fs.tags report.status = "PASS" report.status_extended = ( f"EFS {fs.id} has policy which does not allow access to everyone" diff --git a/prowler/providers/aws/services/efs/efs_service.py b/prowler/providers/aws/services/efs/efs_service.py index 86a0f6bd..6e84b65f 100644 --- a/prowler/providers/aws/services/efs/efs_service.py +++ b/prowler/providers/aws/services/efs/efs_service.py @@ -1,8 +1,9 @@ import json import threading -from dataclasses import dataclass +from typing import Optional from botocore.client import ClientError +from pydantic import BaseModel from prowler.lib.logger import logger from prowler.lib.scan_filters.scan_filters import is_resource_filtered @@ -50,6 +51,7 @@ class EFS: policy=None, backup_policy=None, encrypted=efs["Encrypted"], + tags=efs.get("Tags"), ) ) except Exception as error: @@ -85,24 +87,10 @@ class EFS: ) -@dataclass -class FileSystem: +class FileSystem(BaseModel): id: str region: str - policy: dict - backup_policy: str + policy: Optional[dict] + backup_policy: Optional[str] encrypted: bool - - def __init__( - self, - id, - region, - policy, - backup_policy, - encrypted, - ): - self.id = id - self.region = region - self.policy = policy - self.backup_policy = backup_policy - self.encrypted = encrypted + tags: Optional[list] = [] diff --git a/prowler/providers/aws/services/eks/eks_cluster_kms_cmk_encryption_in_secrets_enabled/eks_cluster_kms_cmk_encryption_in_secrets_enabled.py b/prowler/providers/aws/services/eks/eks_cluster_kms_cmk_encryption_in_secrets_enabled/eks_cluster_kms_cmk_encryption_in_secrets_enabled.py index ec6f8a88..8fc85ca9 100644 --- a/prowler/providers/aws/services/eks/eks_cluster_kms_cmk_encryption_in_secrets_enabled/eks_cluster_kms_cmk_encryption_in_secrets_enabled.py +++ b/prowler/providers/aws/services/eks/eks_cluster_kms_cmk_encryption_in_secrets_enabled/eks_cluster_kms_cmk_encryption_in_secrets_enabled.py @@ -10,6 +10,7 @@ class eks_cluster_kms_cmk_encryption_in_secrets_enabled(Check): report.region = cluster.region report.resource_id = cluster.name report.resource_arn = cluster.arn + report.resource_tags = cluster.tags report.status = "FAIL" report.status_extended = ( f"EKS cluster {cluster.name} has not encryption for Kubernetes secrets." diff --git a/prowler/providers/aws/services/eks/eks_control_plane_endpoint_access_restricted/eks_control_plane_endpoint_access_restricted.py b/prowler/providers/aws/services/eks/eks_control_plane_endpoint_access_restricted/eks_control_plane_endpoint_access_restricted.py index 4f836a67..427d2989 100644 --- a/prowler/providers/aws/services/eks/eks_control_plane_endpoint_access_restricted/eks_control_plane_endpoint_access_restricted.py +++ b/prowler/providers/aws/services/eks/eks_control_plane_endpoint_access_restricted/eks_control_plane_endpoint_access_restricted.py @@ -10,6 +10,7 @@ class eks_control_plane_endpoint_access_restricted(Check): report.region = cluster.region report.resource_id = cluster.name report.resource_arn = cluster.arn + report.resource_tags = cluster.tags report.status = "PASS" report.status_extended = ( f"Cluster endpoint access is private for EKS cluster {cluster.name}" diff --git a/prowler/providers/aws/services/eks/eks_control_plane_logging_all_types_enabled/eks_control_plane_logging_all_types_enabled.py b/prowler/providers/aws/services/eks/eks_control_plane_logging_all_types_enabled/eks_control_plane_logging_all_types_enabled.py index 243468b3..39718df0 100644 --- a/prowler/providers/aws/services/eks/eks_control_plane_logging_all_types_enabled/eks_control_plane_logging_all_types_enabled.py +++ b/prowler/providers/aws/services/eks/eks_control_plane_logging_all_types_enabled/eks_control_plane_logging_all_types_enabled.py @@ -10,6 +10,7 @@ class eks_control_plane_logging_all_types_enabled(Check): report.region = cluster.region report.resource_id = cluster.name report.resource_arn = cluster.arn + report.resource_tags = cluster.tags report.status = "FAIL" report.status_extended = ( f"Control plane logging is not enabled for EKS cluster {cluster.name}" diff --git a/prowler/providers/aws/services/eks/eks_endpoints_not_publicly_accessible/eks_endpoints_not_publicly_accessible.py b/prowler/providers/aws/services/eks/eks_endpoints_not_publicly_accessible/eks_endpoints_not_publicly_accessible.py index 75ccbadb..f3b6aeb8 100644 --- a/prowler/providers/aws/services/eks/eks_endpoints_not_publicly_accessible/eks_endpoints_not_publicly_accessible.py +++ b/prowler/providers/aws/services/eks/eks_endpoints_not_publicly_accessible/eks_endpoints_not_publicly_accessible.py @@ -10,6 +10,7 @@ class eks_endpoints_not_publicly_accessible(Check): report.region = cluster.region report.resource_id = cluster.name report.resource_arn = cluster.arn + report.resource_tags = cluster.tags report.status = "PASS" report.status_extended = ( f"Cluster endpoint access is private for EKS cluster {cluster.name}" diff --git a/prowler/providers/aws/services/eks/eks_service.py b/prowler/providers/aws/services/eks/eks_service.py index c12d3a78..af9ff849 100644 --- a/prowler/providers/aws/services/eks/eks_service.py +++ b/prowler/providers/aws/services/eks/eks_service.py @@ -1,4 +1,5 @@ import threading +from typing import Optional from pydantic import BaseModel @@ -90,6 +91,7 @@ class EKS: ]["publicAccessCidrs"] if "encryptionConfig" in describe_cluster["cluster"]: cluster.encryptionConfig = True + cluster.tags = [describe_cluster["cluster"].get("tags")] except Exception as error: logger.error( @@ -111,3 +113,4 @@ class EKSCluster(BaseModel): endpoint_private_access: bool = None public_access_cidrs: list[str] = None encryptionConfig: bool = None + tags: Optional[list] = [] diff --git a/prowler/providers/aws/services/elb/elb_insecure_ssl_ciphers/elb_insecure_ssl_ciphers.py b/prowler/providers/aws/services/elb/elb_insecure_ssl_ciphers/elb_insecure_ssl_ciphers.py index 9301e6d7..eff89818 100644 --- a/prowler/providers/aws/services/elb/elb_insecure_ssl_ciphers/elb_insecure_ssl_ciphers.py +++ b/prowler/providers/aws/services/elb/elb_insecure_ssl_ciphers/elb_insecure_ssl_ciphers.py @@ -12,6 +12,7 @@ class elb_insecure_ssl_ciphers(Check): report = Check_Report_AWS(self.metadata()) report.region = lb.region report.resource_id = lb.name + report.resource_tags = lb.tags report.status = "PASS" report.status_extended = ( f"ELB {lb.name} has not insecure SSL protocols or ciphers." diff --git a/prowler/providers/aws/services/elb/elb_internet_facing/elb_internet_facing.py b/prowler/providers/aws/services/elb/elb_internet_facing/elb_internet_facing.py index 77a7427f..6a1c0bff 100644 --- a/prowler/providers/aws/services/elb/elb_internet_facing/elb_internet_facing.py +++ b/prowler/providers/aws/services/elb/elb_internet_facing/elb_internet_facing.py @@ -9,6 +9,7 @@ class elb_internet_facing(Check): report = Check_Report_AWS(self.metadata()) report.region = lb.region report.resource_id = lb.name + report.resource_tags = lb.tags report.status = "PASS" report.status_extended = f"ELB {lb.name} is not internet facing." if lb.scheme == "internet-facing": diff --git a/prowler/providers/aws/services/elb/elb_logging_enabled/elb_logging_enabled.py b/prowler/providers/aws/services/elb/elb_logging_enabled/elb_logging_enabled.py index 8822bd60..91eee1e0 100644 --- a/prowler/providers/aws/services/elb/elb_logging_enabled/elb_logging_enabled.py +++ b/prowler/providers/aws/services/elb/elb_logging_enabled/elb_logging_enabled.py @@ -9,6 +9,7 @@ class elb_logging_enabled(Check): report = Check_Report_AWS(self.metadata()) report.region = lb.region report.resource_id = lb.name + report.resource_tags = lb.tags report.status = "FAIL" report.status_extended = f"ELB {lb.name} has not configured access logs." if lb.access_logs: diff --git a/prowler/providers/aws/services/elb/elb_service.py b/prowler/providers/aws/services/elb/elb_service.py index d48a47d6..5bf355e3 100644 --- a/prowler/providers/aws/services/elb/elb_service.py +++ b/prowler/providers/aws/services/elb/elb_service.py @@ -20,6 +20,7 @@ class ELB: self.loadbalancers = [] self.__threading_call__(self.__describe_load_balancers__) self.__threading_call__(self.__describe_load_balancer_attributes__) + self.__describe_tags__() def __get_session__(self): return self.session @@ -85,6 +86,20 @@ class ELB: f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + def __describe_tags__(self): + logger.info("ELB - List Tags...") + try: + for lb in self.loadbalancers: + regional_client = self.regional_clients[lb.region] + response = regional_client.describe_tags(LoadBalancerNames=[lb.name])[ + "TagDescriptions" + ][0] + lb.tags = response.get("Tags") + except Exception as error: + logger.error( + f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + class Listener(BaseModel): protocol: str @@ -99,3 +114,4 @@ class LoadBalancer(BaseModel): scheme: str access_logs: Optional[bool] listeners: list[Listener] + tags: Optional[list] = [] diff --git a/prowler/providers/aws/services/elb/elb_ssl_listeners/elb_ssl_listeners.py b/prowler/providers/aws/services/elb/elb_ssl_listeners/elb_ssl_listeners.py index 3b035472..ea703b93 100644 --- a/prowler/providers/aws/services/elb/elb_ssl_listeners/elb_ssl_listeners.py +++ b/prowler/providers/aws/services/elb/elb_ssl_listeners/elb_ssl_listeners.py @@ -10,6 +10,7 @@ class elb_ssl_listeners(Check): report = Check_Report_AWS(self.metadata()) report.region = lb.region report.resource_id = lb.name + report.resource_tags = lb.tags report.status = "PASS" report.status_extended = f"ELB {lb.name} has HTTPS listeners only." for listener in lb.listeners: diff --git a/prowler/providers/aws/services/elbv2/elbv2_deletion_protection/elbv2_deletion_protection.py b/prowler/providers/aws/services/elbv2/elbv2_deletion_protection/elbv2_deletion_protection.py index eaf0d02b..6ef436be 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_deletion_protection/elbv2_deletion_protection.py +++ b/prowler/providers/aws/services/elbv2/elbv2_deletion_protection/elbv2_deletion_protection.py @@ -10,6 +10,7 @@ class elbv2_deletion_protection(Check): report.region = lb.region report.resource_id = lb.name report.resource_arn = lb.arn + report.resource_tags = lb.tags report.status = "FAIL" report.status_extended = f"ELBv2 {lb.name} has not deletion protection." if lb.deletion_protection == "true": diff --git a/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.py b/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.py index 076840a0..5dba8731 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.py +++ b/prowler/providers/aws/services/elbv2/elbv2_desync_mitigation_mode/elbv2_desync_mitigation_mode.py @@ -11,6 +11,7 @@ class elbv2_desync_mitigation_mode(Check): report.region = lb.region report.resource_id = lb.name report.resource_arn = lb.arn + report.resource_tags = lb.tags report.status = "PASS" report.status_extended = f"ELBv2 ALB {lb.name} is configured with correct desync mitigation mode." if lb.desync_mitigation_mode == "monitor": diff --git a/prowler/providers/aws/services/elbv2/elbv2_insecure_ssl_ciphers/elbv2_insecure_ssl_ciphers.py b/prowler/providers/aws/services/elbv2/elbv2_insecure_ssl_ciphers/elbv2_insecure_ssl_ciphers.py index c25dc9c0..94441e95 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_insecure_ssl_ciphers/elbv2_insecure_ssl_ciphers.py +++ b/prowler/providers/aws/services/elbv2/elbv2_insecure_ssl_ciphers/elbv2_insecure_ssl_ciphers.py @@ -22,6 +22,7 @@ class elbv2_insecure_ssl_ciphers(Check): report.region = lb.region report.resource_id = lb.name report.resource_arn = lb.arn + report.resource_tags = lb.tags report.status = "PASS" report.status_extended = ( f"ELBv2 {lb.name} has not insecure SSL protocols or ciphers." diff --git a/prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.py b/prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.py index 1dd14166..dc310b9b 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.py +++ b/prowler/providers/aws/services/elbv2/elbv2_internet_facing/elbv2_internet_facing.py @@ -10,6 +10,7 @@ class elbv2_internet_facing(Check): report.region = lb.region report.resource_id = lb.name report.resource_arn = lb.arn + report.resource_tags = lb.tags report.status = "PASS" report.status_extended = f"ELBv2 ALB {lb.name} is not internet facing." if lb.scheme == "internet-facing": diff --git a/prowler/providers/aws/services/elbv2/elbv2_listeners_underneath/elbv2_listeners_underneath.py b/prowler/providers/aws/services/elbv2/elbv2_listeners_underneath/elbv2_listeners_underneath.py index 3f47cb26..673e9d5b 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_listeners_underneath/elbv2_listeners_underneath.py +++ b/prowler/providers/aws/services/elbv2/elbv2_listeners_underneath/elbv2_listeners_underneath.py @@ -10,6 +10,7 @@ class elbv2_listeners_underneath(Check): report.region = lb.region report.resource_id = lb.name report.resource_arn = lb.arn + report.resource_tags = lb.tags report.status = "PASS" report.status_extended = f"ELBv2 {lb.name} has listeners underneath." if len(lb.listeners) == 0: diff --git a/prowler/providers/aws/services/elbv2/elbv2_logging_enabled/elbv2_logging_enabled.py b/prowler/providers/aws/services/elbv2/elbv2_logging_enabled/elbv2_logging_enabled.py index 254b8530..c79e1731 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_logging_enabled/elbv2_logging_enabled.py +++ b/prowler/providers/aws/services/elbv2/elbv2_logging_enabled/elbv2_logging_enabled.py @@ -10,6 +10,7 @@ class elbv2_logging_enabled(Check): report.region = lb.region report.resource_id = lb.name report.resource_arn = lb.arn + report.resource_tags = lb.tags report.status = "FAIL" report.status_extended = ( f"ELBv2 ALB {lb.name} has not configured access logs." diff --git a/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.py b/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.py index 288a7ba7..263c408b 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.py +++ b/prowler/providers/aws/services/elbv2/elbv2_request_smugling/elbv2_request_smugling.py @@ -11,6 +11,7 @@ class elbv2_request_smugling(Check): report.region = lb.region report.resource_id = lb.name report.resource_arn = lb.arn + report.resource_tags = lb.tags report.status = "FAIL" report.status_extended = ( f"ELBv2 ALB {lb.name} is not dropping invalid header fields." diff --git a/prowler/providers/aws/services/elbv2/elbv2_service.py b/prowler/providers/aws/services/elbv2/elbv2_service.py index 9e89b420..934c5a67 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_service.py +++ b/prowler/providers/aws/services/elbv2/elbv2_service.py @@ -22,6 +22,7 @@ class ELBv2: self.__threading_call__(self.__describe_listeners__) self.__threading_call__(self.__describe_load_balancer_attributes__) self.__threading_call__(self.__describe_rules__) + self.__describe_tags__() def __get_session__(self): return self.session @@ -148,6 +149,20 @@ class ELBv2: f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + def __describe_tags__(self): + logger.info("ELBv2 - List Tags...") + try: + for lb in self.loadbalancersv2: + regional_client = self.regional_clients[lb.region] + response = regional_client.describe_tags(ResourceArns=[lb.arn])[ + "TagDescriptions" + ][0] + lb.tags = response.get("Tags") + except Exception as error: + logger.error( + f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + class ListenerRule(BaseModel): arn: str @@ -176,3 +191,4 @@ class LoadBalancerv2(BaseModel): drop_invalid_header_fields: Optional[str] listeners: list[Listenerv2] scheme: Optional[str] + tags: Optional[list] = [] diff --git a/prowler/providers/aws/services/elbv2/elbv2_ssl_listeners/elbv2_ssl_listeners.py b/prowler/providers/aws/services/elbv2/elbv2_ssl_listeners/elbv2_ssl_listeners.py index 5180346c..b3ba66c0 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_ssl_listeners/elbv2_ssl_listeners.py +++ b/prowler/providers/aws/services/elbv2/elbv2_ssl_listeners/elbv2_ssl_listeners.py @@ -11,6 +11,7 @@ class elbv2_ssl_listeners(Check): report.region = lb.region report.resource_id = lb.name report.resource_arn = lb.arn + report.resource_tags = lb.tags report.status = "PASS" report.status_extended = ( f"ELBv2 ALB {lb.name} has HTTPS listeners only." diff --git a/prowler/providers/aws/services/elbv2/elbv2_waf_acl_attached/elbv2_waf_acl_attached.py b/prowler/providers/aws/services/elbv2/elbv2_waf_acl_attached/elbv2_waf_acl_attached.py index 24197232..9e3b2456 100644 --- a/prowler/providers/aws/services/elbv2/elbv2_waf_acl_attached/elbv2_waf_acl_attached.py +++ b/prowler/providers/aws/services/elbv2/elbv2_waf_acl_attached/elbv2_waf_acl_attached.py @@ -13,6 +13,7 @@ class elbv2_waf_acl_attached(Check): report.region = lb.region report.resource_id = lb.name report.resource_arn = lb.arn + report.resource_tags = lb.tags report.status = "FAIL" report.status_extended = ( f"ELBv2 ALB {lb.name} is not protected by WAF Web ACL." diff --git a/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.py b/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.py index 9c7caa7b..eb14498c 100644 --- a/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.py +++ b/prowler/providers/aws/services/emr/emr_cluster_master_nodes_no_public_ip/emr_cluster_master_nodes_no_public_ip.py @@ -15,7 +15,7 @@ class emr_cluster_master_nodes_no_public_ip(Check): report.region = cluster.region report.resource_id = cluster.id report.resource_arn = cluster.arn - + report.resource_tags = cluster.tags if cluster.public: report.status = "FAIL" report.status_extended = f"EMR Cluster {cluster.id} has a Public IP" diff --git a/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.py b/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.py index 82160675..868a6e60 100644 --- a/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.py +++ b/prowler/providers/aws/services/emr/emr_cluster_publicly_accesible/emr_cluster_publicly_accesible.py @@ -19,7 +19,7 @@ class emr_cluster_publicly_accesible(Check): report.region = cluster.region report.resource_id = cluster.id report.resource_arn = cluster.arn - + report.resource_tags = cluster.tags report.status = "PASS" report.status_extended = ( f"EMR Cluster {cluster.id} is not publicly accessible" @@ -28,7 +28,6 @@ class emr_cluster_publicly_accesible(Check): # their Security Groups for the Master, # the Slaves and the additional ones if cluster.public: - # Check Public Master Security Groups master_node_sg_groups = deepcopy( cluster.master.additional_security_groups_id diff --git a/prowler/providers/aws/services/emr/emr_service.py b/prowler/providers/aws/services/emr/emr_service.py index ea29672d..aff97377 100644 --- a/prowler/providers/aws/services/emr/emr_service.py +++ b/prowler/providers/aws/services/emr/emr_service.py @@ -125,6 +125,7 @@ class EMR: and ".amazonaws.com" in master_public_dns_name ): self.clusters[cluster.id].public = True + cluster.tags = cluster_info["Cluster"].get("Tags") except Exception as error: logger.error( @@ -185,3 +186,4 @@ class Cluster(BaseModel): slave: Node = Node() master_public_dns_name: str = "" public: bool = False + tags: Optional[list] = [] diff --git a/tests/providers/aws/services/ec2/ec2_service_test.py b/tests/providers/aws/services/ec2/ec2_service_test.py index 873fcac6..94485b50 100644 --- a/tests/providers/aws/services/ec2/ec2_service_test.py +++ b/tests/providers/aws/services/ec2/ec2_service_test.py @@ -127,6 +127,14 @@ class Test_EC2_Service: sg_id = ec2_client.create_security_group( Description="test-description", GroupName="test-security-group", + TagSpecifications=[ + { + "ResourceType": "security-group", + "Tags": [ + {"Key": "test", "Value": "test"}, + ], + }, + ], )["GroupId"] # EC2 client for this test class audit_info = self.set_mocked_audit_info() @@ -153,6 +161,9 @@ class Test_EC2_Service: "UserIdGroupPairs": [], } ] + assert security_group.tags == [ + {"Key": "test", "Value": "test"}, + ] # Test EC2 Describe Nacls @mock_ec2 @@ -164,6 +175,14 @@ class Test_EC2_Service: vpc_id = ec2_client.create_vpc(CidrBlock="10.0.0.0/16")["Vpc"]["VpcId"] nacl_id = ec2_resource.create_network_acl( VpcId=vpc_id, + TagSpecifications=[ + { + "ResourceType": "network-acl", + "Tags": [ + {"Key": "test", "Value": "test"}, + ], + }, + ], ).id # EC2 client for this test class audit_info = self.set_mocked_audit_info() @@ -178,6 +197,9 @@ class Test_EC2_Service: == f"arn:{audit_info.audited_partition}:ec2:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:network-acl/{acl.id}" ) assert acl.entries == [] + assert acl.tags == [ + {"Key": "test", "Value": "test"}, + ] # Test EC2 Describe Snapshots @mock_ec2 @@ -193,6 +215,14 @@ class Test_EC2_Service: ).id snapshot_id = ec2_client.create_snapshot( VolumeId=volume_id, + TagSpecifications=[ + { + "ResourceType": "snapshot", + "Tags": [ + {"Key": "test", "Value": "test"}, + ], + }, + ], )["SnapshotId"] # EC2 client for this test class audit_info = self.set_mocked_audit_info() @@ -207,6 +237,9 @@ class Test_EC2_Service: == f"arn:{audit_info.audited_partition}:ec2:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:snapshot/{snapshot.id}" ) assert snapshot.region == AWS_REGION + assert snapshot.tags == [ + {"Key": "test", "Value": "test"}, + ] assert not snapshot.encrypted assert not snapshot.public @@ -286,7 +319,16 @@ class Test_EC2_Service: # Generate EC2 Client ec2_client = client("ec2", region_name=AWS_REGION) allocation_id = ec2_client.allocate_address( - Domain="vpc", Address="127.38.43.222" + Domain="vpc", + Address="127.38.43.222", + TagSpecifications=[ + { + "ResourceType": "elastic-ip", + "Tags": [ + {"Key": "test", "Value": "test"}, + ], + }, + ], )["AllocationId"] # EC2 client for this test class audit_info = self.set_mocked_audit_info() @@ -296,6 +338,9 @@ class Test_EC2_Service: ec2.elastic_ips[0].arn == f"arn:aws:ec2:{AWS_REGION}:{AWS_ACCOUNT_NUMBER}:eip-allocation/{allocation_id}" ) + assert ec2.elastic_ips[0].tags == [ + {"Key": "test", "Value": "test"}, + ] # Test EC2 Describe Network Interfaces @mock_ec2 @@ -310,7 +355,6 @@ class Test_EC2_Service: GroupName="test-securitygroup", Description="n/a" ) eni_id = subnet.create_network_interface(Groups=[sg.id]).id - print(eni_id) ec2_client.modify_network_interface_attribute( NetworkInterfaceId=eni_id, Groups=[sg.id] ) @@ -383,6 +427,13 @@ class Test_EC2_Service: ) assert not ec2.images[0].public assert ec2.images[0].region == AWS_REGION + assert ec2.images[0].tags == [ + { + "Key": "Base_AMI_Name", + "Value": "Deep Learning Base AMI (Amazon Linux 2) Version 31.0", + }, + {"Key": "OS_Version", "Value": "AWS Linux 2"}, + ] # Test EC2 Describe Volumes @mock_ec2 @@ -394,7 +445,14 @@ class Test_EC2_Service: AvailabilityZone=AWS_REGION, Encrypted=False, Size=40, - TagSpecifications=[], + TagSpecifications=[ + { + "ResourceType": "volume", + "Tags": [ + {"Key": "test", "Value": "test"}, + ], + }, + ], )["VolumeId"] # EC2 client for this test class @@ -410,3 +468,6 @@ class Test_EC2_Service: ) assert ec2.volumes[0].region == AWS_REGION assert not ec2.volumes[0].encrypted + assert ec2.volumes[0].tags == [ + {"Key": "test", "Value": "test"}, + ] diff --git a/tests/providers/aws/services/ecr/ecr_service_test.py b/tests/providers/aws/services/ecr/ecr_service_test.py index 68a61d68..8d0622e4 100644 --- a/tests/providers/aws/services/ecr/ecr_service_test.py +++ b/tests/providers/aws/services/ecr/ecr_service_test.py @@ -118,6 +118,9 @@ class Test_ECR_Service: ecr_client.create_repository( repositoryName=repo_name, imageScanningConfiguration={"scanOnPush": True}, + tags=[ + {"Key": "test", "Value": "test"}, + ], ) audit_info = self.set_mocked_audit_info() ecr = ECR(audit_info) @@ -125,6 +128,9 @@ class Test_ECR_Service: assert ecr.repositories[0].name == repo_name assert ecr.repositories[0].arn == repo_arn assert ecr.repositories[0].scan_on_push + assert ecr.repositories[0].tags == [ + {"Key": "test", "Value": "test"}, + ] # Test describe ECR repository policies @mock_ecr diff --git a/tests/providers/aws/services/ecs/ecs_service_test.py b/tests/providers/aws/services/ecs/ecs_service_test.py index 0d7007cb..6e53c067 100644 --- a/tests/providers/aws/services/ecs/ecs_service_test.py +++ b/tests/providers/aws/services/ecs/ecs_service_test.py @@ -111,6 +111,9 @@ class Test_ECS_Service: ], } ], + tags=[ + {"key": "test", "value": "test"}, + ], ) task_definition = ecs_client.register_task_definition(**definition) @@ -121,6 +124,9 @@ class Test_ECS_Service: assert ( ecs.task_definitions[0].name == task_definition["taskDefinition"]["family"] ) + assert ecs.task_definitions[0].tags == [ + {"key": "test", "value": "test"}, + ] assert ( ecs.task_definitions[0].arn == task_definition["taskDefinition"]["taskDefinitionArn"] diff --git a/tests/providers/aws/services/efs/efs_service_test.py b/tests/providers/aws/services/efs/efs_service_test.py index 3a8dac98..612a12b2 100644 --- a/tests/providers/aws/services/efs/efs_service_test.py +++ b/tests/providers/aws/services/efs/efs_service_test.py @@ -91,12 +91,19 @@ class Test_EFS: def test__describe_file_systems__(self): efs_client = client("efs", AWS_REGION) efs = efs_client.create_file_system( - CreationToken=creation_token, Encrypted=True + CreationToken=creation_token, + Encrypted=True, + Tags=[ + {"Key": "test", "Value": "test"}, + ], ) filesystem = EFS(self.set_mocked_audit_info()) assert len(filesystem.filesystems) == 1 assert filesystem.filesystems[0].id == efs["FileSystemId"] assert filesystem.filesystems[0].encrypted == efs["Encrypted"] + assert filesystem.filesystems[0].tags == [ + {"Key": "test", "Value": "test"}, + ] @mock_efs # Test EFS describe file systems diff --git a/tests/providers/aws/services/eks/eks_service_test.py b/tests/providers/aws/services/eks/eks_service_test.py index cb674be5..437f0d67 100644 --- a/tests/providers/aws/services/eks/eks_service_test.py +++ b/tests/providers/aws/services/eks/eks_service_test.py @@ -92,12 +92,14 @@ class Test_EKS_Service: ], }, roleArn=f"arn:aws:iam::{AWS_ACCOUNT_NUMBER}:role/eks-service-role-AWSServiceRoleForAmazonEKS-J7ONKE3BQ4PI", + tags={"test": "test"}, ) audit_info = self.set_mocked_audit_info() eks = EKS(audit_info) assert len(eks.clusters) == 1 assert eks.clusters[0].name == cluster_name assert eks.clusters[0].region == AWS_REGION + assert eks.clusters[0].tags == [{"test": "test"}] # Test EKS describe clusters @mock_ec2 diff --git a/tests/providers/aws/services/emr/emr_service_test.py b/tests/providers/aws/services/emr/emr_service_test.py index c1eebb2a..e6eb3073 100644 --- a/tests/providers/aws/services/emr/emr_service_test.py +++ b/tests/providers/aws/services/emr/emr_service_test.py @@ -108,6 +108,9 @@ class Test_EMR_Service: Name=cluster_name, ServiceRole="EMR_DefaultRole", VisibleToAllUsers=True, + Tags=[ + {"Key": "test", "Value": "test"}, + ], ) cluster_id = emr_client.run_job_flow(**run_job_flow_args)["JobFlowId"] # EMR Class @@ -127,6 +130,9 @@ class Test_EMR_Service: == "ec2-184-0-0-1.us-west-1.compute.amazonaws.com" ) assert emr.clusters[cluster_id].public + assert emr.clusters[cluster_id].tags == [ + {"Key": "test", "Value": "test"}, + ] @mock_emr def test__get_block_public_access_configuration__(self):