Skip to content

Commit 429cb31

Browse files
Scopes support in auth commands (#4327)
## Changes - Updates the `auth login` command to take `--scopes` as an argument ## Why <!-- Why are these changes needed? Provide the context that the reviewer might be missing. For example, were there any decisions behind the change that are not reflected in the code itself? --> These changes come as part of an effort to support fine-grained, user-provided scopes in all our tools. ## Tests <!-- How have you tested the changes? --> - unit tests - acceptance tests <!-- If your PR needs to be included in the release notes for next release, add a separate entry in NEXT_CHANGELOG.md as part of your PR. --> ---
1 parent 5c11b27 commit 429cb31

File tree

7 files changed

+67
-1
lines changed

7 files changed

+67
-1
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
; The profile defined in the DEFAULT section is to be used as a fallback when no profile is explicitly specified.
2+
[DEFAULT]
3+
4+
[scoped-test]
5+
host = [DATABRICKS_URL]
6+
scopes = jobs,pipelines,clusters
7+
auth_type = databricks-cli

acceptance/cmd/auth/login/with-scopes/out.test.toml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
2+
>>> [CLI] auth login --host [DATABRICKS_URL] --profile scoped-test --scopes jobs,pipelines,clusters
3+
Profile scoped-test was successfully saved
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
sethome "./home"
2+
3+
# Use a fake browser that performs a GET on the authorization URL
4+
# and follows the redirect back to localhost.
5+
export BROWSER="browser.py"
6+
7+
trace $CLI auth login --host $DATABRICKS_HOST --profile scoped-test --scopes "jobs,pipelines,clusters"
8+
9+
# Track the .databrickscfg file that was created to surface changes.
10+
mv "./home/.databrickscfg" "./out.databrickscfg"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Ignore = [
2+
"home"
3+
]

cmd/auth/login.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,15 @@ depends on the existing profiles you have set in your configuration file
101101
var loginTimeout time.Duration
102102
var configureCluster bool
103103
var configureServerless bool
104+
var scopes string
104105
cmd.Flags().DurationVar(&loginTimeout, "timeout", defaultTimeout,
105106
"Timeout for completing login challenge in the browser")
106107
cmd.Flags().BoolVar(&configureCluster, "configure-cluster", false,
107108
"Prompts to configure cluster")
108109
cmd.Flags().BoolVar(&configureServerless, "configure-serverless", false,
109110
"Prompts to configure serverless")
111+
cmd.Flags().StringVar(&scopes, "scopes", "",
112+
"Comma-separated list of OAuth scopes to request (defaults to 'all-apis')")
110113

111114
cmd.RunE = func(cmd *cobra.Command, args []string) error {
112115
ctx := cmd.Context()
@@ -149,14 +152,24 @@ depends on the existing profiles you have set in your configuration file
149152
return err
150153
}
151154

155+
var scopesList []string
156+
if scopes != "" {
157+
for _, s := range strings.Split(scopes, ",") {
158+
scopesList = append(scopesList, strings.TrimSpace(s))
159+
}
160+
}
161+
152162
oauthArgument, err := authArguments.ToOAuthArgument()
153163
if err != nil {
154164
return err
155165
}
156166
persistentAuthOpts := []u2m.PersistentAuthOption{
157167
u2m.WithOAuthArgument(oauthArgument),
168+
u2m.WithBrowser(getBrowserFunc(cmd)),
169+
}
170+
if len(scopesList) > 0 {
171+
persistentAuthOpts = append(persistentAuthOpts, u2m.WithScopes(scopesList))
158172
}
159-
persistentAuthOpts = append(persistentAuthOpts, u2m.WithBrowser(getBrowserFunc(cmd)))
160173
persistentAuth, err := u2m.NewPersistentAuth(ctx, persistentAuthOpts...)
161174
if err != nil {
162175
return err
@@ -222,6 +235,7 @@ depends on the existing profiles you have set in your configuration file
222235
ClusterID: clusterID,
223236
ConfigFile: os.Getenv("DATABRICKS_CONFIG_FILE"),
224237
ServerlessComputeID: serverlessComputeID,
238+
Scopes: scopesList,
225239
})
226240
if err != nil {
227241
return err

libs/databrickscfg/ops_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,3 +225,27 @@ func TestSaveToProfile_ClearingPreviousProfile(t *testing.T) {
225225
assert.Equal(t, "https://foo", raw["host"])
226226
assert.Equal(t, "databricks-cli", raw["auth_type"])
227227
}
228+
229+
func TestSaveToProfile_WithScopes(t *testing.T) {
230+
ctx := context.Background()
231+
path := filepath.Join(t.TempDir(), "databrickscfg")
232+
233+
err := SaveToProfile(ctx, &config.Config{
234+
ConfigFile: path,
235+
Profile: "scoped",
236+
Host: "https://myworkspace.cloud.databricks.com",
237+
AuthType: "databricks-cli",
238+
Scopes: []string{"jobs", "pipelines", "clusters"},
239+
})
240+
require.NoError(t, err)
241+
242+
file, err := loadOrCreateConfigFile(path)
243+
require.NoError(t, err)
244+
section, err := file.GetSection("scoped")
245+
require.NoError(t, err)
246+
raw := section.KeysHash()
247+
assert.Len(t, raw, 3)
248+
assert.Equal(t, "https://myworkspace.cloud.databricks.com", raw["host"])
249+
assert.Equal(t, "databricks-cli", raw["auth_type"])
250+
assert.Equal(t, "jobs,pipelines,clusters", raw["scopes"])
251+
}

0 commit comments

Comments
 (0)