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

feat: SSO Improvement - alter user_sessions table to include access token, implement CRUD ops, GET, POST, PATCH APIs and CLIs #9867

Open
wants to merge 40 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
75fbfda
create table and crud ops
ShreyaLnuHpe Aug 26, 2024
fee92d7
add crud ops in go
ShreyaLnuHpe Aug 28, 2024
5eaa712
integ test wip
ShreyaLnuHpe Aug 28, 2024
0e78f52
integ testing
ShreyaLnuHpe Aug 28, 2024
a93a64a
based on comments
ShreyaLnuHpe Aug 28, 2024
4a85904
API structure
ShreyaLnuHpe Aug 29, 2024
a8031a3
lint go corrections
ShreyaLnuHpe Aug 30, 2024
a8a5ea9
typo
ShreyaLnuHpe Aug 30, 2024
1f689b1
lint check
ShreyaLnuHpe Aug 30, 2024
33c874f
changes per swagger
ShreyaLnuHpe Aug 30, 2024
99b79cf
lint proto
ShreyaLnuHpe Aug 30, 2024
10e2648
add admin nonadmin user auth
ShreyaLnuHpe Aug 31, 2024
feb7d09
add E2E test for POST API
ShreyaLnuHpe Sep 4, 2024
c9ea59b
add GET CRUD ops
ShreyaLnuHpe Sep 4, 2024
293a21d
add GET API structure
ShreyaLnuHpe Sep 4, 2024
a139398
add test-intg for GET API
ShreyaLnuHpe Sep 4, 2024
bc3b7d9
based on comments
ShreyaLnuHpe Sep 6, 2024
cd7dbeb
DELETE API and tests
ShreyaLnuHpe Sep 6, 2024
2c50362
based on brainstoring and building op1
ShreyaLnuHpe Sep 10, 2024
607f0e4
remove llt table
ShreyaLnuHpe Sep 10, 2024
d432aa0
mased on comments
ShreyaLnuHpe Sep 12, 2024
736a9f5
add CLIs
ShreyaLnuHpe Sep 16, 2024
6000477
chore: add revoke token permission
corban-beaird Sep 16, 2024
47d87af
chore: drop WorkspaceCreator from set of roles able to revoke tokens
corban-beaird Sep 16, 2024
7bae276
chore: add rbac token permissions
ShreyaLnuHpe Sep 17, 2024
c2427ba
chore: correct check errors & remove token filter from GetALL
ShreyaLnuHpe Sep 17, 2024
6d9c3ff
refactor: clean up migration for readability
corban-beaird Sep 17, 2024
825af40
Merge branch 'main' into shreya/createTable
ShreyaLnuHpe Sep 18, 2024
05e05a5
fix: lint errors
ShreyaLnuHpe Sep 18, 2024
152f3d3
feat: token description in CLI and authentication using token
corban-beaird Sep 18, 2024
13c4a57
chore: clean up linter issues
corban-beaird Sep 18, 2024
3515ffb
changes to revoke in postgres
ShreyaLnuHpe Sep 18, 2024
a28fbf7
feat: added API support for token description updates & unified revok…
corban-beaird Sep 18, 2024
4d9f9f8
chore: clean up logging
corban-beaird Sep 18, 2024
6f305b5
chore: update table, update cli, getAccessToken, getAllAccessTokens, …
ShreyaLnuHpe Sep 19, 2024
ef03c2a
chore: pretty print cli and unify post api and permissions
ShreyaLnuHpe Sep 19, 2024
c49657e
feat: describe cli to take multiple usernames
ShreyaLnuHpe Sep 20, 2024
c0262e6
fix: authentication of multi login, add tokenType while rendering
ShreyaLnuHpe Sep 24, 2024
f67cffe
fix: change name from long-lived to access token and RBAC access only…
ShreyaLnuHpe Sep 24, 2024
784e69d
chore: refactor Get and Create AccessToken API, add filter option, up…
ShreyaLnuHpe Oct 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 102 additions & 2 deletions harness/determined/cli/user.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import argparse
import collections
import getpass
from typing import Any, List
from typing import Any, Dict, List

from determined import cli
from determined.cli import errors, render
from determined.common import api
from determined.common import api, util
from determined.common.api import authentication, bindings
from determined.experimental import client

Expand Down Expand Up @@ -38,6 +38,18 @@
"agent_group",
],
)
UserSessionInfo = collections.namedtuple(
"UserSessionInfo",
[
"id",
"user_id",
"expiry",
"created_at",
"token_type",
"is_revoked",
"token_description",
],
)


