Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactor a bunch of auth-related python [MLG-215] [MLG-1321] #8347

Merged
merged 1 commit into from
Feb 21, 2024

Conversation

rb-determined-ai
Copy link
Member

@rb-determined-ai rb-determined-ai commented Nov 6, 2023

  • Remove the Authentication object.

    Authentication was both a dataclass containing username and token, as
    well as a complex login function disguised as an init.

    Now the dataclass is called UsernameTokenPair and the complex login
    function is called login() or login_with_cache().

  • Make Session the core of API calls, not the api.request() function.

    The Session has a cache of authentication information and cert
    customization, and is easy to reuse. The api.request() function
    encourages the use of singletons and creates really confusing
    configure-singleton-in-every-entrypoint behaviors.

  • Introduce an UnauthSession which doesn't have an authentication token,
    for those few calls that we need to make which are not authenticated.

  • Add a detproc helper module to the e2e tests, so even tests requiring
    the cli can be based on explicit sessions.

  • Remove cli_auth and cli_cert singletons.

  • Delete all singleton-based @authentication.required decorators from
    the cli; just create a session instead.

  • Remove all api.{get,post,whatever} calls.

  • Refactor the Profiler a bit to accept a Session object. It used to
    depend on the cli_auth as well.

  • Add some Session helpers to the e2e tests, with much better caching.

  • Redesign the e2e auth to be Session-centric rather than cached-login
    centric, in particular:

    • redesign api_utils.create_test_user()
    • remove test_users.logged_in_user()
    • remove test_users.log_in_cli()
    • remove test_users.login_admin()
    • replace any call to Determined() with Determined._from_session()
  • Introduce detproc module in e2e tests for session-centric CLI calls,
    replacing various adhoc helpers:

    • test_user.det_spawn()
    • test_user.det_run()
    • test_exp_continue.det_cmd()
    • test_groups.det_cmd()
    • test_groups.det_cmd_json()
    • test_groupsdet_cmd_expect_error()

Copy link

netlify bot commented Nov 6, 2023

Deploy Preview for determined-ui canceled.

Name Link
🔨 Latest commit 1eef9fe
🔍 Latest deploy log https://app.netlify.com/sites/determined-ui/deploys/65d54a60b7acb0000879b88d

@rb-determined-ai rb-determined-ai force-pushed the rb/boil-oceans branch 3 times, most recently from aeec327 to f404228 Compare November 9, 2023 17:30
session = api.Session(
info.master_url, None, None, cert, max_retries=util.get_max_retries_config()
)
utp = authentication.login_with_cache(info.master_url, cert=cert)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good. The magic is more explicit after this change. I think it's a good sign for the login part of your patch.

It'd be nice it could be done away with entirely, but that's outside the scope of this refactor.

Also note here that Session is a natural choice in this context for a login to return.

token_store.set_token(username, token)
token_store.set_active(username)
token_store = authentication.TokenStore(args.master)
utp = authentication.login(args.master, username, password, cli.cert)
Copy link
Contributor

@wes-turner wes-turner Feb 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not your bug (exists both before this PR and after), but I just noticed that if you aren't logged in and you try to log in with a bad password you get

Failed to log in user: Unauthenticated: Please use 'det user login <username>' for password login, or for Enterprise users logging in with an SSO provider, use 'det auth login --provider=<provider>'.

Just in case you're interested in fixing it here.

Internet says:

Response to the User: A 401 error urges the user to log in or provide valid credentials. In contrast, a 403 error informs the user that access is forbidden, regardless of their authentication status.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not interested in fixing it here, sorry.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rb-determined-ai rb-determined-ai force-pushed the rb/boil-oceans branch 2 times, most recently from 289a04e to 334ae52 Compare February 16, 2024 23:42
retry = api.default_retry()

