From 68475fe015e1faae45bba79e5628eca5375e42d0 Mon Sep 17 00:00:00 2001 From: RubenCGomes Date: Mon, 30 Dec 2024 01:00:26 +0000 Subject: [PATCH] most commands added (doc commands still missing) --- delivery3/features.adoc | 145 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 7 deletions(-) diff --git a/delivery3/features.adoc b/delivery3/features.adoc index 6072315..b0c8d31 100644 --- a/delivery3/features.adoc +++ b/delivery3/features.adoc @@ -224,19 +224,22 @@ a| * `Authorization: token` For the client, each command is executed via terminal and it is used multiple tools with specific functionalities: -* Argparse footnote:[https://docs.python.org/3/library/argparse.html] → Check for errors in arguments given by the user. -* Logging footnote:[https://docs.python.org/3/library/logging.html] → Logging system to send out messages such as errors. -* OS footnote:[https://docs.python.org/3/library/os.html] → Add path to local folder `~/.sio` to save or load any files used by the current command. -* Requests footnote:[https://requests.readthedocs.io/en/latest/] → Main library to allow communication from the client to the API. +* `argparse` footnote:[https://docs.python.org/3/library/argparse.html] → Check for errors in arguments given by the user. +* `logging` footnote:[https://docs.python.org/3/library/logging.html] → Logging system to send out messages such as errors. +* `os` footnote:[https://docs.python.org/3/library/os.html] → Add path to local folder `~/.sio` to save or load any files used by the current command. +* `requests` footnote:[https://requests.readthedocs.io/en/latest/] → Main library to allow communication from the client to the API. For every command the argument `-r` is present to set the API's address. It is needed to define if it wasn't previously, otherwise an error is cast with the corresponding message. + +==== Generating the Subject's Credentials To use the API, it is first needed to create a public key to create an organization with the key. -The command `rep_subject_credentials` it is generated a keypair using RSA with a given password and both public and private keys are saved in different files. +The command `rep_subject_credentials` generates a key-pair using RSA with a given password and saves both public and private keys different files under the folder mentioned before. + ==== Creating an Organization +The command `rep_create_org` creates an organization. In order to do that, the client must give the file containing his public key in order to create a session afterwards. -The command `rep_create_org` creates an organization and for it the client must give the file containing his public key in order to create a session afterwards. ==== Creating a session For the client to use the Authenticated API, the command `rep_create_session` allows the user to create a session and assume an identity. This command also protects information that shouldn't be visible to outsiders when it's being transfered between the client and the server. @@ -245,13 +248,141 @@ To protect the information, the client and the server initiate a Diffie-Hellman [source, python] ---- +# generate the parameters and the key pair generator = 2; key_size = 1024 parameters = generate_parameters(generator, key_size) private_key, public_key = generate_key_pair(parameters) -response = req.json() +# send the parameters and the public key to the server +req = requests.post('json with parameters and public key...') + +# receive the server's public key +response = req.get('json with server public key...') server_public_key = serialization.load_pem_public_key(bytes.fromhex(response['public_key'])) + +# obtain the derived key derived_key = derive_keys(private_key, server_public_key) ---- If the exchange is succesful, the client will attempt to login using it's private key that should be given when executing this command. + + +==== Listing Organizations +The command `rep_list_org` lists all organizations present in the server. Since it requires no authentication, it is a simple command that sends a GET request to the API and prints the response. + +However, it is important to note that the response is encrypted and must be decrypted before being printed. In order to achieve this, the client uses a symmetric encryption algorithm that uses a Initialization Vector (IV) to decrypt the response. This is done by the function `decrypt_request_with_iv` that receives the encrypted response, where it separates the IV from the encrypted text (first 16 bytes being the IV) and returns the decrypted response. + +[source, python] +---- +def decrypt_request_with_iv(response): + iv = response[:16] + cipher = response[16:] + + # decrypt the response (simplified) + plaintext = decrypt(cipher, iv) + + # need to decode the bytes to string + return plaintext.decode() +---- + +It could be argued that if a user is authenticated, the response could be encrypted/decrypted using the derived key from the Diffie-Hellman key exchange, but since the information is publicly available, it's not really needed. + + +==== Listing Users of an Organization +The command `rep_list_users` lists all users of an organization. It requires the user to be authenticated and the response is encrypted with the derived key from the Diffie-Hellman key exchange. Optionally, the user can query for a specific user by providing the username as an argument. + +First, the API checks if the user is authenticated (has a session file) and the username was given as an argument. Then, it sends a `GET` request to the server. The data of the request is encrypted with the derived key, created with the initialization of the session. + +Finally, if the request was successful, the data is decrypted and printed to the screen. + + +==== Assuming a role +With the command `rep_assume_role`, the user can assume a role in the session. This command requires the user to be authenticated and the role to be assumed. The role is sent to the server in a `POST` request, where the role name is used as a parameter in the URL. This way, there is no need to send anything in the body of the request, therefore there is no need to encrypt the data. The server will check if the user has the permission to assume the role and if the role exists. + +If everything is correct, the server will return a 200 status code, otherwise it will return an error message. The API will print the message to the screen and exit with the corresponding status code. + + +==== Adding a role to the organization +The command `rep_add_role` allows the user to add a role to the organization. This command requires the user to be authenticated and the role to be added. The role is sent to the server in a `POST` request, where the role name is sent in the body of the request. The data is encrypted with the derived key from the Diffie-Hellman key exchange. + +If the request is successful, the server will return a 201 status code, otherwise it will return an error message. The API will print the message to the screen and exit with the corresponding status code, as per usual. + + +==== Adding permissions/user to a role +Given a role name and a valid permission/username, the `rep_add_permission` command allows a user to add certain permissions to a specific role in a organization (if the user has permissions to do that) or a username to that role. + +First, since there's only some permissions, it's checked if it corresponds to one of them and if not, it assumes it's a username. + +It then sends a `POST` request to the server, with the role and permission/username on the URL. With this of course, there is no need for encryption. It also sends the session token (which could be encrypted as mentioned in the analysis) in the header. + +Like the other commands, if the request is successful, the server will return a 201 status code, otherwise it will return an error message. The API will print the message to the screen and exit with the corresponding status code. + + +==== Removing a permission/user from a role +Similar to the previous command, the `rep_remove_permission` command allows a user to remove certain permissions from a specific role in a organization (if the user has permissions to do that) or a username from that role. + +It follows the same steps as the `rep_add_permission` command, but instead of adding, it removes the permission/username from the role. + + +==== Suspending a role +The command `rep_suspend_role` allows the user to suspend a role in the organization. This command requires the user to be authenticated and the role to be suspended. The role is sent to the server in a `POST` request, where the role name is used as a parameter in the URL. This way, there is no need to send anything in the body of the request, therefore there is no need to encrypt the data. The server will check if the user has the permission to suspend the role. + +The session token is also sent in the header, so that the server knows who is attempting to access the endpoint. + +An error can occur if the role provided oes not exist (since the endpoint doesn't exist, it will return a "Failed to obtain response from server." error). + +If everything is correct, the server will return a 200 status code, otherwise it will return an error message. The API will print the message to the screen and exit with the corresponding status code. + + +==== Reactivating a role +The command `rep_reactivate_role` allows the user to reactivate a role in the organization. This command requires the user to be authenticated and the role to be reactivated. The role is sent to the server in a `POST` request, where the role name is used as a parameter in the URL. This way, there is no need to send anything in the body of the request, therefore there is no need to encrypt the data. The server will also check if the user has the permission to reactivate the role. + +This command is similar to `rep_suspend_role`, but instead of suspending a role, it reactivates a suspended role. + + +==== Dropping a role +This command (`rep_drop_role`) is, once again, similar to the previous commands in terms of how it works. The only difference being that it makes the current user drop the provided role. + + +==== Listing the existing roles +The command `rep_list_roles` requires a session token in order to function. Given that the token is present, it sends a simple `GET` request to the server, where it returns the existing roles in the current organization. + +The returning content is encrypted using the Diffie-Hellman derived key, calculated when the session was created. + +Like before, the roles are printed to the screen, and any errors would also be printed, with the corresponding exit codes properly returned. + + +==== Listing subjects with a role +The following command `rep_list_role_subjects` is similar to the previous command (`rep_list_roles`), except this command will return the subjects that have a specific role. This role is given as a argument and should be provided beforehand when executing the command. + + +==== Listing roles of a subject +This command (`rep_list_subject_roles`) is very similar to the `rep_list_role_subjects` command, but with one key difference. This command is meant to list the roles of a subject. The implementation of the command is, as mentioned before, similar to the role subjects command. + + +==== Listing a role's permissions +Another command with a similar implementation of the previous ones, the `rep_list_roles` returns a list of the permissions that someone with that role would have on the organization. + + +==== Listing roles with a permission +Once again, this command has a almost identical implementation of the previous commands, the command `rep_list_permission_roles` gives the user a list of roles that have a specific permission, given as a argument before calling said command. + + +==== Adding a subject to a organization +The command `rep_add_subject` aims to give the possibility of a user to be able to add another user to the current organization. This is, of course, a command that requires specific permissions in order to do this. + +First, it checks for the existente of a session file. Then, it sends a `POST` request to the server, with the informatio of the subject to be added. These include the `username`, `full_name`, `email` and `public_key`. This content is encrypted with the derived key from the Diffie-Hellman key exchange from the user that is executing the command. + +According to the success of the previous request, a message will be printed back to the user. + + +==== Suspending a subject +This command (`rep_suspend_subject`) allows for a user (authenticated and with the required permission) to suspend a subject from a organization. + +The username is parsed in the URL, and the session token is, as usual, sent in the header of the request. + + +==== Activating a subject +The following command `rep_activate_subject` has a similar implementation as the `rep_suspend_subject` command. The key difference is that instead of activating a subject, it suspends a subject. In order to activate a subject, the subject must be in a suspended state. + +