From 64536b40f62e326412d953a06d7e7a5bef8f6874 Mon Sep 17 00:00:00 2001 From: Allan Eising Date: Sun, 18 May 2025 09:39:57 +0200 Subject: [PATCH] Create exception hierarchy --- .../src/sshecret_sshd/constants.py | 4 + .../src/sshecret_sshd/exceptions.py | 117 ++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 packages/sshecret-sshd/src/sshecret_sshd/exceptions.py diff --git a/packages/sshecret-sshd/src/sshecret_sshd/constants.py b/packages/sshecret-sshd/src/sshecret_sshd/constants.py index 97c0730..bcfac79 100644 --- a/packages/sshecret-sshd/src/sshecret_sshd/constants.py +++ b/packages/sshecret-sshd/src/sshecret_sshd/constants.py @@ -14,3 +14,7 @@ ERROR_INFO_USERNAME_GONE = "Unexpected error: Username lost in transit." ERROR_INFO_REMOTE_IP_GONE = ( "Unexpected error: Client connection details lost in transit." ) +ERROR_GENERIC_ERROR = "An unexpected error occured" +ERROR_UNAUTHORIZED = "Denied due to policy or configuration" + +ERROR_REGISTRATION_NOT_ALLOWED = "Received registration command from unauthorized source." diff --git a/packages/sshecret-sshd/src/sshecret_sshd/exceptions.py b/packages/sshecret-sshd/src/sshecret_sshd/exceptions.py new file mode 100644 index 0000000..174e5a5 --- /dev/null +++ b/packages/sshecret-sshd/src/sshecret_sshd/exceptions.py @@ -0,0 +1,117 @@ +"""Exceptions. + + +We define a hierarchy like this: + +- BaseSshecretSshError + - PolicyError + - CommandError +""" + +from sshecret_sshd import constants + + +class BaseSshecretSshError(Exception): + """Base exception class.""" + + default_message: str = constants.ERROR_GENERIC_ERROR + + def __init__(self, message: str | None = None) -> None: + """Init error class.""" + super().__init__(message or self.default_message) + + +class BackendError(BaseSshecretSshError): + """Error communicating with the backend.""" + + default_message: str = constants.ERROR_BACKEND_ERROR + + def __init__( + self, message: str | None = None, backend_error: str | None = None + ) -> None: + """Init error class.""" + + if not message: + message = self.default_message + if backend_error: + message += f" Upstream error: {backend_error}" + + super().__init__(message) + + +class PolicyError(BaseSshecretSshError): + """Error related to policy""" + + default_message: str = constants.ERROR_UNAUTHORIZED + + +class CommandError(BaseSshecretSshError): + """Errors related to commands.""" + + default_message: str = constants.ERROR_GENERIC_ERROR + + +class SecretNotFoundError(CommandError): + """Secret was not found.""" + + default_message: str = constants.ERROR_NO_SECRET_FOUND + + +class UnknownClientOrSecretError(CommandError): + """Client or secret was not found.""" + + default_message: str = constants.ERROR_UNKNOWN_CLIENT_OR_SECRET + + +class NoCommandReceivedError(CommandError): + """Client or secret was not found.""" + + default_message: str = constants.ERROR_NO_COMMAND_RECEIVED + + +class NoPublicKeyError(PolicyError): + """No public key received.""" + + default_message: str = constants.ERROR_NO_PUBLIC_KEY + + +class InvalidPublicKeyType(PolicyError): + """Type of public key is not correct.""" + + default_message: str = constants.ERROR_INVALID_KEY_TYPE + + +class UnknownCommandError(CommandError): + """Unknown command received.""" + + default_message: str = constants.ERROR_UNKNOWN_COMMAND + + +class ProcessError(BaseSshecretSshError): + """Process related errors.""" + + default_message: str = constants.ERROR_GENERIC_ERROR + + +class NoBackendError(ProcessError): + """Error related to backend object resolution.""" + + default_message: str = constants.ERROR_INFO_BACKEND_GONE + + +class NoUsernameError(ProcessError): + """Error related to username resolution.""" + + default_message: str = constants.ERROR_INFO_USERNAME_GONE + + +class NoRemoteIpError(ProcessError): + """Error related to remote_ip resolution.""" + + default_message: str = constants.ERROR_INFO_REMOTE_IP_GONE + + +class NoClientError(ProcessError): + """Error related to client resolution.""" + + default_message: str = constants.ERROR_UNKNOWN_CLIENT_OR_SECRET