Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cloud = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

>>> musterr [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code --client-id custom-client-id
Error: device authorization: Client is not allowed to use device code login (error code: unauthorized_client)
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
sethome "./home"
export DATABRICKS_CLI_DEVICE_CODE=true

trace musterr $CLI auth login --host $DATABRICKS_HOST --profile test --use-device-code --client-id custom-client-id
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Ignore = [
"home"
]
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cloud = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

>>> musterr [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code
Error: device code login is not enabled for this workspace

>>> musterr [CLI] auth login --profile ws --use-device-code
Error: device code login is not enabled for this workspace
12 changes: 12 additions & 0 deletions acceptance/cmd/auth/login/use-device-code-not-enabled/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
sethome "./home"
export DATABRICKS_CLI_DEVICE_CODE=true

trace musterr $CLI auth login --host $DATABRICKS_HOST --profile test --use-device-code

# The check also applies to a host that comes from a profile.
cat > ./home/.databrickscfg << EOF
[ws]
host = $DATABRICKS_HOST
auth_type = databricks-cli
EOF
trace musterr $CLI auth login --profile ws --use-device-code
14 changes: 14 additions & 0 deletions acceptance/cmd/auth/login/use-device-code-not-enabled/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Ignore = [
"home"
]

# Workspaces that are not enrolled in the device code preview do not advertise
# a device_authorization_endpoint in their OIDC discovery document.
[[Server]]
Pattern = "GET /oidc/.well-known/oauth-authorization-server"
Response.Body = '''
{
"authorization_endpoint": "https://workspace.test/oidc/v1/authorize",
"token_endpoint": "https://workspace.test/oidc/v1/token"
}
'''
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cloud = false
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

>>> musterr [CLI] auth login --host [DATABRICKS_URL] --use-device-code
Error: --use-device-code is only supported for workspace hosts

>>> print_requests.py //oidc/v1/device/auth
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
sethome "./home"
export DATABRICKS_CLI_DEVICE_CODE=true

# An account-scoped discovery URL marks the host as a unified host.
export DATABRICKS_DISCOVERY_URL="$DATABRICKS_HOST/oidc/accounts/spog-acct-123/.well-known/oauth-authorization-server"

# Unified hosts are rejected before the device authorization request.
trace musterr $CLI auth login --host $DATABRICKS_HOST --use-device-code
trace print_requests.py //oidc/v1/device/auth
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Ignore = [
"home"
]
RecordRequests = true
16 changes: 16 additions & 0 deletions acceptance/cmd/auth/login/use-device-code/out.databrickscfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
; The profile defined in the DEFAULT section is to be used as a fallback when no profile is explicitly specified.
[DEFAULT]

[test]
host = [DATABRICKS_URL]
workspace_id = [WORKSPACE_ID]
auth_type = databricks-cli

[__settings__]
default_profile = test

[custom-scopes]
host = [DATABRICKS_URL]
workspace_id = [WORKSPACE_ID]
scopes = sql
auth_type = databricks-cli
1 change: 1 addition & 0 deletions acceptance/cmd/auth/login/use-device-code/out.test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cloud = false
183 changes: 183 additions & 0 deletions acceptance/cmd/auth/login/use-device-code/output.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@

=== Device code login is disabled by default

>>> musterr [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code
Error: --use-device-code is experimental. Set DATABRICKS_CLI_DEVICE_CODE=true to enable it

=== Inputs device code login cannot honor are rejected

>>> musterr [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code --resource https://resource.test
Error: --use-device-code cannot be combined with --resource

>>> musterr [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code --skip-workspace
Error: --use-device-code cannot be combined with --skip-workspace

>>> musterr [CLI] auth login --profile new-profile --use-device-code
Error: --use-device-code requires a workspace host. Pass it as an argument or with --host

>>> musterr [CLI] auth login --profile scoped --use-device-code
Error: --use-device-code cannot be used with profile scoped because its login is scoped to resources. Log in without --use-device-code

=== Account hosts are rejected, whether passed directly or from a profile

>>> musterr [CLI] auth login --host https://accounts.cloud.databricks.com --profile test --use-device-code
Error: --use-device-code is only supported for workspace hosts

>>> musterr [CLI] auth login --profile account --use-device-code
Error: --use-device-code is only supported for workspace hosts

=== Login fails when no confirmation code is provided

>>> musterr [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code
Using a browser on another device, visit:
[DATABRICKS_URL]/device/verification

And enter the code:
WDJB-MJHT

Once finished, enter the confirmation code provided in your browser.
Confirmation code: Error: reading confirmation code: EOF

=== Login times out while waiting for the confirmation code

>>> musterr [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code --timeout 1s
Using a browser on another device, visit:
[DATABRICKS_URL]/device/verification

And enter the code:
WDJB-MJHT

Once finished, enter the confirmation code provided in your browser.
Confirmation code: Error: reading confirmation code: context deadline exceeded

=== Login fails after 3 wrong confirmation codes

>>> musterr [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code
Using a browser on another device, visit:
[DATABRICKS_URL]/device/verification

And enter the code:
WDJB-MJHT

Once finished, enter the confirmation code provided in your browser.
Confirmation code: Invalid confirmation code (error code: invalid_request). Enter the confirmation code again (2 attempts left).
Confirmation code: Invalid confirmation code (error code: invalid_request). Enter the confirmation code again (1 attempt left).
Confirmation code: Error: Invalid confirmation code (error code: invalid_request). Start login from scratch

=== Login succeeds after re-entering the confirmation code

>>> [CLI] auth login --host [DATABRICKS_URL] --profile test --use-device-code
Using a browser on another device, visit:
[DATABRICKS_URL]/device/verification

And enter the code:
WDJB-MJHT

Once finished, enter the confirmation code provided in your browser.
Confirmation code: Invalid confirmation code (error code: invalid_request). Enter the confirmation code again (2 attempts left).
Confirmation code: Confirmation code: Profile test was successfully saved

>>> [CLI] auth token --profile test
json.access_token = "oauth-token";

>>> [CLI] auth profiles
Name Host Valid
test (Default) [DATABRICKS_URL] YES

=== Login again with the host from the saved profile

>>> [CLI] auth login --profile test --use-device-code
Using a browser on another device, visit:
[DATABRICKS_URL]/device/verification

And enter the code:
WDJB-MJHT

Once finished, enter the confirmation code provided in your browser.
Confirmation code: Profile test was successfully saved

>>> [CLI] auth token --profile test
json.access_token = "oauth-token";

=== Device code requests

>>> print_requests.py //oidc/v1/device/auth //oidc/v1/token
{
"method": "POST",
"path": "/oidc/v1/device/auth",
"raw_body": "client_id=databricks-cli&scope=offline_access+all-apis"
}
{
"method": "POST",
"path": "/oidc/v1/device/auth",
"raw_body": "client_id=databricks-cli&scope=offline_access+all-apis"
}
{
"method": "POST",
"path": "/oidc/v1/device/auth",
"raw_body": "client_id=databricks-cli&scope=offline_access+all-apis"
}
{
"method": "POST",
"path": "/oidc/v1/token",
"raw_body": "client_id=databricks-cli&confirmation_code=AAAAAAAA&device_code=device-code-3&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"
}
{
"method": "POST",
"path": "/oidc/v1/token",
"raw_body": "client_id=databricks-cli&confirmation_code=BBBBBBBB&device_code=device-code-3&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"
}
{
"method": "POST",
"path": "/oidc/v1/token",
"raw_body": "client_id=databricks-cli&confirmation_code=CCCCCCCC&device_code=device-code-3&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"
}
{
"method": "POST",
"path": "/oidc/v1/device/auth",
"raw_body": "client_id=databricks-cli&scope=offline_access+all-apis"
}
{
"method": "POST",
"path": "/oidc/v1/token",
"raw_body": "client_id=databricks-cli&confirmation_code=AAAAAAAA&device_code=device-code-4&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"
}
{
"method": "POST",
"path": "/oidc/v1/token",
"raw_body": "client_id=databricks-cli&confirmation_code=FTFAQQKY&device_code=device-code-4&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"
}
{
"method": "POST",
"path": "/oidc/v1/device/auth",
"raw_body": "client_id=databricks-cli&scope=offline_access+all-apis"
}
{
"method": "POST",
"path": "/oidc/v1/token",
"raw_body": "client_id=databricks-cli&confirmation_code=FTFAQQKY&device_code=device-code-5&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"
}

=== Custom scopes are requested at device authorization

>>> [CLI] auth login --host [DATABRICKS_URL] --profile custom-scopes --use-device-code --scopes sql
Using a browser on another device, visit:
[DATABRICKS_URL]/device/verification

And enter the code:
WDJB-MJHT

Once finished, enter the confirmation code provided in your browser.
Confirmation code: Profile custom-scopes was successfully saved

>>> print_requests.py //oidc/v1/device/auth //oidc/v1/token
{
"method": "POST",
"path": "/oidc/v1/device/auth",
"raw_body": "client_id=databricks-cli&scope=offline_access+sql"
}
{
"method": "POST",
"path": "/oidc/v1/token",
"raw_body": "client_id=databricks-cli&confirmation_code=FTFAQQKY&device_code=device-code-6&grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code"
}
67 changes: 67 additions & 0 deletions acceptance/cmd/auth/login/use-device-code/script
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
sethome "./home"

title "Device code login is disabled by default\n"
trace musterr $CLI auth login --host $DATABRICKS_HOST --profile test --use-device-code

export DATABRICKS_CLI_DEVICE_CODE=true

title "Inputs device code login cannot honor are rejected\n"
trace musterr $CLI auth login --host $DATABRICKS_HOST --profile test --use-device-code --resource https://resource.test
trace musterr $CLI auth login --host $DATABRICKS_HOST --profile test --use-device-code --skip-workspace
# The profile does not exist yet and no host is given. auth login does not read
# DATABRICKS_HOST, so the usual login would fall back to the browser-based
# discovery flow, which device code login does not support.
trace musterr $CLI auth login --profile new-profile --use-device-code
cat > ./home/.databrickscfg << EOF
[scoped]
host = $DATABRICKS_HOST
auth_type = databricks-cli
resources = https://resource.test
EOF
trace musterr $CLI auth login --profile scoped --use-device-code
rm ./home/.databrickscfg

# The profile has no account ID: the host is rejected before the CLI would
# prompt for one.
title "Account hosts are rejected, whether passed directly or from a profile\n"
trace musterr $CLI auth login --host https://accounts.cloud.databricks.com --profile test --use-device-code
cat > ./home/.databrickscfg << EOF
[account]
host = https://accounts.cloud.databricks.test
EOF
trace musterr $CLI auth login --profile account --use-device-code
rm ./home/.databrickscfg

title "Login fails when no confirmation code is provided\n"
trace musterr $CLI auth login --host $DATABRICKS_HOST --profile test --use-device-code < /dev/null

# stdin stays open without a code, so only the timeout ends the login.
title "Login times out while waiting for the confirmation code\n"
sleep 3 | trace musterr $CLI auth login --host $DATABRICKS_HOST --profile test --use-device-code --timeout 1s

title "Login fails after 3 wrong confirmation codes\n"
printf "AAAA-AAAA\nBBBB-BBBB\nCCCC-CCCC\n" | trace musterr $CLI auth login --host $DATABRICKS_HOST --profile test --use-device-code

# A wrong confirmation code leaves the device code valid, so the user can
# enter it again. A blank line asks again without contacting the workspace.
# The confirmation code is accepted the way the browser displays it, in any case.
title "Login succeeds after re-entering the confirmation code\n"
printf "AAAA-AAAA\n\nftfa-qqky\n" | trace $CLI auth login --host $DATABRICKS_HOST --profile test --use-device-code
trace $CLI auth token --profile test | gron.py | grep access_token
trace $CLI auth profiles

title "Login again with the host from the saved profile\n"
printf "FTFA-QQKY\n" | trace $CLI auth login --profile test --use-device-code
trace $CLI auth token --profile test | gron.py | grep access_token

title "Device code requests\n"
trace print_requests.py //oidc/v1/device/auth //oidc/v1/token

# The token gets the scopes requested at device authorization, so --scopes is
# sent there and not with the token request.
title "Custom scopes are requested at device authorization\n"
printf "FTFA-QQKY\n" | trace $CLI auth login --host $DATABRICKS_HOST --profile custom-scopes --use-device-code --scopes sql
trace print_requests.py //oidc/v1/device/auth //oidc/v1/token

# Track the .databrickscfg file that was created to surface changes.
mv "./home/.databrickscfg" "./out.databrickscfg"
4 changes: 4 additions & 0 deletions acceptance/cmd/auth/login/use-device-code/test.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Ignore = [
"home"
]
RecordRequests = true
Loading
Loading