From 5b4613dc050b340d2ba71f7c4caca7772524498d Mon Sep 17 00:00:00 2001 From: Rasmus Oscar Welander Date: Fri, 30 Aug 2024 18:24:36 +0200 Subject: [PATCH] Added possibility to set client secret and id at both runtime and in config --- README.md | 8 ++++++-- cs3client/auth.py | 32 +++++++++++++++++++++-------- cs3client/config.py | 9 ++++++++ cs3client/statuscodehandler.py | 26 +++++++++++------------ examples/app_api_example.py | 2 ++ examples/auth_example.py | 2 ++ examples/checkpoints_api_example.py | 2 ++ examples/default.conf | 2 ++ examples/file_api_example.py | 2 ++ examples/shares_api_example.py | 2 ++ examples/user_api_example.py | 2 ++ 11 files changed, 65 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 3ca164a..ded609a 100644 --- a/README.md +++ b/README.md @@ -88,12 +88,14 @@ ssl_verify = False # Optional, defaults to an empty string ssl_client_cert = test_client_cert # Optional, defaults to an empty string -ssl_client_key = test_client_key +ssl_client_key = test_client_key # Optional, defaults to an empty string -ssl_ca_cert = test_ca_cert +ssl_ca_cert = test_ca_cert # Optinal, defaults to an empty string auth_client_id = einstein +# Optional (can also be set when instansiating the class) +auth_client_secret = relativity # Optional, defaults to basic auth_login_type = basic @@ -125,6 +127,8 @@ log = logging.getLogger(__name__) client = CS3Client(config, "cs3client", log) auth = Auth(client) +# Set the client id (can also be set in the config) +auth.set_client_id("") # Set client secret (can also be set in config) auth.set_client_secret("") # Checks if token is expired if not return ('x-access-token', ) diff --git a/cs3client/auth.py b/cs3client/auth.py index bb7087f..fed31fe 100644 --- a/cs3client/auth.py +++ b/cs3client/auth.py @@ -37,20 +37,31 @@ def __init__(self, cs3_client: CS3Client) -> None: self._gateway: GatewayAPIStub = cs3_client._gateway self._log: logging.Logger = cs3_client._log self._config: Config = cs3_client._config - # The user should be able to change the client secret (e.g. token) at runtime - self._client_secret: str | None = None + # The user should be able to change the client secret (e.g. token) and client id at runtime + self._client_secret: str | None = self._config.auth_client_secret + self._client_id: str | None = self._config.auth_client_id self._token: str | None = None def set_client_secret(self, token: str) -> None: """ Sets the client secret, exists so that the user can change the client secret (e.g. token, password) at runtime, - without having to create a new Auth object. NOTE that token OR the client secret has to be set when - instantiating the client object. + without having to create a new Auth object. Note client secret has to be set when + instantiating the client object or through the configuration. :param token: Auth token/password. """ self._client_secret = token + def set_client_id(self, id: str) -> None: + """ + Sets the client id, exists so that the user can change the client id at runtime, without having to create + a new Auth object. Settings this (either through config or here) is optional unless you are using + basic authentication. + + :param token: id. + """ + self._client_id = id + def get_token(self) -> tuple[str, str]: """ Attempts to get a valid authentication token. If the token is not valid, a new token is requested @@ -72,19 +83,22 @@ def get_token(self) -> tuple[str, str]: # Token has expired, obtain another one. req = AuthenticateRequest( type=self._config.auth_login_type, - client_id=self._config.auth_client_id, + client_id=self._client_id, client_secret=self._client_secret, ) # Send the authentication request to the CS3 Gateway res = self._gateway.Authenticate(req) if res.status.code != CODE_OK: - self._log.error(f"Failed to authenticate user {self._config.auth_client_id}, error: {res.status}") + self._log.error(f'msg="Failed to authenticate" ' + f'user="{self._client_id if self._client_id else "no_id_set"}" ' + f'error_code="{res.status}"') raise AuthenticationException( - f"Failed to authenticate user {self._config.auth_client_id}, error: {res.status}" + f'Failed to authenticate: user="{self._client_id if self._client_id else "no_id_set"}" ' + f'error_code="{res.status}"' ) self._token = res.token - self._log.debug(f'msg="Authenticated user" user="{self._config.auth_client_id}"') + self._log.debug(f'msg="Authenticated user" user="{self._client_id if self._client_id else "no_id_set"}"') return ("x-access-token", self._token) def list_auth_providers(self) -> list[str]: @@ -97,7 +111,7 @@ def list_auth_providers(self) -> list[str]: try: res = self._gateway.ListAuthProviders(request=ListAuthProvidersRequest()) if res.status.code != CODE_OK: - self._log.error(f"List auth providers request failed, error: {res.status}") + self._log.error(f'msg="List auth providers request failed" error_code="{res.status}"') raise Exception(res.status.message) except grpc.RpcError as e: self._log.error("List auth providers request failed") diff --git a/cs3client/config.py b/cs3client/config.py index 316b204..78ba99b 100644 --- a/cs3client/config.py +++ b/cs3client/config.py @@ -131,6 +131,15 @@ def auth_client_id(self) -> str: """ return self._config.get(self._config_category, "auth_client_id", fallback=None) + @property + def auth_client_secret(self) -> str: + """ + The auth_client_secret property returns the auth_client_secret value from the configuration, + + :return: auth_client_secret + """ + return self._config.get(self._config_category, "auth_client_secret", fallback=None) + @property def tus_enabled(self) -> bool: """ diff --git a/cs3client/statuscodehandler.py b/cs3client/statuscodehandler.py index 47b48a5..bed57f5 100644 --- a/cs3client/statuscodehandler.py +++ b/cs3client/statuscodehandler.py @@ -22,44 +22,44 @@ def __init__(self, log: logging.Logger, config: Config) -> None: def _log_not_found_info(self, status: cs3status.Status, operation: str, msg: str = None) -> None: self._log.info( - f'msg="Not found on {operation}" {msg + " " if msg else ""}' - f'userid="{self._config.auth_client_id}" trace="{status.trace}" ' - f'reason="{status.message.replace('"', "'")}"' + f'msg="Not found on {operation}" {msg + " " if msg else ""} ' + f'userid="{self._config.auth_client_id if self._config.auth_client_id else "no_id_set"}" ' + f'trace="{status.trace}" reason="{status.message.replace('"', "'")}"' ) def _log_authentication_error(self, status: cs3status.Status, operation: str, msg: str = None) -> None: self._log.error( f'msg="Authentication failed on {operation}" {msg + " " if msg else ""}' - f'userid="{self._config.auth_client_id}" trace="{status.trace}" ' - f'reason="{status.message.replace('"', "'")}"' + f'userid="{self._config.auth_client_id if self._config.auth_client_id else "no_id_set"}" ' + f'trace="{status.trace}" reason="{status.message.replace('"', "'")}"' ) def _log_unknown_error(self, status: cs3status.Status, operation: str, msg: str = None) -> None: self._log.error( f'msg="Failed to {operation}, unknown error" {msg + " " if msg else ""}' - f'userid="{self._config.auth_client_id}" trace="{status.trace}" ' - f'reason="{status.message.replace('"', "'")}"' + f'userid="{self._config.auth_client_id if self._config.auth_client_id else "no_id_set"}" ' + f'trace="{status.trace}" reason="{status.message.replace('"', "'")}"' ) def _log_precondition_info(self, status: cs3status.Status, operation: str, msg: str = None) -> None: self._log.info( f'msg="Failed precondition on {operation}" {msg + " " if msg else ""}' - f'userid="{self._config.auth_client_id}" trace="{status.trace}" ' - f'reason="{status.message.replace('"', "'")}"' + f'userid="{self._config.auth_client_id if self._config.auth_client_id else "no_id_set"}" ' + f'trace="{status.trace}" reason="{status.message.replace('"', "'")}"' ) def _log_already_exists(self, status: cs3status.Status, operation: str, msg: str = None) -> None: self._log.info( f'msg="Already exists on {operation}" {msg + " " if msg else ""}' - f'userid="{self._config.auth_client_id}" trace="{status.trace}" ' - f'reason="{status.message.replace('"', "'")}"' + f'userid="{self._config.auth_client_id if self._config.auth_client_id else "no_id_set"}" ' + f'trace="{status.trace}" reason="{status.message.replace('"', "'")}"' ) def _log_unimplemented(self, status: cs3status.Status, operation: str, msg: str = None) -> None: self._log.info( f'msg="Invoked {operation} on unimplemented feature" {msg + " " if msg else ""}' - f'userid="{self._config.auth_client_id}" trace="{status.trace}" ' - f'reason="{status.message.replace('"', "'")}"' + f'userid="{self._config.auth_client_id if self._config.auth_client_id else "no_id_set"}" ' + f'trace="{status.trace}" reason="{status.message.replace('"', "'")}"' ) def handle_errors(self, status: cs3status.Status, operation: str, msg: str = None) -> None: diff --git a/examples/app_api_example.py b/examples/app_api_example.py index 07d464a..f778d57 100644 --- a/examples/app_api_example.py +++ b/examples/app_api_example.py @@ -22,6 +22,8 @@ client = CS3Client(config, "cs3client", log) auth = Auth(client) +# Set the client id (can also be set in the config) +auth.set_client_id("") # Set client secret (can also be set in config) auth.set_client_secret("") # Checks if token is expired if not return ('x-access-token', ) diff --git a/examples/auth_example.py b/examples/auth_example.py index e9c3db3..926c5c2 100644 --- a/examples/auth_example.py +++ b/examples/auth_example.py @@ -21,6 +21,8 @@ client = CS3Client(config, "cs3client", log) auth = Auth(client) +# Set the client id (can also be set in the config) +auth.set_client_id("") # Set client secret (can also be set in config) auth.set_client_secret("") # Checks if token is expired if not return ('x-access-token', ) diff --git a/examples/checkpoints_api_example.py b/examples/checkpoints_api_example.py index f418cdb..efc21d5 100644 --- a/examples/checkpoints_api_example.py +++ b/examples/checkpoints_api_example.py @@ -22,6 +22,8 @@ client = CS3Client(config, "cs3client", log) auth = Auth(client) +# Set the client id (can also be set in the config) +auth.set_client_id("") # Set client secret (can also be set in config) auth.set_client_secret("") # Checks if token is expired if not return ('x-access-token', ) diff --git a/examples/default.conf b/examples/default.conf index e5be292..b8d0c68 100644 --- a/examples/default.conf +++ b/examples/default.conf @@ -33,6 +33,8 @@ ssl_ca_cert = test_ca_cert auth_client_id = einstein # Optional, defaults to basic auth_login_type = basic +# Optional (Can also be set after instantiating the Auth object) +auth_client_secret = relativity # For the future lock implementation diff --git a/examples/file_api_example.py b/examples/file_api_example.py index c19c4c0..2b6e1b4 100644 --- a/examples/file_api_example.py +++ b/examples/file_api_example.py @@ -29,6 +29,8 @@ client = CS3Client(config, "cs3client", log) auth = Auth(client) +# Set the client id (can also be set in the config) +auth.set_client_id("") # Set client secret (can also be set in config) auth.set_client_secret("") # Checks if token is expired if not return ('x-access-token', ) diff --git a/examples/shares_api_example.py b/examples/shares_api_example.py index 6ae256f..abbfa31 100644 --- a/examples/shares_api_example.py +++ b/examples/shares_api_example.py @@ -22,6 +22,8 @@ client = CS3Client(config, "cs3client", log) auth = Auth(client) +# Set the client id (can also be set in the config) +auth.set_client_id("") # Set client secret (can also be set in config) auth.set_client_secret("") # Checks if token is expired if not return ('x-access-token', ) diff --git a/examples/user_api_example.py b/examples/user_api_example.py index ed0decb..7fdc105 100644 --- a/examples/user_api_example.py +++ b/examples/user_api_example.py @@ -21,6 +21,8 @@ client = CS3Client(config, "cs3client", log) auth = Auth(client) +# Set the client id (can also be set in the config) +auth.set_client_id("") # Set client secret (can also be set in config) auth.set_client_secret("") # Checks if token is expired if not return ('x-access-token', )