feat(exceptions): modify custom exceptions (#5451)

This commit is contained in:
Pedro Martín
2024-10-18 09:28:58 +02:00
committed by GitHub
parent 98cb954f74
commit e65b346afd
14 changed files with 342 additions and 269 deletions
+13 -12
View File
@@ -1,31 +1,32 @@
from prowler.exceptions.exceptions import ProwlerException
# Exceptions codes from 5000 to 5999 are reserved for Scan exceptions
class ScanBaseException(ProwlerException):
"""Base class for Scan errors."""
SCAN_ERROR_CODES = {
(2000, "ScanInvalidSeverityError"): {
(5000, "ScanInvalidSeverityError"): {
"message": "Invalid severity level provided.",
"remediation": "Please provide a valid severity level. Valid severities are: critical, high, medium, low, informational.",
},
(2001, "ScanInvalidCheckError"): {
(5001, "ScanInvalidCheckError"): {
"message": "Invalid check provided.",
"remediation": "Please provide a valid check name.",
},
(2002, "ScanInvalidServiceError"): {
(5002, "ScanInvalidServiceError"): {
"message": "Invalid service provided.",
"remediation": "Please provide a valid service name.",
},
(2003, "ScanInvalidComplianceFrameworkError"): {
(5003, "ScanInvalidComplianceFrameworkError"): {
"message": "Invalid compliance framework provided.",
"remediation": "Please provide a valid compliance framework name for the chosen provider.",
},
(2004, "ScanInvalidCategoryError"): {
(5004, "ScanInvalidCategoryError"): {
"message": "Invalid category provided.",
"remediation": "Please provide a valid category name.",
},
(2005, "ScanInvalidStatusError"): {
(5005, "ScanInvalidStatusError"): {
"message": "Invalid status provided.",
"remediation": "Please provide a valid status: FAIL, PASS, MANUAL.",
},
@@ -48,40 +49,40 @@ class ScanBaseException(ProwlerException):
class ScanInvalidSeverityError(ScanBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
2000, file=file, original_exception=original_exception, message=message
5000, file=file, original_exception=original_exception, message=message
)
class ScanInvalidCheckError(ScanBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
2001, file=file, original_exception=original_exception, message=message
5001, file=file, original_exception=original_exception, message=message
)
class ScanInvalidServiceError(ScanBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
2002, file=file, original_exception=original_exception, message=message
5002, file=file, original_exception=original_exception, message=message
)
class ScanInvalidComplianceFrameworkError(ScanBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
2003, file=file, original_exception=original_exception, message=message
5003, file=file, original_exception=original_exception, message=message
)
class ScanInvalidCategoryError(ScanBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
2004, file=file, original_exception=original_exception, message=message
5004, file=file, original_exception=original_exception, message=message
)
class ScanInvalidStatusError(ScanBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
2005, file=file, original_exception=original_exception, message=message
5005, file=file, original_exception=original_exception, message=message
)
+63 -37
View File
@@ -24,21 +24,21 @@ from prowler.providers.aws.config import (
ROLE_SESSION_NAME,
)
from prowler.providers.aws.exceptions.exceptions import (
AWSAccessKeyIDInvalid,
AWSAccessKeyIDInvalidError,
AWSArgumentTypeValidationError,
AWSAssumeRoleError,
AWSClientError,
AWSIAMRoleARNEmptyResource,
AWSIAMRoleARNInvalidAccountID,
AWSIAMRoleARNInvalidResourceType,
AWSIAMRoleARNPartitionEmpty,
AWSIAMRoleARNRegionNotEmtpy,
AWSIAMRoleARNServiceNotIAMnorSTS,
AWSInvalidAccountCredentials,
AWSIAMRoleARNEmptyResourceError,
AWSIAMRoleARNInvalidAccountIDError,
AWSIAMRoleARNInvalidResourceTypeError,
AWSIAMRoleARNPartitionEmptyError,
AWSIAMRoleARNRegionNotEmtpyError,
AWSIAMRoleARNServiceNotIAMnorSTSError,
AWSInvalidProviderIdError,
AWSNoCredentialsError,
AWSProfileNotFoundError,
AWSSecretAccessKeyInvalid,
AWSSessionTokenExpired,
AWSSecretAccessKeyInvalidError,
AWSSessionTokenExpiredError,
AWSSetUpSessionError,
)
from prowler.providers.aws.lib.arn.arn import parse_iam_credentials_arn
@@ -974,17 +974,17 @@ class AwsProvider(Provider):
f"{client_error.__class__.__name__}[{client_error.__traceback__.tb_lineno}]: {client_error}"
)
if client_error.response["Error"]["Code"] == "InvalidClientTokenId":
raise AWSAccessKeyIDInvalid(
raise AWSAccessKeyIDInvalidError(
original_exception=client_error,
file=pathlib.Path(__file__).name,
)
elif client_error.response["Error"]["Code"] == "SignatureDoesNotMatch":
raise AWSSecretAccessKeyInvalid(
raise AWSSecretAccessKeyInvalidError(
original_exception=client_error,
file=pathlib.Path(__file__).name,
)
elif client_error.response["Error"]["Code"] == "ExpiredToken":
raise AWSSessionTokenExpired(
raise AWSSessionTokenExpiredError(
original_exception=client_error,
file=pathlib.Path(__file__).name,
)
@@ -1097,62 +1097,80 @@ class AwsProvider(Provider):
caller_identity = AwsProvider.validate_credentials(session, aws_region)
# Do an extra validation if the AWS account ID is provided
if provider_id and caller_identity.account != provider_id:
raise AWSInvalidAccountCredentials(file=pathlib.Path(__file__).name)
raise AWSInvalidProviderIdError(file=pathlib.Path(__file__).name)
return Connection(
is_connected=True,
)
except AWSSetUpSessionError as setup_session_error:
logger.error(str(setup_session_error))
logger.error(
f"{setup_session_error.__class__.__name__}[{setup_session_error.__traceback__.tb_lineno}]: {setup_session_error}"
)
if raise_on_exception:
raise setup_session_error
return Connection(error=setup_session_error)
except AWSArgumentTypeValidationError as validation_error:
logger.error(str(validation_error))
logger.error(
f"{validation_error.__class__.__name__}[{validation_error.__traceback__.tb_lineno}]: {validation_error}"
)
if raise_on_exception:
raise validation_error
return Connection(error=validation_error)
except AWSIAMRoleARNRegionNotEmtpy as arn_region_not_empty_error:
logger.error(str(arn_region_not_empty_error))
except AWSIAMRoleARNRegionNotEmtpyError as arn_region_not_empty_error:
logger.error(
f"{arn_region_not_empty_error.__class__.__name__}[{arn_region_not_empty_error.__traceback__.tb_lineno}]: {arn_region_not_empty_error}"
)
if raise_on_exception:
raise arn_region_not_empty_error
return Connection(error=arn_region_not_empty_error)
except AWSIAMRoleARNPartitionEmpty as arn_partition_empty_error:
logger.error(str(arn_partition_empty_error))
except AWSIAMRoleARNPartitionEmptyError as arn_partition_empty_error:
logger.error(
f"{arn_partition_empty_error.__class__.__name__}[{arn_partition_empty_error.__traceback__.tb_lineno}]: {arn_partition_empty_error}"
)
if raise_on_exception:
raise arn_partition_empty_error
return Connection(error=arn_partition_empty_error)
except AWSIAMRoleARNServiceNotIAMnorSTS as arn_service_not_iam_sts_error:
logger.error(str(arn_service_not_iam_sts_error))
except AWSIAMRoleARNServiceNotIAMnorSTSError as arn_service_not_iam_sts_error:
logger.error(
f"{arn_service_not_iam_sts_error.__class__.__name__}[{arn_service_not_iam_sts_error.__traceback__.tb_lineno}]: {arn_service_not_iam_sts_error}"
)
if raise_on_exception:
raise arn_service_not_iam_sts_error
return Connection(error=arn_service_not_iam_sts_error)
except AWSIAMRoleARNInvalidAccountID as arn_invalid_account_id_error:
logger.error(str(arn_invalid_account_id_error))
except AWSIAMRoleARNInvalidAccountIDError as arn_invalid_account_id_error:
logger.error(
f"{arn_invalid_account_id_error.__class__.__name__}[{arn_invalid_account_id_error.__traceback__.tb_lineno}]: {arn_invalid_account_id_error}"
)
if raise_on_exception:
raise arn_invalid_account_id_error
return Connection(error=arn_invalid_account_id_error)
except AWSIAMRoleARNInvalidResourceType as arn_invalid_resource_type_error:
logger.error(str(arn_invalid_resource_type_error))
except AWSIAMRoleARNInvalidResourceTypeError as arn_invalid_resource_type_error:
logger.error(
f"{arn_invalid_resource_type_error.__class__.__name__}[{arn_invalid_resource_type_error.__traceback__.tb_lineno}]: {arn_invalid_resource_type_error}"
)
if raise_on_exception:
raise arn_invalid_resource_type_error
return Connection(error=arn_invalid_resource_type_error)
except AWSIAMRoleARNEmptyResource as arn_empty_resource_error:
logger.error(str(arn_empty_resource_error))
except AWSIAMRoleARNEmptyResourceError as arn_empty_resource_error:
logger.error(
f"{arn_empty_resource_error.__class__.__name__}[{arn_empty_resource_error.__traceback__.tb_lineno}]: {arn_empty_resource_error}"
)
if raise_on_exception:
raise arn_empty_resource_error
return Connection(error=arn_empty_resource_error)
except AWSAssumeRoleError as assume_role_error:
logger.error(str(assume_role_error))
logger.error(
f"{assume_role_error.__class__.__name__}[{assume_role_error.__traceback__.tb_lineno}]: {assume_role_error}"
)
if raise_on_exception:
raise assume_role_error
return Connection(error=assume_role_error)
@@ -1189,26 +1207,34 @@ class AwsProvider(Provider):
) from no_credentials_error
return Connection(error=no_credentials_error)
except AWSAccessKeyIDInvalid as access_key_id_invalid_error:
logger.error(str(access_key_id_invalid_error))
except AWSAccessKeyIDInvalidError as access_key_id_invalid_error:
logger.error(
f"{access_key_id_invalid_error.__class__.__name__}[{access_key_id_invalid_error.__traceback__.tb_lineno}]: {access_key_id_invalid_error}"
)
if raise_on_exception:
raise access_key_id_invalid_error
return Connection(error=access_key_id_invalid_error)
except AWSSecretAccessKeyInvalid as secret_access_key_invalid_error:
logger.error(str(secret_access_key_invalid_error))
except AWSSecretAccessKeyInvalidError as secret_access_key_invalid_error:
logger.error(
f"{secret_access_key_invalid_error.__class__.__name__}[{secret_access_key_invalid_error.__traceback__.tb_lineno}]: {secret_access_key_invalid_error}"
)
if raise_on_exception:
raise secret_access_key_invalid_error
return Connection(error=secret_access_key_invalid_error)
except AWSInvalidAccountCredentials as invalid_account_credentials_error:
logger.error(str(invalid_account_credentials_error))
except AWSInvalidProviderIdError as invalid_account_credentials_error:
logger.error(
f"{invalid_account_credentials_error.__class__.__name__}[{invalid_account_credentials_error.__traceback__.tb_lineno}]: {invalid_account_credentials_error}"
)
if raise_on_exception:
raise invalid_account_credentials_error
return Connection(error=invalid_account_credentials_error)
except AWSSessionTokenExpired as session_token_expired:
logger.error(str(session_token_expired))
except AWSSessionTokenExpiredError as session_token_expired:
logger.error(
f"{session_token_expired.__class__.__name__}[{session_token_expired.__traceback__.tb_lineno}]: {session_token_expired}"
)
if raise_on_exception:
raise session_token_expired
return Connection(error=session_token_expired)
+46 -45
View File
@@ -1,75 +1,76 @@
from prowler.exceptions.exceptions import ProwlerException
# Exceptions codes from 1000 to 1999 are reserved for AWS exceptions
class AWSBaseException(ProwlerException):
"""Base class for AWS errors."""
AWS_ERROR_CODES = {
(1902, "AWSClientError"): {
(1000, "AWSClientError"): {
"message": "AWS ClientError occurred",
"remediation": "Check your AWS client configuration and permissions.",
},
(1903, "AWSProfileNotFoundError"): {
(1001, "AWSProfileNotFoundError"): {
"message": "AWS Profile not found",
"remediation": "Ensure the AWS profile is correctly configured, please visit https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-files.html",
},
(1904, "AWSNoCredentialsError"): {
(1002, "AWSNoCredentialsError"): {
"message": "No AWS credentials found",
"remediation": "Verify that AWS credentials are properly set up, please visit https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/aws/authentication/ and https://docs.aws.amazon.com/cli/v1/userguide/cli-chap-configure.html",
},
(1905, "AWSArgumentTypeValidationError"): {
(1003, "AWSArgumentTypeValidationError"): {
"message": "AWS argument type validation error",
"remediation": "Check the provided argument types specific to AWS and ensure they meet the required format. For session duration check: https://docs.aws.amazon.com/singlesignon/latest/userguide/howtosessionduration.html and for role session name check: https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#iam-term-role-session-name",
},
(1906, "AWSSetUpSessionError"): {
(1004, "AWSSetUpSessionError"): {
"message": "AWS session setup error",
"remediation": "Check the AWS session setup and ensure it is properly configured, please visit https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html and check if the provided profile has the necessary permissions.",
},
(1907, "AWSIAMRoleARNRegionNotEmtpy"): {
(1005, "AWSIAMRoleARNRegionNotEmtpyError"): {
"message": "AWS IAM Role ARN region is not empty",
"remediation": "Check the AWS IAM Role ARN region and ensure it is empty, visit https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns for more information.",
},
(1908, "AWSIAMRoleARNPartitionEmpty"): {
(1006, "AWSIAMRoleARNPartitionEmptyError"): {
"message": "AWS IAM Role ARN partition is empty",
"remediation": "Check the AWS IAM Role ARN partition and ensure it is not empty, visit https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns for more information.",
},
(1909, "AWSIAMRoleARNMissingFields"): {
(1007, "AWSIAMRoleARNMissingFieldsError"): {
"message": "AWS IAM Role ARN missing fields",
"remediation": "Check the AWS IAM Role ARN and ensure all required fields are present, visit https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns for more information.",
},
(1910, "AWSIAMRoleARNServiceNotIAMnorSTS"): {
(1008, "AWSIAMRoleARNServiceNotIAMnorSTSError"): {
"message": "AWS IAM Role ARN service is not IAM nor STS",
"remediation": "Check the AWS IAM Role ARN service and ensure it is either IAM or STS, visit https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns for more information.",
},
(1911, "AWSIAMRoleARNInvalidAccountID"): {
(1009, "AWSIAMRoleARNInvalidAccountIDError"): {
"message": "AWS IAM Role ARN account ID is invalid",
"remediation": "Check the AWS IAM Role ARN account ID and ensure it is a valid 12-digit number, visit https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns for more information.",
},
(1912, "AWSIAMRoleARNInvalidResourceType"): {
(1010, "AWSIAMRoleARNInvalidResourceTypeError"): {
"message": "AWS IAM Role ARN resource type is invalid",
"remediation": "Check the AWS IAM Role ARN resource type and ensure it is valid, resources types are: role, user, assumed-role, root, federated-user, visit https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns for more information.",
},
(1913, "AWSIAMRoleARNEmptyResource"): {
(1011, "AWSIAMRoleARNEmptyResourceError"): {
"message": "AWS IAM Role ARN resource is empty",
"remediation": "Check the AWS IAM Role ARN resource and ensure it is not empty, visit https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-arns for more information.",
},
(1914, "AWSAssumeRoleError"): {
(1012, "AWSAssumeRoleError"): {
"message": "AWS assume role error",
"remediation": "Check the AWS assume role configuration and ensure it is properly set up, please visit https://docs.prowler.com/projects/prowler-open-source/en/latest/tutorials/aws/role-assumption/ and https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#iam-term-role-session-name",
},
(1915, "AWSAccessKeyIDInvalid"): {
(1013, "AWSAccessKeyIDInvalidError"): {
"message": "AWS Access Key ID or Session Token is invalid",
"remediation": "Check your AWS Access Key ID or Session Token and ensure it is valid.",
},
(1916, "AWSSecretAccessKeyInvalid"): {
(1014, "AWSSecretAccessKeyInvalidError"): {
"message": "AWS Secret Access Key is invalid",
"remediation": "Check your AWS Secret Access Key and signing method and ensure it is valid.",
},
(1917, "AWSInvalidAccountCredentials"): {
(1015, "AWSInvalidProviderIdError"): {
"message": "The provided AWS credentials belong to a different account",
"remediation": "Check the provided AWS credentials and review if belong to the account you want to use.",
},
(1918, "AWSSessionTokenExpired"): {
(1016, "AWSSessionTokenExpiredError"): {
"message": "The provided AWS Session Token is expired",
"remediation": "Get a new AWS Session Token and configure it for the provider.",
},
@@ -98,35 +99,35 @@ class AWSCredentialsError(AWSBaseException):
class AWSClientError(AWSCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1902, file=file, original_exception=original_exception, message=message
1000, file=file, original_exception=original_exception, message=message
)
class AWSProfileNotFoundError(AWSCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1903, file=file, original_exception=original_exception, message=message
1001, file=file, original_exception=original_exception, message=message
)
class AWSNoCredentialsError(AWSCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1904, file=file, original_exception=original_exception, message=message
1002, file=file, original_exception=original_exception, message=message
)
class AWSArgumentTypeValidationError(AWSBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1905, file=file, original_exception=original_exception, message=message
1003, file=file, original_exception=original_exception, message=message
)
class AWSSetUpSessionError(AWSBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1906, file=file, original_exception=original_exception, message=message
1004, file=file, original_exception=original_exception, message=message
)
@@ -137,85 +138,85 @@ class AWSRoleArnError(AWSBaseException):
super().__init__(code, file, original_exception, message)
class AWSIAMRoleARNRegionNotEmtpy(AWSRoleArnError):
class AWSIAMRoleARNRegionNotEmtpyError(AWSRoleArnError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1907, file=file, original_exception=original_exception, message=message
1005, file=file, original_exception=original_exception, message=message
)
class AWSIAMRoleARNPartitionEmpty(AWSRoleArnError):
class AWSIAMRoleARNPartitionEmptyError(AWSRoleArnError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1908, file=file, original_exception=original_exception, message=message
1006, file=file, original_exception=original_exception, message=message
)
class AWSIAMRoleARNMissingFields(AWSRoleArnError):
class AWSIAMRoleARNMissingFieldsError(AWSRoleArnError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1909, file=file, original_exception=original_exception, message=message
1007, file=file, original_exception=original_exception, message=message
)
class AWSIAMRoleARNServiceNotIAMnorSTS(AWSRoleArnError):
class AWSIAMRoleARNServiceNotIAMnorSTSError(AWSRoleArnError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1910, file=file, original_exception=original_exception, message=message
1008, file=file, original_exception=original_exception, message=message
)
class AWSIAMRoleARNInvalidAccountID(AWSRoleArnError):
class AWSIAMRoleARNInvalidAccountIDError(AWSRoleArnError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1911, file=file, original_exception=original_exception, message=message
1009, file=file, original_exception=original_exception, message=message
)
class AWSIAMRoleARNInvalidResourceType(AWSRoleArnError):
class AWSIAMRoleARNInvalidResourceTypeError(AWSRoleArnError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1912, file=file, original_exception=original_exception, message=message
1010, file=file, original_exception=original_exception, message=message
)
class AWSIAMRoleARNEmptyResource(AWSRoleArnError):
class AWSIAMRoleARNEmptyResourceError(AWSRoleArnError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1913, file=file, original_exception=original_exception, message=message
1011, file=file, original_exception=original_exception, message=message
)
class AWSAssumeRoleError(AWSBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1914, file=file, original_exception=original_exception, message=message
1012, file=file, original_exception=original_exception, message=message
)
class AWSAccessKeyIDInvalid(AWSCredentialsError):
class AWSAccessKeyIDInvalidError(AWSCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1915, file=file, original_exception=original_exception, message=message
1013, file=file, original_exception=original_exception, message=message
)
class AWSSecretAccessKeyInvalid(AWSCredentialsError):
class AWSSecretAccessKeyInvalidError(AWSCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1916, file=file, original_exception=original_exception, message=message
1014, file=file, original_exception=original_exception, message=message
)
class AWSInvalidAccountCredentials(AWSCredentialsError):
class AWSInvalidProviderIdError(AWSCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1917, file=file, original_exception=original_exception, message=message
1015, file=file, original_exception=original_exception, message=message
)
class AWSSessionTokenExpired(AWSCredentialsError):
class AWSSessionTokenExpiredError(AWSCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1918, file=file, original_exception=original_exception, message=message
1016, file=file, original_exception=original_exception, message=message
)
+12 -12
View File
@@ -3,12 +3,12 @@ import re
from argparse import ArgumentTypeError
from prowler.providers.aws.exceptions.exceptions import (
AWSIAMRoleARNEmptyResource,
AWSIAMRoleARNInvalidAccountID,
AWSIAMRoleARNInvalidResourceType,
AWSIAMRoleARNPartitionEmpty,
AWSIAMRoleARNRegionNotEmtpy,
AWSIAMRoleARNServiceNotIAMnorSTS,
AWSIAMRoleARNEmptyResourceError,
AWSIAMRoleARNInvalidAccountIDError,
AWSIAMRoleARNInvalidResourceTypeError,
AWSIAMRoleARNPartitionEmptyError,
AWSIAMRoleARNRegionNotEmtpyError,
AWSIAMRoleARNServiceNotIAMnorSTSError,
)
from prowler.providers.aws.lib.arn.models import ARN
@@ -25,7 +25,7 @@ def parse_iam_credentials_arn(arn: str) -> ARN:
arn_parsed = ARN(arn)
# First check if region is empty (in IAM ARN's region is always empty)
if arn_parsed.region:
raise AWSIAMRoleARNRegionNotEmtpy(file=os.path.basename(__file__))
raise AWSIAMRoleARNRegionNotEmtpyError(file=os.path.basename(__file__))
else:
# check if needed fields are filled:
# - partition
@@ -34,15 +34,15 @@ def parse_iam_credentials_arn(arn: str) -> ARN:
# - resource_type
# - resource
if arn_parsed.partition is None or arn_parsed.partition == "":
raise AWSIAMRoleARNPartitionEmpty(file=os.path.basename(__file__))
raise AWSIAMRoleARNPartitionEmptyError(file=os.path.basename(__file__))
elif arn_parsed.service != "iam" and arn_parsed.service != "sts":
raise AWSIAMRoleARNServiceNotIAMnorSTS(file=os.path.basename(__file__))
raise AWSIAMRoleARNServiceNotIAMnorSTSError(file=os.path.basename(__file__))
elif (
arn_parsed.account_id is None
or len(arn_parsed.account_id) != 12
or not arn_parsed.account_id.isnumeric()
):
raise AWSIAMRoleARNInvalidAccountID(file=os.path.basename(__file__))
raise AWSIAMRoleARNInvalidAccountIDError(file=os.path.basename(__file__))
elif (
arn_parsed.resource_type != "role"
and arn_parsed.resource_type != "user"
@@ -50,9 +50,9 @@ def parse_iam_credentials_arn(arn: str) -> ARN:
and arn_parsed.resource_type != "root"
and arn_parsed.resource_type != "federated-user"
):
raise AWSIAMRoleARNInvalidResourceType(file=os.path.basename(__file__))
raise AWSIAMRoleARNInvalidResourceTypeError(file=os.path.basename(__file__))
elif arn_parsed.resource == "":
raise AWSIAMRoleARNEmptyResource(file=os.path.basename(__file__))
raise AWSIAMRoleARNEmptyResourceError(file=os.path.basename(__file__))
else:
return arn_parsed
+2 -2
View File
@@ -3,7 +3,7 @@ from typing import Optional
from pydantic import BaseModel
from prowler.providers.aws.exceptions.exceptions import AWSIAMRoleARNMissingFields
from prowler.providers.aws.exceptions.exceptions import AWSIAMRoleARNMissingFieldsError
class ARN(BaseModel):
@@ -19,7 +19,7 @@ class ARN(BaseModel):
# Validate the ARN
## Check that arn starts with arn
if not arn.startswith("arn:"):
raise AWSIAMRoleARNMissingFields(file=os.path.basename(__file__))
raise AWSIAMRoleARNMissingFieldsError(file=os.path.basename(__file__))
## Retrieve fields
arn_elements = arn.split(":", 5)
data = {
+62 -24
View File
@@ -32,10 +32,10 @@ from prowler.providers.azure.exceptions.exceptions import (
AzureGetTokenIdentityError,
AzureHTTPResponseError,
AzureInteractiveBrowserCredentialError,
AzureInvalidAccountCredentialsError,
AzureInvalidProviderIdError,
AzureNoAuthenticationMethodError,
AzureNoSubscriptionsError,
AzureNotTenantIdButClientIdAndClienSecret,
AzureNotTenantIdButClientIdAndClienSecretError,
AzureNotValidClientIdError,
AzureNotValidClientSecretError,
AzureNotValidTenantIdError,
@@ -320,7 +320,7 @@ class AzureProvider(Provider):
)
else:
if not tenant_id:
raise AzureNotTenantIdButClientIdAndClienSecret(
raise AzureNotTenantIdButClientIdAndClienSecretError(
file=os.path.basename(__file__),
message="Tenant Id is required for Azure static credentials. Make sure you are using the correct credentials.",
)
@@ -621,7 +621,7 @@ class AzureProvider(Provider):
if provider_id and provider_id not in [
sub.subscription_id for sub in available_subscriptions
]:
raise AzureInvalidAccountCredentialsError(
raise AzureInvalidProviderIdError(
file=os.path.basename(__file__),
message="The provided credentials are not valid for the specified Azure subscription.",
)
@@ -631,88 +631,120 @@ class AzureProvider(Provider):
return Connection(is_connected=True)
# Exceptions from validate_arguments
except AzureNoAuthenticationMethodError as no_auth_method_error:
logger.error(str(no_auth_method_error))
logger.error(
f"{no_auth_method_error.__class__.__name__}[{no_auth_method_error.__traceback__.tb_lineno}]: {no_auth_method_error}"
)
if raise_on_exception:
raise no_auth_method_error
return Connection(error=no_auth_method_error)
except AzureBrowserAuthNoTenantIDError as browser_no_tenant_error:
logger.error(str(browser_no_tenant_error))
logger.error(
f"{browser_no_tenant_error.__class__.__name__}[{browser_no_tenant_error.__traceback__.tb_lineno}]: {browser_no_tenant_error}"
)
if raise_on_exception:
raise browser_no_tenant_error
return Connection(error=browser_no_tenant_error)
except AzureTenantIDNoBrowserAuthError as tenant_no_browser_error:
logger.error(str(tenant_no_browser_error))
logger.error(
f"{tenant_no_browser_error.__class__.__name__}[{tenant_no_browser_error.__traceback__.tb_lineno}]: {tenant_no_browser_error}"
)
# Exceptions from setup_region_config
except AzureArgumentTypeValidationError as type_validation_error:
logger.error(str(type_validation_error))
logger.error(
f"{type_validation_error.__class__.__name__}[{type_validation_error.__traceback__.tb_lineno}]: {type_validation_error}"
)
if raise_on_exception:
raise type_validation_error
return Connection(error=type_validation_error)
except AzureSetUpRegionConfigError as region_config_error:
logger.error(str(region_config_error))
logger.error(
f"{region_config_error.__class__.__name__}[{region_config_error.__traceback__.tb_lineno}]: {region_config_error}"
)
if raise_on_exception:
raise region_config_error
return Connection(error=region_config_error)
# Exceptions from setup_session
except AzureEnvironmentVariableError as environment_credentials_error:
logger.error(str(environment_credentials_error))
logger.error(
f"{environment_credentials_error.__class__.__name__}[{environment_credentials_error.__traceback__.tb_lineno}]: {environment_credentials_error}"
)
if raise_on_exception:
raise environment_credentials_error
return Connection(error=environment_credentials_error)
except AzureDefaultAzureCredentialError as default_credentials_error:
logger.error(str(default_credentials_error))
logger.error(
f"{default_credentials_error.__class__.__name__}[{default_credentials_error.__traceback__.tb_lineno}]: {default_credentials_error}"
)
if raise_on_exception:
raise default_credentials_error
return Connection(error=default_credentials_error)
except AzureInteractiveBrowserCredentialError as interactive_browser_error:
logger.error(str(interactive_browser_error))
logger.error(
f"{interactive_browser_error.__class__.__name__}[{interactive_browser_error.__traceback__.tb_lineno}]: {interactive_browser_error}"
)
if raise_on_exception:
raise interactive_browser_error
return Connection(error=interactive_browser_error)
except AzureConfigCredentialsError as config_credentials_error:
logger.error(str(config_credentials_error))
logger.error(
f"{config_credentials_error.__class__.__name__}[{config_credentials_error.__traceback__.tb_lineno}]: {config_credentials_error}"
)
if raise_on_exception:
raise config_credentials_error
return Connection(error=config_credentials_error)
except AzureClientAuthenticationError as client_auth_error:
logger.error(str(client_auth_error))
logger.error(
f"{client_auth_error.__class__.__name__}[{client_auth_error.__traceback__.tb_lineno}]: {client_auth_error}"
)
if raise_on_exception:
raise client_auth_error
return Connection(error=client_auth_error)
except AzureCredentialsUnavailableError as credential_unavailable_error:
logger.error(str(credential_unavailable_error))
logger.error(
f"{credential_unavailable_error.__class__.__name__}[{credential_unavailable_error.__traceback__.tb_lineno}]: {credential_unavailable_error}"
)
if raise_on_exception:
raise credential_unavailable_error
return Connection(error=credential_unavailable_error)
except AzureDefaultAzureCredentialError as default_credentials_error:
logger.error(str(default_credentials_error))
logger.error(
f"{default_credentials_error.__class__.__name__}[{default_credentials_error.__traceback__.tb_lineno}]: {default_credentials_error}"
)
if raise_on_exception:
raise default_credentials_error
return Connection(error=default_credentials_error)
except (
AzureClientIdAndClientSecretNotBelongingToTenantIdError
) as tenant_id_error:
logger.error(str(tenant_id_error))
logger.error(
f"{tenant_id_error.__class__.__name__}[{tenant_id_error.__traceback__.tb_lineno}]: {tenant_id_error}"
)
if raise_on_exception:
raise tenant_id_error
return Connection(error=tenant_id_error)
except (
AzureTenantIdAndClientSecretNotBelongingToClientIdError
) as client_id_error:
logger.error(str(client_id_error))
logger.error(
f"{client_id_error.__class__.__name__}[{client_id_error.__traceback__.tb_lineno}]: {client_id_error}"
)
if raise_on_exception:
raise client_id_error
return Connection(error=client_id_error)
except (
AzureTenantIdAndClientIdNotBelongingToClientSecretError
) as client_secret_error:
logger.error(str(client_secret_error))
logger.error(
f"{client_secret_error.__class__.__name__}[{client_secret_error.__traceback__.tb_lineno}]: {client_secret_error}"
)
if raise_on_exception:
raise client_secret_error
return Connection(error=client_secret_error)
# Exceptions from provider_id validation
except AzureInvalidAccountCredentialsError as invalid_credentials_error:
logger.error(str(invalid_credentials_error))
except AzureInvalidProviderIdError as invalid_credentials_error:
logger.error(
f"{invalid_credentials_error.__class__.__name__}[{invalid_credentials_error.__traceback__.tb_lineno}]: {invalid_credentials_error}"
)
if raise_on_exception:
raise invalid_credentials_error
return Connection(error=invalid_credentials_error)
@@ -998,19 +1030,25 @@ class AzureProvider(Provider):
"client_secret": client_secret,
}
except AzureNotValidTenantIdError as tenant_id_error:
logger.error(str(tenant_id_error))
logger.error(
f"{tenant_id_error.__class__.__name__}[{tenant_id_error.__traceback__.tb_lineno}]: {tenant_id_error}"
)
raise AzureClientIdAndClientSecretNotBelongingToTenantIdError(
file=os.path.basename(__file__),
message="The provided Azure Client ID and Client Secret do not belong to the specified Tenant ID.",
)
except AzureNotValidClientIdError as client_id_error:
logger.error(str(client_id_error))
logger.error(
f"{client_id_error.__class__.__name__}[{client_id_error.__traceback__.tb_lineno}]: {client_id_error}"
)
raise AzureTenantIdAndClientSecretNotBelongingToClientIdError(
file=os.path.basename(__file__),
message="The provided Azure Tenant ID and Client Secret do not belong to the specified Client ID.",
)
except AzureNotValidClientSecretError as client_secret_error:
logger.error(str(client_secret_error))
logger.error(
f"{client_secret_error.__class__.__name__}[{client_secret_error.__traceback__.tb_lineno}]: {client_secret_error}"
)
raise AzureTenantIdAndClientIdNotBelongingToClientSecretError(
file=os.path.basename(__file__),
message="The provided Azure Tenant ID and Client ID do not belong to the specified Client Secret.",
@@ -1,103 +1,104 @@
from prowler.exceptions.exceptions import ProwlerException
# Exceptions codes from 2000 to 2999 are reserved for Azure exceptions
class AzureBaseException(ProwlerException):
"""Base class for Azure Errors."""
AZURE_ERROR_CODES = {
(1914, "AzureEnvironmentVariableError"): {
(2000, "AzureEnvironmentVariableError"): {
"message": "Azure environment variable error",
"remediation": "Check the Azure environment variables and ensure they are properly set.",
},
(1915, "AzureNoSubscriptionsError"): {
(2001, "AzureNoSubscriptionsError"): {
"message": "No Azure subscriptions found",
"remediation": "Check the Azure subscriptions and ensure they are properly set up.",
},
(1916, "AzureSetUpIdentityError"): {
(2002, "AzureSetUpIdentityError"): {
"message": "Azure identity setup error related with credentials",
"remediation": "Check credentials and ensure they are properly set up for Azure and the identity provider.",
},
(1917, "AzureNoAuthenticationMethodError"): {
(2003, "AzureNoAuthenticationMethodError"): {
"message": "No Azure authentication method found",
"remediation": "Check that any authentication method is properly set up for Azure.",
},
(1918, "AzureBrowserAuthNoTenantIDError"): {
(2004, "AzureBrowserAuthNoTenantIDError"): {
"message": "Azure browser authentication error: no tenant ID found",
"remediation": "To use browser authentication, ensure the tenant ID is properly set.",
},
(1919, "AzureTenantIDNoBrowserAuthError"): {
(2005, "AzureTenantIDNoBrowserAuthError"): {
"message": "Azure tenant ID error: browser authentication not found",
"remediation": "To use browser authentication, both the tenant ID and browser authentication must be properly set.",
},
(1920, "AzureArgumentTypeValidationError"): {
(2006, "AzureArgumentTypeValidationError"): {
"message": "Azure argument type validation error",
"remediation": "Check the provided argument types specific to Azure and ensure they meet the required format.",
},
(1921, "AzureSetUpRegionConfigError"): {
(2007, "AzureSetUpRegionConfigError"): {
"message": "Azure region configuration setup error",
"remediation": "Check the Azure region configuration and ensure it is properly set up.",
},
(1922, "AzureDefaultAzureCredentialError"): {
(2008, "AzureDefaultAzureCredentialError"): {
"message": "Error in DefaultAzureCredential",
"remediation": "Check that all the attributes are properly set up for the DefaultAzureCredential.",
},
(1923, "AzureInteractiveBrowserCredentialError"): {
(2009, "AzureInteractiveBrowserCredentialError"): {
"message": "Error retrieving InteractiveBrowserCredential",
"remediation": "Check your browser and ensure that the tenant ID and browser authentication are properly set.",
},
(1924, "AzureHTTPResponseError"): {
(2010, "AzureHTTPResponseError"): {
"message": "Error in HTTP response from Azure",
"remediation": "",
},
(1925, "AzureCredentialsUnavailableError"): {
(2011, "AzureCredentialsUnavailableError"): {
"message": "Error trying to configure Azure credentials because they are unavailable",
"remediation": "Check the dictionary and ensure it is properly set up for Azure credentials. TENANT_ID, CLIENT_ID and CLIENT_SECRET are required.",
},
(1926, "AzureGetTokenIdentityError"): {
(2012, "AzureGetTokenIdentityError"): {
"message": "Error trying to get token from Azure Identity",
"remediation": "Check the Azure Identity and ensure it is properly set up.",
},
(1927, "AzureNotTenantIdButClientIdAndClienSecret"): {
(2013, "AzureNotTenantIdButClientIdAndClienSecretError"): {
"message": "The provided credentials are not a tenant ID but a client ID and client secret",
"remediation": "Tenant Id, Client Id and Client Secret are required for Azure credentials. Make sure you are using the correct credentials.",
},
(1928, "AzureClientAuthenticationError"): {
(2014, "AzureClientAuthenticationError"): {
"message": "Error in client authentication",
"remediation": "Check the client authentication and ensure it is properly set up.",
},
(1929, "AzureSetUpSessionError"): {
(2015, "AzureSetUpSessionError"): {
"message": "Error setting up session",
"remediation": "Check the session setup and ensure it is properly set up.",
},
(1930, "AzureNotValidTenantIdError"): {
(2016, "AzureNotValidTenantIdError"): {
"message": "The provided tenant ID is not valid",
"remediation": "Check the tenant ID and ensure it is a valid ID.",
},
(1931, "AzureNotValidClientIdError"): {
(2017, "AzureNotValidClientIdError"): {
"message": "The provided client ID is not valid",
"remediation": "Check the client ID and ensure it is a valid ID.",
},
(1932, "AzureNotValidClientSecretError"): {
(2018, "AzureNotValidClientSecretError"): {
"message": "The provided client secret is not valid",
"remediation": "Check the client secret and ensure it is a valid secret.",
},
(1933, "AzureConfigCredentialsError"): {
(2019, "AzureConfigCredentialsError"): {
"message": "Error in configuration of Azure credentials",
"remediation": "Check the configuration of Azure credentials and ensure it is properly set up.",
},
(1934, "AzureClientIdAndClientSecretNotBelongingToTenantIdError"): {
(2020, "AzureClientIdAndClientSecretNotBelongingToTenantIdError"): {
"message": "The provided client ID and client secret do not belong to the provided tenant ID",
"remediation": "Check the client ID and client secret and ensure they belong to the provided tenant ID.",
},
(1935, "AzureTenantIdAndClientSecretNotBelongingToClientIdError"): {
(2021, "AzureTenantIdAndClientSecretNotBelongingToClientIdError"): {
"message": "The provided tenant ID and client secret do not belong to the provided client ID",
"remediation": "Check the tenant ID and client secret and ensure they belong to the provided client ID.",
},
(1936, "AzureTenantIdAndClientIdNotBelongingToClientSecretError"): {
(2022, "AzureTenantIdAndClientIdNotBelongingToClientSecretError"): {
"message": "The provided tenant ID and client ID do not belong to the provided client secret",
"remediation": "Check the tenant ID and client ID and ensure they belong to the provided client secret.",
},
(1937, "AzureInvalidAccountCredentialsError"): {
(2023, "AzureInvalidProviderIdError"): {
"message": "The provided provider_id does not match with the available subscriptions",
"remediation": "Check the provider_id and ensure it is a valid subscription for the given credentials.",
},
@@ -127,166 +128,166 @@ class AzureCredentialsError(AzureBaseException):
class AzureEnvironmentVariableError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1914, file=file, original_exception=original_exception, message=message
2000, file=file, original_exception=original_exception, message=message
)
class AzureNoSubscriptionsError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1915, file=file, original_exception=original_exception, message=message
2001, file=file, original_exception=original_exception, message=message
)
class AzureSetUpIdentityError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1916, file=file, original_exception=original_exception, message=message
2002, file=file, original_exception=original_exception, message=message
)
class AzureNoAuthenticationMethodError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1917, file=file, original_exception=original_exception, message=message
2003, file=file, original_exception=original_exception, message=message
)
class AzureBrowserAuthNoTenantIDError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1918, file=file, original_exception=original_exception, message=message
2004, file=file, original_exception=original_exception, message=message
)
class AzureTenantIDNoBrowserAuthError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1919, file=file, original_exception=original_exception, message=message
2005, file=file, original_exception=original_exception, message=message
)
class AzureArgumentTypeValidationError(AzureBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1920, file=file, original_exception=original_exception, message=message
2006, file=file, original_exception=original_exception, message=message
)
class AzureSetUpRegionConfigError(AzureBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1921, file=file, original_exception=original_exception, message=message
2007, file=file, original_exception=original_exception, message=message
)
class AzureDefaultAzureCredentialError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1922, file=file, original_exception=original_exception, message=message
2008, file=file, original_exception=original_exception, message=message
)
class AzureInteractiveBrowserCredentialError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1923, file=file, original_exception=original_exception, message=message
2009, file=file, original_exception=original_exception, message=message
)
class AzureHTTPResponseError(AzureBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1924, file=file, original_exception=original_exception, message=message
2010, file=file, original_exception=original_exception, message=message
)
class AzureCredentialsUnavailableError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1925, file=file, original_exception=original_exception, message=message
2011, file=file, original_exception=original_exception, message=message
)
class AzureGetTokenIdentityError(AzureBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1926, file=file, original_exception=original_exception, message=message
2012, file=file, original_exception=original_exception, message=message
)
class AzureNotTenantIdButClientIdAndClienSecret(AzureCredentialsError):
class AzureNotTenantIdButClientIdAndClienSecretError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1927, file=file, original_exception=original_exception, message=message
2013, file=file, original_exception=original_exception, message=message
)
class AzureClientAuthenticationError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1928, file=file, original_exception=original_exception, message=message
2014, file=file, original_exception=original_exception, message=message
)
class AzureSetUpSessionError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1929, file=file, original_exception=original_exception, message=message
2015, file=file, original_exception=original_exception, message=message
)
class AzureNotValidTenantIdError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1930, file=file, original_exception=original_exception, message=message
2016, file=file, original_exception=original_exception, message=message
)
class AzureNotValidClientIdError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1931, file=file, original_exception=original_exception, message=message
2017, file=file, original_exception=original_exception, message=message
)
class AzureNotValidClientSecretError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1932, file=file, original_exception=original_exception, message=message
2018, file=file, original_exception=original_exception, message=message
)
class AzureConfigCredentialsError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1933, file=file, original_exception=original_exception, message=message
2019, file=file, original_exception=original_exception, message=message
)
class AzureClientIdAndClientSecretNotBelongingToTenantIdError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1934, file=file, original_exception=original_exception, message=message
2020, file=file, original_exception=original_exception, message=message
)
class AzureTenantIdAndClientSecretNotBelongingToClientIdError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1935, file=file, original_exception=original_exception, message=message
2021, file=file, original_exception=original_exception, message=message
)
class AzureTenantIdAndClientIdNotBelongingToClientSecretError(AzureCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1936, file=file, original_exception=original_exception, message=message
2022, file=file, original_exception=original_exception, message=message
)
class AzureInvalidAccountCredentialsError(AzureBaseException):
class AzureInvalidProviderIdError(AzureBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1937, file=file, original_exception=original_exception, message=message
2023, file=file, original_exception=original_exception, message=message
)
+20 -19
View File
@@ -1,43 +1,44 @@
from prowler.exceptions.exceptions import ProwlerException
# Exceptions codes from 3000 to 3999 are reserved for GCP exceptions
class GCPBaseException(ProwlerException):
"""Base class for GCP Errors."""
GCP_ERROR_CODES = {
(1925, "GCPCloudResourceManagerAPINotUsedError"): {
(3000, "GCPCloudResourceManagerAPINotUsedError"): {
"message": "Cloud Resource Manager API not used",
"remediation": "Enable the Cloud Resource Manager API for the project.",
},
(1926, "GCPHTTPError"): {
(3001, "GCPHTTPError"): {
"message": "HTTP error",
"remediation": "Check the HTTP error and ensure the request is properly formatted.",
},
(1927, "GCPNoAccesibleProjectsError"): {
(3002, "GCPNoAccesibleProjectsError"): {
"message": "No Project IDs can be accessed via Google Credentials",
"remediation": "Ensure the project is accessible and properly set up.",
},
(1928, "GCPSetUpSessionError"): {
(3003, "GCPSetUpSessionError"): {
"message": "Error setting up session",
"remediation": "Check the session setup and ensure it is properly set up.",
},
(1929, "GCPGetProjectError"): {
(3004, "GCPGetProjectError"): {
"message": "Error getting project",
"remediation": "Check the project and ensure it is properly set up.",
},
(1930, "GCPTestConnectionError"): {
(3005, "GCPTestConnectionError"): {
"message": "Error testing connection to GCP",
"remediation": "Check the connection and ensure it is properly set up.",
},
(1931, "GCPLoadCredentialsFromDictError"): {
(3006, "GCPLoadCredentialsFromDictError"): {
"message": "Error loading credentials from dictionary",
"remediation": "Check the credentials and ensure they are properly set up. client_id, client_secret and refresh_token are required.",
},
(1932, "GCPStaticCredentialsError"): {
(3007, "GCPStaticCredentialsError"): {
"message": "Error loading static credentials",
"remediation": "Check the credentials and ensure they are properly set up. client_id, client_secret and refresh_token are required.",
},
(1933, "GCPInvalidAccountCredentials"): {
(3008, "GCPInvalidProviderIdError"): {
"message": "Provider does not match with the expected project_id",
"remediation": "Check the provider and ensure it matches the expected project_id.",
},
@@ -67,61 +68,61 @@ class GCPCredentialsError(GCPBaseException):
class GCPCloudResourceManagerAPINotUsedError(GCPBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1925, file=file, original_exception=original_exception, message=message
3000, file=file, original_exception=original_exception, message=message
)
class GCPHTTPError(GCPBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1926, file=file, original_exception=original_exception, message=message
3001, file=file, original_exception=original_exception, message=message
)
class GCPNoAccesibleProjectsError(GCPCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1927, file=file, original_exception=original_exception, message=message
3002, file=file, original_exception=original_exception, message=message
)
class GCPSetUpSessionError(GCPCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1928, file=file, original_exception=original_exception, message=message
3003, file=file, original_exception=original_exception, message=message
)
class GCPGetProjectError(GCPCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1929, file=file, original_exception=original_exception, message=message
3004, file=file, original_exception=original_exception, message=message
)
class GCPTestConnectionError(GCPBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1930, file=file, original_exception=original_exception, message=message
3005, file=file, original_exception=original_exception, message=message
)
class GCPLoadCredentialsFromDictError(GCPCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1931, file=file, original_exception=original_exception, message=message
3006, file=file, original_exception=original_exception, message=message
)
class GCPStaticCredentialsError(GCPCredentialsError):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1932, file=file, original_exception=original_exception, message=message
3007, file=file, original_exception=original_exception, message=message
)
class GCPInvalidAccountCredentials(GCPBaseException):
class GCPInvalidProviderIdError(GCPBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(
1933, file=file, original_exception=original_exception, message=message
3008, file=file, original_exception=original_exception, message=message
)
+13 -7
View File
@@ -19,7 +19,7 @@ from prowler.providers.gcp.exceptions.exceptions import (
GCPCloudResourceManagerAPINotUsedError,
GCPGetProjectError,
GCPHTTPError,
GCPInvalidAccountCredentials,
GCPInvalidProviderIdError,
GCPLoadCredentialsFromDictError,
GCPNoAccesibleProjectsError,
GCPSetUpSessionError,
@@ -340,12 +340,16 @@ class GcpProvider(Provider):
# Errors from setup_session
except GCPLoadCredentialsFromDictError as load_credentials_error:
logger.critical(str(load_credentials_error))
logger.critical(
f"{load_credentials_error.__class__.__name__}[{load_credentials_error.__traceback__.tb_lineno}]: {load_credentials_error}"
)
if raise_on_exception:
raise load_credentials_error
return Connection(error=load_credentials_error)
except GCPSetUpSessionError as setup_session_error:
logger.critical(str(setup_session_error))
logger.critical(
f"{setup_session_error.__class__.__name__}[{setup_session_error.__traceback__.tb_lineno}]: {setup_session_error}"
)
if raise_on_exception:
raise setup_session_error
return Connection(error=setup_session_error)
@@ -366,8 +370,10 @@ class GcpProvider(Provider):
raise http_error
return Connection(error=http_error)
# Exceptions from validating Provider ID
except GCPInvalidAccountCredentials as not_valid_provider_id_error:
logger.critical(str(not_valid_provider_id_error))
except GCPInvalidProviderIdError as not_valid_provider_id_error:
logger.critical(
f"{not_valid_provider_id_error.__class__.__name__}[{not_valid_provider_id_error.__traceback__.tb_lineno}]: {not_valid_provider_id_error}"
)
if raise_on_exception:
raise not_valid_provider_id_error
return Connection(error=not_valid_provider_id_error)
@@ -563,7 +569,7 @@ class GcpProvider(Provider):
None
Raises:
GCPInvalidAccountCredentials if the provider ID does not match with the expected project_id
GCPInvalidProviderIdError if the provider ID does not match with the expected project_id
"""
available_projects = list(
@@ -576,7 +582,7 @@ class GcpProvider(Provider):
message="No Project IDs can be accessed via Google Credentials.",
)
elif provider_id not in available_projects:
raise GCPInvalidAccountCredentials(
raise GCPInvalidProviderIdError(
file=__file__,
message="The provider ID does not match with the expected project_id.",
)
@@ -1,35 +1,36 @@
from prowler.exceptions.exceptions import ProwlerException
# Exceptions codes from 4000 to 4999 are reserved for Kubernetes exceptions
class KubernetesBaseException(ProwlerException):
"""Base class for Kubernetes errors."""
KUBERNETES_ERROR_CODES = {
(1931, "KubernetesCloudResourceManagerAPINotUsedError"): {
(4000, "KubernetesCloudResourceManagerAPINotUsedError"): {
"message": "Cloud Resource Manager API is not enabled, blocking access to necessary resources.",
"remediation": "Refer to the Kubernetes documentation to enable the Cloud Resource Manager API: https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
},
(1932, "KubernetesSetUpSessionError"): {
(4001, "KubernetesSetUpSessionError"): {
"message": "Failed to establish a Kubernetes session, preventing further actions.",
"remediation": "Verify your session setup, including credentials and Kubernetes cluster configuration. Refer to this guide for proper setup: https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/",
},
(1933, "KubernetesAPIError"): {
(4002, "KubernetesAPIError"): {
"message": "An error occurred while interacting with the Kubernetes API.",
"remediation": "Check the API request and ensure it is properly formatted. Refer to the Kubernetes API documentation for guidance: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/",
},
(1934, "KubernetesTimeoutError"): {
(4003, "KubernetesTimeoutError"): {
"message": "The request to the Kubernetes API timed out.",
"remediation": "Check the network connection and the Kubernetes API server status. For information on troubleshooting timeouts, refer to the Kubernetes documentation: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#-strong-timeout-strong-",
},
(1935, "KubernetesError"): {
(4004, "KubernetesError"): {
"message": "An error occurred in the Kubernetes provider.",
"remediation": "Check the provider code and configuration to identify the issue. For more information on troubleshooting Kubernetes providers, refer to the Kubernetes documentation: https://kubernetes.io/docs/reference/",
},
(1936, "KubernetesInvalidProviderIdError"): {
(4005, "KubernetesInvalidProviderIdError"): {
"message": "The provider ID is invalid.",
"remediation": "Check the provider ID and ensure it is correctly formatted. Refer to the Kubernetes documentation for guidance on provider IDs: https://kubernetes.io/docs/reference/access-authn-authz/rbac/",
},
(1937, "KubernetesInvalidKubeConfigFileError"): {
(4006, "KubernetesInvalidKubeConfigFileError"): {
"message": "The provided kube-config is invalid.",
"remediation": "Review the kube-config and the attached error to get more details. Please, refer to the Kubernetes config documentation: https://kubernetes.io/docs/reference/config-api/kubeconfig.v1/#Config",
},
@@ -57,34 +58,34 @@ class KubernetesBaseException(ProwlerException):
class KubernetesError(KubernetesBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(1935, file, original_exception, message)
super().__init__(4004, file, original_exception, message)
class KubernetesCloudResourceManagerAPINotUsedError(KubernetesBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(1931, file, original_exception, message)
super().__init__(4000, file, original_exception, message)
class KubernetesSetUpSessionError(KubernetesBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(1932, file, original_exception, message)
super().__init__(4001, file, original_exception, message)
class KubernetesAPIError(KubernetesBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(1933, file, original_exception, message)
super().__init__(4002, file, original_exception, message)
class KubernetesTimeoutError(KubernetesBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(1934, file, original_exception, message)
super().__init__(4003, file, original_exception, message)
class KubernetesInvalidProviderIdError(KubernetesBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(1936, file, original_exception, message)
super().__init__(4005, file, original_exception, message)
class KubernetesInvalidKubeConfigFileError(KubernetesBaseException):
def __init__(self, file=None, original_exception=None, message=None):
super().__init__(1937, file, original_exception, message)
super().__init__(4006, file, original_exception, message)
+14 -14
View File
@@ -28,8 +28,8 @@ from prowler.providers.aws.config import (
)
from prowler.providers.aws.exceptions.exceptions import (
AWSArgumentTypeValidationError,
AWSIAMRoleARNInvalidResourceType,
AWSInvalidAccountCredentials,
AWSIAMRoleARNInvalidResourceTypeError,
AWSInvalidProviderIdError,
AWSNoCredentialsError,
)
from prowler.providers.aws.lib.arn.models import ARN
@@ -1265,7 +1265,7 @@ aws:
) # No profile to avoid ProfileNotFound error
assert exception.type == AWSNoCredentialsError
assert "AWSNoCredentialsError[1904]: No AWS credentials found" in str(
assert "AWSNoCredentialsError[1002]: No AWS credentials found" in str(
exception.value
)
@@ -1307,7 +1307,7 @@ aws:
assert exception.type == AWSArgumentTypeValidationError
assert (
exception.value.args[0]
== "[1905] Session Duration must be between 900 and 43200 seconds."
== "[1003] Session Duration must be between 900 and 43200 seconds."
)
@mock_aws
@@ -1327,7 +1327,7 @@ aws:
assert isinstance(connection.error, AWSArgumentTypeValidationError)
assert (
connection.error.args[0]
== "[1905] Session Duration must be between 900 and 43200 seconds."
== "[1003] Session Duration must be between 900 and 43200 seconds."
)
@mock_aws
@@ -1343,7 +1343,7 @@ aws:
assert exception.type == AWSArgumentTypeValidationError
assert (
exception.value.args[0]
== "[1905] Role Session Name must be between 2 and 64 characters and may contain alphanumeric characters, periods, hyphens, and underscores."
== "[1003] Role Session Name must be between 2 and 64 characters and may contain alphanumeric characters, periods, hyphens, and underscores."
)
@mock_aws
@@ -1351,13 +1351,13 @@ aws:
role_name = "test-role"
role_arn = f"arn:{AWS_COMMERCIAL_PARTITION}:iam::{AWS_ACCOUNT_NUMBER}:not-role/{role_name}"
with raises(AWSIAMRoleARNInvalidResourceType) as exception:
with raises(AWSIAMRoleARNInvalidResourceTypeError) as exception:
AwsProvider.test_connection(role_arn=role_arn)
assert exception.type == AWSIAMRoleARNInvalidResourceType
assert exception.type == AWSIAMRoleARNInvalidResourceTypeError
assert (
exception.value.args[0]
== "[1912] AWS IAM Role ARN resource type is invalid"
== "[1010] AWS IAM Role ARN resource type is invalid"
)
@mock_aws
@@ -1429,13 +1429,13 @@ aws:
"provider_id": "111122223333",
}
with raises(AWSInvalidAccountCredentials) as exception:
with raises(AWSInvalidProviderIdError) as exception:
AwsProvider.test_connection(**session_credentials)
assert exception.type == AWSInvalidAccountCredentials
assert exception.type == AWSInvalidProviderIdError
assert (
exception.value.args[0]
== "[1917] The provided AWS credentials belong to a different account"
== "[1015] The provided AWS credentials belong to a different account"
)
@mock_aws
@@ -1456,12 +1456,12 @@ aws:
assert isinstance(connection, Connection)
assert not connection.is_connected
assert isinstance(connection.error, AWSInvalidAccountCredentials)
assert isinstance(connection.error, AWSInvalidProviderIdError)
assert (
connection.error.message
== "The provided AWS credentials belong to a different account"
)
assert connection.error.code == 1917
assert connection.error.code == 1015
@mock_aws
def test_create_sts_session(self):
+21 -21
View File
@@ -1,13 +1,13 @@
from pytest import raises
from prowler.providers.aws.exceptions.exceptions import (
AWSIAMRoleARNEmptyResource,
AWSIAMRoleARNInvalidAccountID,
AWSIAMRoleARNInvalidResourceType,
AWSIAMRoleARNMissingFields,
AWSIAMRoleARNPartitionEmpty,
AWSIAMRoleARNRegionNotEmtpy,
AWSIAMRoleARNServiceNotIAMnorSTS,
AWSIAMRoleARNEmptyResourceError,
AWSIAMRoleARNInvalidAccountIDError,
AWSIAMRoleARNInvalidResourceTypeError,
AWSIAMRoleARNMissingFieldsError,
AWSIAMRoleARNPartitionEmptyError,
AWSIAMRoleARNRegionNotEmtpyError,
AWSIAMRoleARNServiceNotIAMnorSTSError,
)
from prowler.providers.aws.lib.arn.arn import is_valid_arn, parse_iam_credentials_arn
from prowler.providers.aws.lib.arn.models import ARN
@@ -327,54 +327,54 @@ class Test_ARN_Parsing:
self,
):
input_arn = ""
with raises(AWSIAMRoleARNMissingFields) as error:
with raises(AWSIAMRoleARNMissingFieldsError) as error:
parse_iam_credentials_arn(input_arn)
assert error._excinfo[0] == AWSIAMRoleARNMissingFields
assert error._excinfo[0] == AWSIAMRoleARNMissingFieldsError
def test_iam_credentials_arn_parsing_raising_AWSIAMRoleARNRegionNotEmtpy(self):
input_arn = "arn:aws:iam:eu-west-1:111111111111:user/prowler"
with raises(AWSIAMRoleARNRegionNotEmtpy) as error:
with raises(AWSIAMRoleARNRegionNotEmtpyError) as error:
parse_iam_credentials_arn(input_arn)
assert error._excinfo[0] == AWSIAMRoleARNRegionNotEmtpy
assert error._excinfo[0] == AWSIAMRoleARNRegionNotEmtpyError
def test_iam_credentials_arn_parsing_raising_AWSIAMRoleARNPartitionEmpty(self):
input_arn = "arn::iam::111111111111:user/prowler"
with raises(AWSIAMRoleARNPartitionEmpty) as error:
with raises(AWSIAMRoleARNPartitionEmptyError) as error:
parse_iam_credentials_arn(input_arn)
assert error._excinfo[0] == AWSIAMRoleARNPartitionEmpty
assert error._excinfo[0] == AWSIAMRoleARNPartitionEmptyError
def test_iam_credentials_arn_parsing_raising_AWSIAMRoleARNServiceNotIAMnorSTS(self):
input_arn = "arn:aws:s3::111111111111:user/prowler"
with raises(AWSIAMRoleARNServiceNotIAMnorSTS) as error:
with raises(AWSIAMRoleARNServiceNotIAMnorSTSError) as error:
parse_iam_credentials_arn(input_arn)
assert error._excinfo[0] == AWSIAMRoleARNServiceNotIAMnorSTS
assert error._excinfo[0] == AWSIAMRoleARNServiceNotIAMnorSTSError
def test_iam_credentials_arn_parsing_raising_AWSIAMRoleARNInvalidAccountID(self):
input_arn = "arn:aws:iam::AWS_ACCOUNT_ID:user/prowler"
with raises(AWSIAMRoleARNInvalidAccountID) as error:
with raises(AWSIAMRoleARNInvalidAccountIDError) as error:
parse_iam_credentials_arn(input_arn)
assert error._excinfo[0] == AWSIAMRoleARNInvalidAccountID
assert error._excinfo[0] == AWSIAMRoleARNInvalidAccountIDError
def test_iam_credentials_arn_parsing_raising_AWSIAMRoleARNInvalidResourceType(
self,
):
input_arn = "arn:aws:iam::111111111111:account/prowler"
with raises(AWSIAMRoleARNInvalidResourceType) as error:
with raises(AWSIAMRoleARNInvalidResourceTypeError) as error:
parse_iam_credentials_arn(input_arn)
assert error._excinfo[0] == AWSIAMRoleARNInvalidResourceType
assert error._excinfo[0] == AWSIAMRoleARNInvalidResourceTypeError
def test_iam_credentials_arn_parsing_raising_AWSIAMRoleARNEmptyResource(self):
input_arn = "arn:aws:iam::111111111111:role/"
with raises(AWSIAMRoleARNEmptyResource) as error:
with raises(AWSIAMRoleARNEmptyResourceError) as error:
parse_iam_credentials_arn(input_arn)
assert error._excinfo[0] == AWSIAMRoleARNEmptyResource
assert error._excinfo[0] == AWSIAMRoleARNEmptyResourceError
def test_is_valid_arn(self):
assert is_valid_arn("arn:aws:iam::012345678910:user/test")
+7 -9
View File
@@ -15,7 +15,7 @@ from prowler.providers.azure.azure_provider import AzureProvider
from prowler.providers.azure.exceptions.exceptions import (
AzureBrowserAuthNoTenantIDError,
AzureHTTPResponseError,
AzureInvalidAccountCredentialsError,
AzureInvalidProviderIdError,
AzureNoAuthenticationMethodError,
AzureTenantIDNoBrowserAuthError,
)
@@ -158,7 +158,7 @@ class TestAzureProvider:
assert exception.type == AzureBrowserAuthNoTenantIDError
assert (
exception.value.args[0]
== "[1918] Azure Tenant ID (--tenant-id) is required for browser authentication mode"
== "[2004] Azure Tenant ID (--tenant-id) is required for browser authentication mode"
)
def test_azure_provider_not_browser_auth_but_tenant_id(self):
@@ -197,7 +197,7 @@ class TestAzureProvider:
assert exception.type == AzureTenantIDNoBrowserAuthError
assert (
exception.value.args[0]
== "[1919] Azure Tenant ID (--tenant-id) is required for browser authentication mode"
== "[2005] Azure Tenant ID (--tenant-id) is required for browser authentication mode"
)
def test_test_connection_browser_auth(self):
@@ -370,9 +370,7 @@ class TestAzureProvider:
)
assert test_connection.error is not None
assert isinstance(
test_connection.error, AzureInvalidAccountCredentialsError
)
assert isinstance(test_connection.error, AzureInvalidProviderIdError)
assert (
"The provided credentials are not valid for the specified Azure subscription."
in test_connection.error.args[0]
@@ -390,7 +388,7 @@ class TestAzureProvider:
assert exception.type == AzureHTTPResponseError
assert (
exception.value.args[0]
== f"[1924] Error in HTTP response from Azure - Authentication failed: Unable to get authority configuration for https://login.microsoftonline.com/{tenant_id}. Authority would typically be in a format of https://login.microsoftonline.com/your_tenant or https://tenant_name.ciamlogin.com or https://tenant_name.b2clogin.com/tenant.onmicrosoft.com/policy. Also please double check your tenant name or GUID is correct."
== f"[2010] Error in HTTP response from Azure - Authentication failed: Unable to get authority configuration for https://login.microsoftonline.com/{tenant_id}. Authority would typically be in a format of https://login.microsoftonline.com/your_tenant or https://tenant_name.ciamlogin.com or https://tenant_name.b2clogin.com/tenant.onmicrosoft.com/policy. Also please double check your tenant name or GUID is correct."
)
def test_test_connection_without_any_method(self):
@@ -399,7 +397,7 @@ class TestAzureProvider:
assert exception.type == AzureNoAuthenticationMethodError
assert (
"[1917] Azure provider requires at least one authentication method set: [--az-cli-auth | --sp-env-auth | --browser-auth | --managed-identity-auth]"
"[2003] Azure provider requires at least one authentication method set: [--az-cli-auth | --sp-env-auth | --browser-auth | --managed-identity-auth]"
in exception.value.args[0]
)
@@ -424,7 +422,7 @@ class TestAzureProvider:
assert exception.type == AzureHTTPResponseError
assert (
exception.value.args[0]
== "[1924] Error in HTTP response from Azure - Simulated HttpResponseError"
== "[2010] Error in HTTP response from Azure - Simulated HttpResponseError"
)
def test_test_connection_with_exception(self):
+3 -3
View File
@@ -13,7 +13,7 @@ from prowler.config.config import (
)
from prowler.providers.common.models import Connection
from prowler.providers.gcp.exceptions.exceptions import (
GCPInvalidAccountCredentials,
GCPInvalidProviderIdError,
GCPTestConnectionError,
)
from prowler.providers.gcp.gcp_provider import GcpProvider
@@ -593,7 +593,7 @@ class TestGCPProvider:
"prowler.providers.gcp.gcp_provider.GcpProvider.validate_project_id"
) as mock_validate_project_id:
mock_validate_project_id.side_effect = GCPInvalidAccountCredentials(
mock_validate_project_id.side_effect = GCPInvalidProviderIdError(
"Invalid project ID"
)
@@ -605,4 +605,4 @@ class TestGCPProvider:
provider_id="test-invalid-project",
)
assert e.type == GCPInvalidAccountCredentials
assert e.type == GCPInvalidProviderIdError