return api.Session(master_url, args.user, authentication.cli_auth, cert, retry)
utp = authentication.login_with_cache(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like how this refactor has landed for the CLI. I'm not asking for anything from this PR, in this comment.

I think this is a place where this refactor is a potential stepping-stone to a later state where we've set up a login path that is only for this particular use case. Curious if you think the same and can express it in a sentence or two for the wiki.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand what you mean

resp = bindings.get_GetMaster(setup_session(args))
if not resp.to_json().get("rbacEnabled"):
resp = bindings.get_GetMaster(unauth_session(args))
if not resp.rbacEnabled:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't tell if you wanted feature_flag to be a parameter or if you wanted it rbacEnabled only.

Copy link
Member Author

@rb-determined-ai rb-determined-ai Feb 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pre-existing bug

(I only changed the code from weirdly switching from strongly typed bindings objects to weakly typed json dicts)

from determined.cli import render
from determined.common import api
from determined.common.declarative_argparse import Cmd


def get_version(host: str) -> Dict[str, Any]:
client_info = {"version": determined.__version__}
def get_version(sess: api.BaseSession, host: str) -> Dict[str, Any]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think including host might be an unnecessary footgun.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, this is a carryover from when I had Session leaving certain of its attributes as private. It doesn't really make sense anymore.

Fixed.

@rb-determined-ai rb-determined-ai force-pushed the rb/boil-oceans branch 2 times, most recently from 42a02fc to 9a867e9 Compare February 21, 2024 00:41
- Remove the Authentication object.

  Authentication was both a dataclass containing username and token, as
  well as a complex login function disguised as an __init__.

  Now the dataclass is called UsernameTokenPair and the complex login
  function is called `login()` or `login_with_cache()`.

- Make Session the core of API calls, not the api.request() function.

  The Session has a cache of authentication information and cert
  customization, and is easy to reuse.  The api.request() function
  encourages the use of singletons and creates really confusing
  configure-singleton-in-every-entrypoint behaviors.

- Introduce an UnauthSession which doesn't have an authentication token,
  for those few calls that we need to make which are not authenticated.

- Add a detproc helper module to the e2e tests, so even tests requiring
  the cli can be based on explicit sessions.

- Remove cli_auth and cli_cert singletons.

- Delete all singleton-based @authentication.required decorators from
  the cli; just create a session instead.

- Remove all api.{get,post,whatever} calls.

- Refactor the Profiler a bit to accept a Session object.  It used to
  depend on the cli_auth as well.

- Add some Session helpers to the e2e tests, with much better caching.

- Redesign the e2e auth to be Session-centric rather than cached-login
  centric, in particular:
    - redesign api_utils.create_test_user()
    - remove test_users.logged_in_user()
    - remove test_users.log_in_cli()
    - remove test_users.login_admin()
    - replace any call to Determined() with Determined._from_session()

- Introduce detproc module in e2e tests for session-centric CLI calls,
  replacing various adhoc helpers:
    - test_user.det_spawn()
    - test_user.det_run()
    - test_exp_continue.det_cmd()
    - test_groups.det_cmd()
    - test_groups.det_cmd_json()
    - test_groups.det_cmd_expect_error()

BREAKING CHANGE: This refactor removes the Session object from all
public API namespaces, and also adds the new requirement that all tasks
have a writable HOME directory.  Previously, a small subset of
functionality existed for tasks which had no writable HOME directory.
Copy link
Member

@dannysauer dannysauer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@rb-determined-ai rb-determined-ai merged commit 76ec233 into main Feb 21, 2024
102 of 103 checks passed
@rb-determined-ai rb-determined-ai deleted the rb/boil-oceans branch February 21, 2024 03:37
maxrussell pushed a commit that referenced this pull request Mar 21, 2024
- Remove the Authentication object.

  Authentication was both a dataclass containing username and token, as
  well as a complex login function disguised as an __init__.

  Now the dataclass is called UsernameTokenPair and the complex login
  function is called `login()` or `login_with_cache()`.

- Make Session the core of API calls, not the api.request() function.

  The Session has a cache of authentication information and cert
  customization, and is easy to reuse.  The api.request() function
  encourages the use of singletons and creates really confusing
  configure-singleton-in-every-entrypoint behaviors.

- Introduce an UnauthSession which doesn't have an authentication token,
  for those few calls that we need to make which are not authenticated.

- Add a detproc helper module to the e2e tests, so even tests requiring
  the cli can be based on explicit sessions.

- Remove cli_auth and cli_cert singletons.

- Delete all singleton-based @authentication.required decorators from
  the cli; just create a session instead.

- Remove all api.{get,post,whatever} calls.

- Refactor the Profiler a bit to accept a Session object.  It used to
  depend on the cli_auth as well.

- Add some Session helpers to the e2e tests, with much better caching.

- Redesign the e2e auth to be Session-centric rather than cached-login
  centric, in particular:
    - redesign api_utils.create_test_user()
    - remove test_users.logged_in_user()
    - remove test_users.log_in_cli()
    - remove test_users.login_admin()
    - replace any call to Determined() with Determined._from_session()

- Introduce detproc module in e2e tests for session-centric CLI calls,
  replacing various adhoc helpers:
    - test_user.det_spawn()
    - test_user.det_run()
    - test_exp_continue.det_cmd()
    - test_groups.det_cmd()
    - test_groups.det_cmd_json()
    - test_groups.det_cmd_expect_error()

BREAKING CHANGE: This refactor removes the Session object from all
public API namespaces, and also adds the new requirement that all tasks
have a writable HOME directory.  Previously, a small subset of
functionality existed for tasks which had no writable HOME directory.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla-signed documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants