Files
prowler/providers/aws/services/vpc/vpc_service.py
2022-10-28 12:15:15 +02:00

307 lines
10 KiB
Python

import json
import threading
from dataclasses import dataclass
from lib.logger import logger
from providers.aws.aws_provider import generate_regional_clients
################## VPC
class VPC:
def __init__(self, audit_info):
self.service = "ec2"
self.session = audit_info.audit_session
self.audited_account = audit_info.audited_account
self.regional_clients = generate_regional_clients(self.service, audit_info)
self.vpcs = []
self.vpc_peering_connections = []
self.vpc_endpoints = []
self.vpc_endpoint_services = []
self.__threading_call__(self.__describe_vpcs__)
self.__threading_call__(self.__describe_vpc_peering_connections__)
self.__threading_call__(self.__describe_vpc_endpoints__)
self.__threading_call__(self.__describe_vpc_endpoint_services__)
self.__describe_flow_logs__()
self.__describe_route_tables__()
self.__describe_vpc_endpoint_service_permissions__()
def __get_session__(self):
return self.session
def __threading_call__(self, call):
threads = []
for regional_client in self.regional_clients.values():
threads.append(threading.Thread(target=call, args=(regional_client,)))
for t in threads:
t.start()
for t in threads:
t.join()
def __describe_vpcs__(self, regional_client):
logger.info("VPC - Describing VPCs...")
try:
describe_vpcs_paginator = regional_client.get_paginator("describe_vpcs")
for page in describe_vpcs_paginator.paginate():
for vpc in page["Vpcs"]:
self.vpcs.append(
VPCs(
vpc["VpcId"],
vpc["IsDefault"],
vpc["CidrBlock"],
regional_client.region,
)
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __describe_vpc_peering_connections__(self, regional_client):
logger.info("VPC - Describing VPC Peering Connections...")
try:
describe_vpc_peering_connections_paginator = regional_client.get_paginator(
"describe_vpc_peering_connections"
)
for page in describe_vpc_peering_connections_paginator.paginate():
for conn in page["VpcPeeringConnections"]:
self.vpc_peering_connections.append(
VpcPeeringConnection(
conn["VpcPeeringConnectionId"],
conn["AccepterVpcInfo"]["VpcId"],
conn["AccepterVpcInfo"]["CidrBlock"],
conn["RequesterVpcInfo"]["VpcId"],
conn["RequesterVpcInfo"]["CidrBlock"],
regional_client.region,
)
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __describe_route_tables__(self):
logger.info("VPC - Describing Peering Route Tables...")
try:
for conn in self.vpc_peering_connections:
regional_client = self.regional_clients[conn.region]
for route_table in regional_client.describe_route_tables(
Filters=[
{
"Name": "route.vpc-peering-connection-id",
"Values": [
conn.id,
],
},
]
)["RouteTables"]:
destination_cidrs = []
for route in route_table["Routes"]:
if (
route["Origin"] != "CreateRouteTable"
): # avoid default route table
destination_cidrs.append(route["DestinationCidrBlock"])
conn.route_tables.append(
Route(
route_table["RouteTableId"],
destination_cidrs,
)
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __describe_flow_logs__(self):
logger.info("VPC - Describing flow logs...")
try:
for vpc in self.vpcs:
regional_client = self.regional_clients[vpc.region]
flow_logs = regional_client.describe_flow_logs(
Filters=[
{
"Name": "resource-id",
"Values": [
vpc.id,
],
},
]
)["FlowLogs"]
if flow_logs:
vpc.flow_log = True
except Exception as error:
logger.error(f"{error.__class__.__name__}: {error}")
def __describe_vpc_endpoints__(self, regional_client):
logger.info("VPC - Describing VPC Endpoints...")
try:
describe_vpc_endpoints_paginator = regional_client.get_paginator(
"describe_vpc_endpoints"
)
for page in describe_vpc_endpoints_paginator.paginate():
for endpoint in page["VpcEndpoints"]:
self.vpc_endpoints.append(
VpcEndpoint(
endpoint["VpcEndpointId"],
endpoint["VpcId"],
endpoint["State"],
json.loads(endpoint["PolicyDocument"]),
endpoint["OwnerId"],
regional_client.region,
)
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __describe_vpc_endpoint_services__(self, regional_client):
logger.info("VPC - Describing VPC Endpoint Services...")
try:
describe_vpc_endpoint_services_paginator = regional_client.get_paginator(
"describe_vpc_endpoint_services"
)
for page in describe_vpc_endpoint_services_paginator.paginate():
for endpoint in page["ServiceDetails"]:
if endpoint["Owner"] != "amazon":
self.vpc_endpoint_services.append(
VpcEndpointService(
endpoint["ServiceId"],
endpoint["ServiceName"],
endpoint["Owner"],
regional_client.region,
)
)
except Exception as error:
logger.error(
f"{regional_client.region} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
def __describe_vpc_endpoint_service_permissions__(self):
logger.info("VPC - Describing VPC Endpoint service permissions...")
try:
for service in self.vpc_endpoint_services:
regional_client = self.regional_clients[service.region]
for (
principal
) in regional_client.describe_vpc_endpoint_service_permissions(
ServiceId=service.id
)[
"AllowedPrincipals"
]:
service.allowed_principals.append(principal["Principal"])
except Exception as error:
logger.error(f"{error.__class__.__name__}: {error}")
@dataclass
class VPCs:
id: str
default: bool
cidr_block: str
flow_log: bool
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:
id: str
destination_cidrs: list[str]
def __init__(
self,
id,
destination_cidrs,
):
self.id = id
self.destination_cidrs = destination_cidrs
@dataclass
class VpcPeeringConnection:
id: str
accepter_vpc: str
accepter_cidr: str
requester_vpc: str
requester_cidr: 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:
id: str
vpc_id: str
state: str
policy_document: dict
owner_id: list[Route]
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:
id: str
service: str
owner_id: str
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