diff --git a/internal/provider/databricks/databricks.go b/internal/provider/databricks/databricks.go index 8c86a4e..63883c6 100644 --- a/internal/provider/databricks/databricks.go +++ b/internal/provider/databricks/databricks.go @@ -318,18 +318,23 @@ func (p *Provider) Value(ctx context.Context, o provider.Object) (provider.Secre } // deniedChecks are what to check when Databricks refuses: the network, -// when the workspace's IP access list refused, else access. -func deniedChecks(msg string) []string { +// when the workspace's IP access list refused, else access, and for a +// profile signed in through az, which account az is on. +func deniedChecks(pr profile, msg string) []string { if strings.Contains(msg, "IP ACL") || strings.Contains(msg, "IP access list") { return []string{ "you're on a network the workspace lets in (VPN, office)", "the workspace's admin has let your network in", } } - return []string{ + var checks []string + if pr.authType == "azure-cli" { + checks = append(checks, "az is signed in as the account with access: profile "+pr.name+" uses your az login (az account show)") + } + return append(checks, "you have access to the workspace", "the scope's manager has given you READ on it, or a group you're in", - } + ) } var errNoFallback = errors.New("no Key Vault fallback") @@ -369,7 +374,7 @@ func classify(pr profile, err error) error { var api *apierr.APIError if errors.As(err, &api) { if api.StatusCode == 403 { - return &provider.Denied{Err: err, Checks: deniedChecks(api.Message)} + return &provider.Denied{Err: err, Checks: deniedChecks(pr, api.Message)} } if api.StatusCode != 401 { return err diff --git a/internal/provider/databricks/databricks_test.go b/internal/provider/databricks/databricks_test.go index 33efc6a..89909c5 100644 --- a/internal/provider/databricks/databricks_test.go +++ b/internal/provider/databricks/databricks_test.go @@ -322,10 +322,15 @@ func TestDeniedSaysWhatToCheck(t *testing.T) { p := newTestProvider(t, workspaceAPI(t, 0), nil) _, err := p.Objects(context.Background(), provider.Container{Source: provider.Source{ID: "prod"}, Name: "locked"}, provider.TypeSecret) var d *provider.Denied - if !errors.As(err, &d) || !strings.Contains(err.Error(), "READ permission on scope locked\n\nCheck:\n• you have access to the workspace") { + // The test profile signs in through az: that's the first check. + if !errors.As(err, &d) || !strings.Contains(err.Error(), "READ permission on scope locked\n\nCheck:\n• az is signed in as the account with access: profile prod uses your az login") || + !strings.Contains(err.Error(), "\n• you have access to the workspace") { t.Errorf("err %q", err) } - if got := deniedChecks("Source IP address: 1.2.3.4 is blocked by Databricks IP ACL for workspace: 1"); !strings.Contains(got[0], "network") { + if got := deniedChecks(profile{authType: "pat"}, "denied"); strings.Contains(got[0], "az") { + t.Errorf("a token profile's checks %q", got) + } + if got := deniedChecks(profile{}, "Source IP address: 1.2.3.4 is blocked by Databricks IP ACL for workspace: 1"); !strings.Contains(got[0], "network") { t.Errorf("IP ACL checks %q", got) }