"""Security and user identity utilities for Arkouda clients.The `arkouda.security` module provides functionality for managing access credentials,user identity, and secure client-side metadata used in communicating with the Arkouda server.Features--------- Platform-independent retrieval of the current user’s username and home directory.- Creation and management of a `.arkouda` directory for client-specific data.- Secure generation of authentication tokens using Python’s `secrets` module.- Serialization of user credentials for use with token-based server authentication.Functions---------generate_token(length=32) Generate a secure hexadecimal token using `secrets.token_hex`.generate_username_token_json(token) Return a JSON-formatted string containing both the current user's username and a token.get_home_directory() Return the user's home directory in a cross-platform manner.get_arkouda_client_directory() Get or create the `.arkouda` directory where client configuration and credentials are stored.get_username() Determine the system username based on the user's home directory path.Notes------ The `.arkouda` directory can be overridden using the `ARKOUDA_CLIENT_DIRECTORY` environment variable.- This module supports Linux, macOS (Darwin), and Windows platforms.- Token storage conventions in this module differ from the Arkouda server’s expectations /and must not be confused.Examples-------->>> from arkouda.security import generate_token, get_username, generate_username_token_json>>> token = generate_token()>>> print(token) # doctest: +SKIP'8f3a52e1b75f44d1a3a57a869488b637'>>> user = get_username()>>> print(user) # doctest: +SKIP'emma'>>> generate_username_token_json(token) # doctest: +SKIP'{"username": "emma", "token": "8f3a52e1b75f44d1a3a57a869488b637"}'"""importjsonimportosimportplatformimportsecretsfromcollectionsimportdefaultdictfromos.pathimportexpanduserfrompathlibimportPathfromtypeguardimporttypecheckedfromarkouda.pandasimportio_util__all__=["generate_token","generate_username_token_json","get_arkouda_client_directory","get_home_directory","get_username",]username_tokenizer=defaultdict(lambdax:x.split("/"))# type:ignoreusername_tokenizer["Windows"]=lambdax:x.split("\\")username_tokenizer["Linux"]=lambdax:x.split("/")username_tokenizer["Darwin"]=lambdax:x.split("/")
[docs]@typecheckeddefgenerate_token(length:int=32)->str:""" Use the secrets.token_hex() method to generate a hexidecimal token. Parameters ---------- length : int The desired length of token Returns ------- str The hexidecimal string generated by Python Notes ----- This method uses the Python secrets.token_hex method """returnsecrets.token_hex(length//2)
[docs]defget_home_directory()->str:""" Find a path to the current user's home directory in a platform-independent manner. Returns ------- str The user's home directory path Notes ----- This method uses the Python os.path.expanduser method to retrieve the user's home directory """returnexpanduser("~")
[docs]defget_arkouda_client_directory()->Path:""" Find a path to the current user's .arkouda directory. Artifacts such as server access tokens are stored in a platform-independent manner in the .arkouda directory. Returns ------- Path Path corresponding to the user's .arkouda directory path Notes ----- The default implementation is to place the .arkouda directory in the current user's home directory. The default can be overridden by setting the ARKOUDA_CLIENT_DIRECTORY environment variable. It is important this is not the same location as the server's token directory as the file format is different. """arkouda_parent_dir=os.getenv("ARKOUDA_CLIENT_DIRECTORY")ifnotarkouda_parent_dir:arkouda_parent_dir=get_home_directory()returnio_util.get_directory("{}{}.arkouda".format(arkouda_parent_dir,os.sep)).absolute()
[docs]defget_username()->str:""" Retrieve the current user's username for the host system in a platform-independent manner. Returns ------- str The username in the form of string Raises ------ EnvironmentError Raised if the host OS is unsupported Notes ----- The currently supported operating systems are Windows, Linux, and MacOS AKA Darwin """try:u_tokens=username_tokenizer[platform.system()](get_home_directory())exceptKeyErroraske:raiseEnvironmentError(f"Unsupported OS: {ke}")returnu_tokens[-1]
[docs]@typecheckeddefgenerate_username_token_json(token:str)->str:""" Generate a JSON object encapsulating the user's username and token. These credentials are for connecting to an arkouda server with basic authentication enabled. Parameters ---------- token : string The token to be used to access arkouda server Returns ------- str The JSON-formatted string encapsulating username and token """returnjson.dumps({"username":get_username(),"token":token})