def list_users(args: argparse.Namespace) -> None:
Expand Down Expand Up @@ -218,6 +230,65 @@ def edit(args: argparse.Namespace) -> None:
raise errors.CliError("No field provided. Use 'det user edit -h' for usage.")


def printData(data: Dict[str, Any], args: argparse.Namespace) -> None:
if args.yaml:
print(util.yaml_safe_dump(data, default_flow_style=False))
else:
render.print_json(data)


def describe_token(args: argparse.Namespace) -> None:
sess = cli.setup_session(args)

if args.username is None:
respFromLongLiveToken = bindings.get_GetLongLivedToken(sess)
printData(respFromLongLiveToken.to_json(), args)
else:
userID = bindings.get_GetUserByUsername(session=sess, username=args.username).user.id
if userID is not None:
respFromUserLongLiveToken = bindings.get_GetUserLongLivedToken(
session=sess, userId=userID
)
printData(respFromUserLongLiveToken.to_json(), args)


def list_tokens(args: argparse.Namespace) -> None:
sess = cli.setup_session(args)
d = client.Determined._from_session(sess)
userSessions_list = d.list_tokens(isRevoked=None if args.all else False)
renderer = UserSessionInfo # type: Any
render.render_objects(renderer, userSessions_list)


def revoke_token(args: argparse.Namespace) -> None:
sess = cli.setup_session(args)
bindings.delete_DeleteLongLivedTokenByTokenID(sess, tokenId=args.tokenId)


def create_token(args: argparse.Namespace) -> None:
sess = cli.setup_session(args)
# TODO: API to update token description & CLI

if args.username is None:
contentForLongLivedToken = bindings.v1PostLongLivedTokenRequest(
lifespan=args.lifespan,
)
respFromLongLivedToken = bindings.post_PostLongLivedToken(
sess, body=contentForLongLivedToken
)
printData(respFromLongLivedToken.to_json(), args)
else:
userID = bindings.get_GetUserByUsername(session=sess, username=args.username).user.id
if userID is not None:
contentForUserLongLivedToken = bindings.v1PostUserLongLivedTokenRequest(
lifespan=args.lifespan, userId=userID
)
respFromUserLongLivedToken = bindings.post_PostUserLongLivedToken(
sess, body=contentForUserLongLivedToken, userId=userID
)
printData(respFromUserLongLivedToken.to_json(), args)


AGENT_USER_GROUP_ARGS = [
cli.Arg("--agent-uid", type=int, help="UID on the agent to run tasks as"),
cli.Arg("--agent-user", help="user on the agent to run tasks as"),
Expand Down Expand Up @@ -313,6 +384,35 @@ def edit(args: argparse.Namespace) -> None:
help="grant/remove user admin permissions",
),
]),
cli.Cmd("token", None, "manage long lived access tokens", [
cli.Cmd("describe", describe_token, "describe token info", [
cli.Arg("--username", nargs="?", default=None,
help="name of user to describe token"),
cli.Group(
cli.output_format_args["json"],
cli.output_format_args["yaml"],
Copy link
Contributor

Choose a reason for hiding this comment

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

i'm not sure we need YAML here or in the other commands. YAMLs are largely for configs, and i can't imagine why you'd want to parse a YAML if you're using this as part of an automated workflow.

),
]),
cli.Cmd("list ls", list_tokens, "list all active access tokens", [
cli.Arg("--all", "-a", action="store_true", default=None,
help="list all access tokens, including revoked & expired tokens"),
cli.Group(
cli.output_format_args["json"],
),
]),
cli.Cmd("revoke", revoke_token, "revoke token", [
cli.Arg("tokenId", help="revoke given access token"),
]),
cli.Cmd("create", create_token, "create token", [
Copy link
Contributor

@azhou-determined azhou-determined Sep 25, 2024

Choose a reason for hiding this comment

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

copying my comment from JIRA, but open to other thoughts:


det user create-token <username> --expiration-days (-e) <int> --description (-d) <string> --output-file (-o) <filepath>

where if isn’t specified, we’ll default to current user (#1). if it is, create token for specified user (#2).

  • prefer explicit duration to avoid confusion about what parameters are allowed. since token expirations are commonly in days, let’s just call it what it is.

  • “output” is a commonly-recognized name for where a command output is to be saved, --output-file makes it super clear what the command expects from this argument.

cli.Arg("--username", type=str, help="name of user to create token"),
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be a positional arg, like other commands here

cli.Arg("--lifespan", type=str, help="give expiry lifespan"),
cli.Arg("--description", type=str, help="description of new token"), # TODO
cli.Group(
cli.output_format_args["json"],
cli.output_format_args["yaml"],
),
]),
]),
])
] # type: List[Any]

Expand Down
Loading
Loading