diff --git a/prowler/providers/aws/services/emr/emr_service.py b/prowler/providers/aws/services/emr/emr_service.py index e7737782..61a16ac2 100644 --- a/prowler/providers/aws/services/emr/emr_service.py +++ b/prowler/providers/aws/services/emr/emr_service.py @@ -110,16 +110,19 @@ class EMR: ) # Save MasterPublicDnsName - master_public_dns_name = cluster_info["Cluster"][ + master_public_dns_name = cluster_info["Cluster"].get( "MasterPublicDnsName" - ] + ) self.clusters[ cluster.id ].master_public_dns_name = master_public_dns_name # Set cluster Public/Private # Public EMR cluster have their DNS ending with .amazonaws.com # while private ones have format of ip-xxx-xx-xx.us-east-1.compute.internal. - if ".amazonaws.com" in master_public_dns_name: + if ( + master_public_dns_name + and ".amazonaws.com" in master_public_dns_name + ): self.clusters[cluster.id].public = True except Exception as error: diff --git a/prowler/providers/aws/services/rds/rds_service.py b/prowler/providers/aws/services/rds/rds_service.py index f4db038c..727bd5cf 100644 --- a/prowler/providers/aws/services/rds/rds_service.py +++ b/prowler/providers/aws/services/rds/rds_service.py @@ -54,7 +54,7 @@ class RDS: self.db_instances.append( DBInstance( id=instance["DBInstanceIdentifier"], - endpoint=instance["Endpoint"]["Address"], + endpoint=instance.get("Endpoint"), engine=instance["Engine"], status=instance["DBInstanceStatus"], public=instance["PubliclyAccessible"], @@ -171,7 +171,7 @@ class RDS: class DBInstance(BaseModel): id: str - endpoint: str + endpoint: Optional[dict] engine: str status: str public: bool diff --git a/prowler/providers/aws/services/s3/s3_service.py b/prowler/providers/aws/services/s3/s3_service.py index b239f233..579e6f93 100644 --- a/prowler/providers/aws/services/s3/s3_service.py +++ b/prowler/providers/aws/services/s3/s3_service.py @@ -44,35 +44,33 @@ class S3: try: list_buckets = self.client.list_buckets() for bucket in list_buckets["Buckets"]: - try: - bucket_region = self.client.get_bucket_location( - Bucket=bucket["Name"] - )["LocationConstraint"] - if bucket_region == "EU": # If EU, bucket_region is eu-west-1 - bucket_region = "eu-west-1" - if not bucket_region: # If Nonce, bucket_region is us-east-1 - bucket_region = "us-east-1" - # Arn - arn = f"arn:{self.audited_partition}:s3:::{bucket['Name']}" - if not self.audit_resources or ( - is_resource_filtered(arn, self.audit_resources) - ): - # Check if there are filter regions - if audit_info.audited_regions: - if bucket_region in audit_info.audited_regions: - buckets.append( - Bucket(bucket["Name"], arn, bucket_region) - ) - else: + bucket_region = self.client.get_bucket_location(Bucket=bucket["Name"])[ + "LocationConstraint" + ] + if bucket_region == "EU": # If EU, bucket_region is eu-west-1 + bucket_region = "eu-west-1" + if not bucket_region: # If Nonce, bucket_region is us-east-1 + bucket_region = "us-east-1" + # Arn + arn = f"arn:{self.audited_partition}:s3:::{bucket['Name']}" + if not self.audit_resources or ( + is_resource_filtered(arn, self.audit_resources) + ): + # Check if there are filter regions + if audit_info.audited_regions: + if bucket_region in audit_info.audited_regions: buckets.append(Bucket(bucket["Name"], arn, bucket_region)) - except Exception as error: - logger.error( - f"{bucket} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) + else: + buckets.append(Bucket(bucket["Name"], arn, bucket_region)) except Exception as error: - logger.error( - f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) + if bucket: + logger.error( + f"{bucket} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) return buckets def __get_bucket_versioning__(self, bucket): @@ -89,9 +87,14 @@ class S3: if "Enabled" == bucket_versioning["MFADelete"]: bucket.mfa_delete = True except Exception as error: - logger.error( - f"{bucket.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) + if bucket.region: + logger.error( + f"{bucket.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) def __get_bucket_encryption__(self, bucket): logger.info("S3 - Get buckets encryption...") @@ -107,10 +110,14 @@ class S3: except Exception as error: if "ServerSideEncryptionConfigurationNotFoundError" in str(error): bucket.encryption = None - else: + elif regional_client: logger.error( f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) def __get_bucket_logging__(self, bucket): logger.info("S3 - Get buckets logging...") @@ -123,9 +130,14 @@ class S3: "TargetBucket" ] except Exception as error: - logger.error( - f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) + if regional_client: + logger.error( + f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) def __get_public_access_block__(self, bucket): logger.info("S3 - Get buckets public access block...") @@ -148,9 +160,14 @@ class S3: } ) else: - logger.error( - f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) + if regional_client: + logger.error( + f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) def __get_bucket_acl__(self, bucket): logger.info("S3 - Get buckets acl...") @@ -171,9 +188,14 @@ class S3: grantees.append(grantee) bucket.acl_grantees = grantees except Exception as error: - logger.error( - f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) + if regional_client: + logger.error( + f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) def __get_bucket_policy__(self, bucket): logger.info("S3 - Get buckets policy...") @@ -186,9 +208,14 @@ class S3: if "NoSuchBucketPolicy" in str(error): bucket.policy = {} else: - logger.error( - f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) + if regional_client: + logger.error( + f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) def __get_bucket_ownership_controls__(self, bucket): logger.info("S3 - Get buckets ownership controls...") @@ -201,9 +228,14 @@ class S3: if "OwnershipControlsNotFoundError" in str(error): bucket.ownership = None else: - logger.error( - f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) + if regional_client: + logger.error( + f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) ################## S3Control diff --git a/prowler/providers/aws/services/vpc/vpc_service.py b/prowler/providers/aws/services/vpc/vpc_service.py index ca84679e..21b64ee9 100644 --- a/prowler/providers/aws/services/vpc/vpc_service.py +++ b/prowler/providers/aws/services/vpc/vpc_service.py @@ -1,6 +1,8 @@ import json import threading -from dataclasses import dataclass +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 @@ -50,10 +52,10 @@ class VPC: ): self.vpcs.append( VPCs( - vpc["VpcId"], - vpc["IsDefault"], - vpc["CidrBlock"], - regional_client.region, + id=vpc["VpcId"], + default=vpc["IsDefault"], + cidr_block=vpc["CidrBlock"], + region=regional_client.region, ) ) except Exception as error: @@ -74,14 +76,17 @@ class VPC: conn["VpcPeeringConnectionId"], self.audit_resources ) ): + conn["AccepterVpcInfo"]["CidrBlock"] = None self.vpc_peering_connections.append( VpcPeeringConnection( - conn["VpcPeeringConnectionId"], - conn["AccepterVpcInfo"]["VpcId"], - conn["AccepterVpcInfo"]["CidrBlock"], - conn["RequesterVpcInfo"]["VpcId"], - conn["RequesterVpcInfo"]["CidrBlock"], - regional_client.region, + id=conn["VpcPeeringConnectionId"], + accepter_vpc=conn["AccepterVpcInfo"]["VpcId"], + accepter_cidr=conn["AccepterVpcInfo"].get("CidrBlock"), + requester_vpc=conn["RequesterVpcInfo"]["VpcId"], + requester_cidr=conn["RequesterVpcInfo"].get( + "CidrBlock" + ), + region=regional_client.region, ) ) except Exception as error: @@ -113,8 +118,8 @@ class VPC: destination_cidrs.append(route["DestinationCidrBlock"]) conn.route_tables.append( Route( - route_table["RouteTableId"], - destination_cidrs, + id=route_table["RouteTableId"], + destination_cidrs=destination_cidrs, ) ) except Exception as error: @@ -160,12 +165,12 @@ class VPC: endpoint_policy = json.loads(endpoint["PolicyDocument"]) self.vpc_endpoints.append( VpcEndpoint( - endpoint["VpcEndpointId"], - endpoint["VpcId"], - endpoint["State"], - endpoint_policy, - endpoint["OwnerId"], - regional_client.region, + id=endpoint["VpcEndpointId"], + vpc_id=endpoint["VpcId"], + state=endpoint["State"], + policy_document=endpoint_policy, + owner_id=endpoint["OwnerId"], + region=regional_client.region, ) ) except Exception as error: @@ -189,10 +194,10 @@ class VPC: ): self.vpc_endpoint_services.append( VpcEndpointService( - endpoint["ServiceId"], - endpoint["ServiceName"], - endpoint["Owner"], - regional_client.region, + id=endpoint["ServiceId"], + service=endpoint["ServiceName"], + owner_id=endpoint["Owner"], + region=regional_client.region, ) ) except Exception as error: @@ -217,114 +222,41 @@ class VPC: logger.error(f"{error.__class__.__name__}: {error}") -@dataclass -class VPCs: +class VPCs(BaseModel): id: str default: bool cidr_block: str - flow_log: bool + flow_log: bool = False region: str - def __init__( - self, - id, - default, - cidr_block, - region, - ): - self.id = id - self.default = default - self.cidr_block = cidr_block - self.flow_log = False - self.region = region - -@dataclass -class Route: +class Route(BaseModel): id: str destination_cidrs: list[str] - def __init__( - self, - id, - destination_cidrs, - ): - self.id = id - self.destination_cidrs = destination_cidrs - -@dataclass -class VpcPeeringConnection: +class VpcPeeringConnection(BaseModel): id: str accepter_vpc: str - accepter_cidr: str + accepter_cidr: Optional[str] requester_vpc: str - requester_cidr: str - route_tables: list[Route] + requester_cidr: Optional[str] + route_tables: list[Route] = [] region: str - def __init__( - self, - id, - accepter_vpc, - accepter_cidr, - requester_vpc, - requester_cidr, - region, - ): - self.id = id - self.accepter_vpc = accepter_vpc - self.accepter_cidr = accepter_cidr - self.requester_vpc = requester_vpc - self.requester_cidr = requester_cidr - self.route_tables = [] - self.region = region - -@dataclass -class VpcEndpoint: +class VpcEndpoint(BaseModel): id: str vpc_id: str state: str policy_document: dict - owner_id: list[Route] + owner_id: str region: str - def __init__( - self, - id, - vpc_id, - state, - policy_document, - owner_id, - region, - ): - self.id = id - self.vpc_id = vpc_id - self.state = state - self.policy_document = policy_document - self.owner_id = owner_id - self.route_tables = [] - self.region = region - -@dataclass -class VpcEndpointService: +class VpcEndpointService(BaseModel): id: str service: str owner_id: str - allowed_principals: list + allowed_principals: list = [] region: str - - def __init__( - self, - id, - service, - owner_id, - region, - ): - self.id = id - self.service = service - self.owner_id = owner_id - self.allowed_principals = [] - self.region = region diff --git a/tests/providers/aws/services/rds/rds_service_test.py b/tests/providers/aws/services/rds/rds_service_test.py index 3bfd24f2..0d20b607 100644 --- a/tests/providers/aws/services/rds/rds_service_test.py +++ b/tests/providers/aws/services/rds/rds_service_test.py @@ -90,7 +90,7 @@ class Test_RDS_Service: assert rds.db_instances[0].id == "db-master-1" assert rds.db_instances[0].region == AWS_REGION assert ( - rds.db_instances[0].endpoint + rds.db_instances[0].endpoint["Address"] == "db-master-1.aaaaaaaaaa.us-east-1.rds.amazonaws.com" ) assert rds.db_instances[0].status == "available" diff --git a/tests/providers/aws/services/vpc/vpc_peering_routing_tables_with_least_privilege/vpc_peering_routing_tables_with_least_privilege_test.py b/tests/providers/aws/services/vpc/vpc_peering_routing_tables_with_least_privilege/vpc_peering_routing_tables_with_least_privilege_test.py index 0c3fbe75..25d827ad 100644 --- a/tests/providers/aws/services/vpc/vpc_peering_routing_tables_with_least_privilege/vpc_peering_routing_tables_with_least_privilege_test.py +++ b/tests/providers/aws/services/vpc/vpc_peering_routing_tables_with_least_privilege/vpc_peering_routing_tables_with_least_privilege_test.py @@ -75,8 +75,8 @@ class Test_vpc_peering_routing_tables_with_least_privilege: service_client.vpc_peering_connections[0].route_tables = [ Route( - main_route_table_id, - ["10.12.23.44/32"], + id=main_route_table_id, + destination_cidrs=["10.12.23.44/32"], ) ] check = vpc_peering_routing_tables_with_least_privilege() @@ -138,8 +138,8 @@ class Test_vpc_peering_routing_tables_with_least_privilege: service_client.vpc_peering_connections[0].route_tables = [ Route( - main_route_table_id, - ["10.0.0.0/16"], + id=main_route_table_id, + destination_cidrs=["10.0.0.0/16"], ) ] check = vpc_peering_routing_tables_with_least_privilege() diff --git a/tests/providers/aws/services/vpc/vpc_service_test.py b/tests/providers/aws/services/vpc/vpc_service_test.py index 29498e7f..656c4e51 100644 --- a/tests/providers/aws/services/vpc/vpc_service_test.py +++ b/tests/providers/aws/services/vpc/vpc_service_test.py @@ -163,8 +163,8 @@ class Test_VPC_Service: vpc = VPC(audit_info) vpc.vpc_peering_connections[0].route_tables = [ Route( - main_route_table_id, - ["10.0.0.4/24"], + id=main_route_table_id, + destination_cidrs=["10.0.0.4/24"], ) ] assert len(vpc.vpc_peering_connections[0].route_tables) == 1