Skip to content

Commit

Permalink
Added possibility to set client secret and id at both runtime and in …
Browse files Browse the repository at this point in the history
…config
  • Loading branch information
Rasmus Oscar Welander committed Sep 3, 2024
1 parent fd102d2 commit 5b4613d
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 24 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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("<your_client_id_here>")
# Set client secret (can also be set in config)
auth.set_client_secret("<your_client_secret_here>")
# Checks if token is expired if not return ('x-access-token', <token>)
Expand Down
32 changes: 23 additions & 9 deletions cs3client/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]:
Expand All @@ -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")
Expand Down
9 changes: 9 additions & 0 deletions cs3client/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
"""
Expand Down
26 changes: 13 additions & 13 deletions cs3client/statuscodehandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 2 additions & 0 deletions examples/app_api_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("<your_client_id_here>")
# Set client secret (can also be set in config)
auth.set_client_secret("<your_client_secret_here>")
# Checks if token is expired if not return ('x-access-token', <token>)
Expand Down
2 changes: 2 additions & 0 deletions examples/auth_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("<your_client_id_here>")
# Set client secret (can also be set in config)
auth.set_client_secret("<your_client_secret_here>")
# Checks if token is expired if not return ('x-access-token', <token>)
Expand Down
2 changes: 2 additions & 0 deletions examples/checkpoints_api_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("<your_client_id_here>")
# Set client secret (can also be set in config)
auth.set_client_secret("<your_client_secret_here>")
# Checks if token is expired if not return ('x-access-token', <token>)
Expand Down
2 changes: 2 additions & 0 deletions examples/default.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions examples/file_api_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("<your_client_id_here>")
# Set client secret (can also be set in config)
auth.set_client_secret("<your_client_secret_here>")
# Checks if token is expired if not return ('x-access-token', <token>)
Expand Down
2 changes: 2 additions & 0 deletions examples/shares_api_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("<your_client_id_here>")
# Set client secret (can also be set in config)
auth.set_client_secret("<your_client_secret_here>")
# Checks if token is expired if not return ('x-access-token', <token>)
Expand Down
2 changes: 2 additions & 0 deletions examples/user_api_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -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("<your_client_id_here>")
# Set client secret (can also be set in config)
auth.set_client_secret("<your_client_secret_here>")
# Checks if token is expired if not return ('x-access-token', <token>)
Expand Down

0 comments on commit 5b4613d

Please sign in to comment.