Skip to content

Automatically Retry the CLI Command upon Session Unlocking #240

@CMCDragonkai

Description

@CMCDragonkai

Specification

MR: https://gitlab.com/MatrixAI/Engineering/Polykey/js-polykey/-/merge_requests/213

When a user executes a CLI command without having been authenticated previously the command sent to the agent will be rejected as "unauthorised". Instead of throwing an exception here, we can prompt the user for the root password in order to authenticate the client. Provided we know that the user is not a machine (which would classify as unattended usage), we can continue to prompt the user for the root password until the correct password is supplied and they can be authenticated. We will refer to this loop as the CLI Authentication Retry Loop (CARL):
CARL attended grpc call flow

Before we can activate the CARL and begin to prompt the user for the password, we need to ensure that the command is not unattended (since we need to account for both machine and human usage). We can do this by checking if either of the two environment variables PK_PASSWORD (for the root password) or PK_TOKEN (for the session token) are set (since the purpose of setting these is for unattended usage). Before we activate the CARL we also need to check that the first exception we receive back from the agent is ErrorClientAuthMissing (thrown when the call has no authorisation metadata), since we only want to retry the call if the client is not authenticated, rather than if the authentication metadata is invalid or if there is some other error on the agent side. Once we are inside the loop we only want to restart it if the error we receive back from the agent is ErrorClientAuthDenied (thrown when the authorisation metadata is invalid), since this means that the password supplied by the user was invalid and we want to prompt them to try again. The user can always manually exit the loop from the terminal if they have forgotten their password or otherwise wish to cancel the call.

Since we want this loop to be as automated as possible, prompting the user to enter their password should be our last option. As such, the retry function can be optionally called with an initial metadata object that is constructed during parsing of command line options for each call. This metadata is encoded using the first set value from the following in order:

  1. Password File (optional for every CLI call)
  2. PK_PASSWORD environment variable
  3. PK_TOKEN environment variable

In this way, if the password is already supplied it will be made use of. Once we enter the CARL we know that all other options have been exhausted and we have to prompt the user for the password.

Additional context

  • Previous @DrFacepalm had asked how this is supposed to be done in an efficient way. This should be done by separating the phases of the UI/UX loop above procedure functions, and then using a while loop to enable recursion. Note that we don't use function recursion in JavaScript runtimes due to the lack of tail-call optimisation in JS runtimes.

Tasks

  1. - Update the design of the sequence diagrams in the sessions reference article https://github.com/MatrixAI/js-polykey/wiki/Sessions to include the CLI command retry loop
  2. - Break up the loop into separate named phases, and create procedure functions for each phase in the CLI src/bin location
  3. - Add these tests to the tests/bin (these are singular tests, you can pick any CLI command for this):
    • Retry loop when the session token is missing, succeeds in unlocking, succeeds in retrying the call
    • Failure to unlock session when prompted
    • Failure to to do the repeated call because session token is invalid
    • Ensure that if password is supplied, and the token is missing, the root password can be substituted for the session token, and the token is established
  4. - Integrate functions into bin/utils and all relevant commands

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions