fix: handle errors in AWS, Azure, and GCP (#7456)

This commit is contained in:
Sergio Garcia
2025-04-08 08:20:43 -04:00
committed by GitHub
parent 7cbc60d977
commit b55f8efed1
8 changed files with 52 additions and 18 deletions
@@ -33,6 +33,10 @@ IGNORED_EXCEPTIONS = [
"ValidationException",
"AWSSecretAccessKeyInvalidError",
"InvalidAction",
"InvalidRequestException",
"RequestExpired",
"ConnectionClosedError",
"HTTPSConnectionPool",
"Pool is closed", # The following comes from urllib3: eu-west-1 -- HTTPClientError[126]: An HTTP Client raised an unhandled exception: AWSHTTPSConnectionPool(host='hostname.s3.eu-west-1.amazonaws.com', port=443): Pool is closed.
# Authentication Errors from GCP
"ClientAuthenticationError",
@@ -41,6 +45,8 @@ IGNORED_EXCEPTIONS = [
"Permission denied to get service",
"API has not been used in project",
"HttpError 404 when requesting",
"HttpError 403 when requesting",
"HttpError 400 when requesting",
"GCPNoAccesibleProjectsError",
# Authentication Errors from Azure
"ClientAuthenticationError",
@@ -19,7 +19,8 @@ class redshift_cluster_public_access(Check):
report.status_extended = f"Redshift Cluster {cluster.id} has the endpoint {cluster.endpoint_address} set as publicly accessible but is not publicly exposed."
# 2. Check if Redshift Cluster is in a public subnet
if any(
subnet in vpc_client.subnets and vpc_client.subnets[subnet].public
subnet in vpc_client.vpc_subnets
and vpc_client.vpc_subnets[subnet].public
for subnet in cluster.subnets
):
report.status_extended = f"Redshift Cluster {cluster.id} has the endpoint {cluster.endpoint_address} set as publicly accessible in a public subnet but is not publicly exposed."
@@ -46,9 +46,6 @@ class ContainerRegistry(AzureService):
admin_user_enabled=getattr(
registry, "admin_user_enabled", False
),
network_rule_set=getattr(
registry, "network_rule_set", None
),
monitor_diagnostic_settings=self._get_registry_monitor_settings(
registry.name, resource_group, subscription
),
@@ -53,10 +53,13 @@ class KeyVault(AzureService):
),
private_endpoint_connections=[
PrivateEndpointConnection(id=conn.id)
for conn in getattr(
keyvault_properties,
"private_endpoint_connections",
[],
for conn in (
getattr(
keyvault_properties,
"private_endpoint_connections",
[],
)
or []
)
],
enable_soft_delete=getattr(
@@ -53,7 +53,7 @@ class Monitor(AzureService):
category_group=log_settings.category_group,
enabled=log_settings.enabled,
)
for log_settings in getattr(setting, "logs", [])
for log_settings in (getattr(setting, "logs", []) or [])
],
storage_account_id=setting.storage_account_id,
)
@@ -1,6 +1,8 @@
import re
from dataclasses import dataclass
from typing import List, Optional
from azure.core.exceptions import ResourceNotFoundError
from azure.mgmt.network import NetworkManagementClient
from prowler.lib.logger import logger
@@ -64,14 +66,22 @@ class Network(AzureService):
network_watchers.update({subscription: []})
network_watchers_list = client.network_watchers.list_all()
for network_watcher in network_watchers_list:
flow_logs = self._get_flow_logs(subscription, network_watcher.name)
flow_logs = self._get_flow_logs(
subscription, network_watcher.name, network_watcher.id
)
network_watchers[subscription].append(
NetworkWatcher(
id=network_watcher.id,
name=network_watcher.name,
location=network_watcher.location,
flow_logs=[
FlowLog(id=flow_log.id) for flow_log in flow_logs
FlowLog(
id=flow_log.id,
name=flow_log.name,
enabled=flow_log.properties.enabled,
retention_policy=flow_log.properties.retentionPolicy,
)
for flow_log in flow_logs
],
)
)
@@ -82,12 +92,29 @@ class Network(AzureService):
)
return network_watchers
def _get_flow_logs(self, subscription, network_watcher_name):
def _get_flow_logs(self, subscription, network_watcher_name, network_watcher_id):
logger.info("Network - Getting Flow Logs...")
client = self.clients[subscription]
resource_group = "NetworkWatcherRG"
flow_logs = client.flow_logs.list(resource_group, network_watcher_name)
return flow_logs
match = re.search(r"/resourceGroups/(?P<rg>[^/]+)/", network_watcher_id)
if not match:
logger.error(
f"Could not extract resource group from ID: {network_watcher_id}"
)
return []
resource_group = match.group("rg")
try:
flow_logs = client.flow_logs.list(resource_group, network_watcher_name)
return flow_logs
except ResourceNotFoundError as error:
logger.warning(
f"Subscription name: {subscription} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
return []
except Exception as error:
logger.error(
f"Subscription name: {subscription} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}"
)
return []
def _get_bastion_hosts(self):
logger.info("Network - Getting Bastion Hosts...")
@@ -23,7 +23,7 @@ class cloudstorage_bucket_log_retention_policy_lock(Check):
if bucket.retention_policy:
report.status = "FAIL"
report.status_extended = f"Log Sink Bucket {bucket.name} has no Retention Policy but without Bucket Lock."
if bucket.retention_policy["isLocked"]:
if bucket.retention_policy.get("isLocked", False):
report.status = "PASS"
report.status_extended = f"Log Sink Bucket {bucket.name} has a Retention Policy with Bucket Lock."
findings.append(report)
@@ -206,7 +206,7 @@ class Test_redshift_cluster_public_access:
)
)
vpc_client = mock.MagicMock
vpc_client.subnets = {"subnet-123456": mock.MagicMock(public=True)}
vpc_client.vpc_subnets = {"subnet-123456": mock.MagicMock(public=True)}
ec2_client = mock.MagicMock
aws_provider = set_mocked_aws_provider([AWS_REGION_EU_WEST_1])
@@ -260,7 +260,7 @@ class Test_redshift_cluster_public_access:
)
)
vpc_client = mock.MagicMock
vpc_client.subnets = {"subnet-123456": mock.MagicMock(public=True)}
vpc_client.vpc_subnets = {"subnet-123456": mock.MagicMock(public=True)}
ec2_client = mock.MagicMock
ec2_client.security_groups = {
f"arn:aws:ec2:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:security-group/sg-123456": mock.MagicMock(