From cda93dd8ec366910549bc5ec663e3afdd959a9e9 Mon Sep 17 00:00:00 2001 From: Lennart Kats Date: Tue, 3 Nov 2026 13:26:33 +0000 Subject: [PATCH 1/3] Warn when bundle run_as may lack file access --- .../bundles/warn-run-as-file-access.md | 1 + .../run_as/allowed/regular_user/output.txt | 16 ++ .../allowed/service_principal/output.txt | 16 ++ .../bundle/run_as/dashboard_embed/output.txt | 10 +- .../bundle/run_as/empty_override/output.txt | 8 + .../bundle/run_as/empty_override/script | 2 +- .../bundle/run_as/empty_run_as_dict/script | 2 +- acceptance/bundle/run_as/output.txt | 16 ++ .../run_as/pipelines/regular_user/output.txt | 102 ++++++++++- .../pipelines/service_principal/output.txt | 102 ++++++++++- .../bundle/run_as/pipelines_legacy/output.txt | 8 + .../telemetry/deploy-experimental/output.txt | 8 + .../bundle/telemetry/deploy-run-as/output.txt | 8 + bundle/permissions/permission_diagnostics.go | 67 +++++++- .../permission_diagnostics_test.go | 160 ++++++++++++++++++ 15 files changed, 513 insertions(+), 13 deletions(-) create mode 100644 .nextchanges/bundles/warn-run-as-file-access.md diff --git a/.nextchanges/bundles/warn-run-as-file-access.md b/.nextchanges/bundles/warn-run-as-file-access.md new file mode 100644 index 00000000000..c802ab9d6e0 --- /dev/null +++ b/.nextchanges/bundles/warn-run-as-file-access.md @@ -0,0 +1 @@ +* Warn when a bundle's `run_as` identity may lack access to deployed files, with guidance for top-level permissions and source-linked files. diff --git a/acceptance/bundle/run_as/allowed/regular_user/output.txt b/acceptance/bundle/run_as/allowed/regular_user/output.txt index a326e670813..aff3856965a 100644 --- a/acceptance/bundle/run_as/allowed/regular_user/output.txt +++ b/acceptance/bundle/run_as/allowed/regular_user/output.txt @@ -1,5 +1,13 @@ >>> [CLI] bundle validate -o json +Warning: run_as identity "my_service_principal" is not in top-level permissions for bundle files + in databricks.yml:5:3 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: my_service_principal + level: CAN_VIEW + >>> jq .run_as { @@ -38,6 +46,14 @@ } >>> [CLI] bundle validate -o json -t development +Warning: run_as identity "my_user_name" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: my_user_name + level: CAN_VIEW + >>> jq .run_as { diff --git a/acceptance/bundle/run_as/allowed/service_principal/output.txt b/acceptance/bundle/run_as/allowed/service_principal/output.txt index a326e670813..aff3856965a 100644 --- a/acceptance/bundle/run_as/allowed/service_principal/output.txt +++ b/acceptance/bundle/run_as/allowed/service_principal/output.txt @@ -1,5 +1,13 @@ >>> [CLI] bundle validate -o json +Warning: run_as identity "my_service_principal" is not in top-level permissions for bundle files + in databricks.yml:5:3 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: my_service_principal + level: CAN_VIEW + >>> jq .run_as { @@ -38,6 +46,14 @@ } >>> [CLI] bundle validate -o json -t development +Warning: run_as identity "my_user_name" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: my_user_name + level: CAN_VIEW + >>> jq .run_as { diff --git a/acceptance/bundle/run_as/dashboard_embed/output.txt b/acceptance/bundle/run_as/dashboard_embed/output.txt index 5f316f521f6..58a182936c0 100644 --- a/acceptance/bundle/run_as/dashboard_embed/output.txt +++ b/acceptance/bundle/run_as/dashboard_embed/output.txt @@ -1,12 +1,20 @@ >>> errcode [CLI] bundle validate --var embed=false +Warning: run_as identity "sp-name" is not in top-level permissions for bundle files + in databricks.yml:5:3 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: sp-name + level: CAN_VIEW + Name: dashboard_embed Target: default Workspace: User: [USERNAME] Path: /Workspace/Users/[USERNAME]/.bundle/dashboard_embed/default -Validation OK! +Found 1 warning >>> errcode [CLI] bundle validate --var embed=true Error: dashboards with embed_credentials set to true do not support a setting a run_as user that is different from the owner. diff --git a/acceptance/bundle/run_as/empty_override/output.txt b/acceptance/bundle/run_as/empty_override/output.txt index 635d9eda9df..78e4fc53292 100644 --- a/acceptance/bundle/run_as/empty_override/output.txt +++ b/acceptance/bundle/run_as/empty_override/output.txt @@ -1,2 +1,10 @@ +Warning: run_as identity "my_user_name" is not in top-level permissions for bundle files + in databricks.yml:5:3 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: my_user_name + level: CAN_VIEW + "run_as": { "run_as": { diff --git a/acceptance/bundle/run_as/empty_override/script b/acceptance/bundle/run_as/empty_override/script index de89daa9199..c97112e9ddb 100644 --- a/acceptance/bundle/run_as/empty_override/script +++ b/acceptance/bundle/run_as/empty_override/script @@ -1 +1 @@ -$CLI bundle validate -o json | grep run_as +$CLI bundle validate -o json | grep '"run_as"' diff --git a/acceptance/bundle/run_as/empty_run_as_dict/script b/acceptance/bundle/run_as/empty_run_as_dict/script index a8f5a36d672..d29883e42a6 100644 --- a/acceptance/bundle/run_as/empty_run_as_dict/script +++ b/acceptance/bundle/run_as/empty_run_as_dict/script @@ -1 +1 @@ -musterr $CLI bundle validate -o json | grep run_as +musterr $CLI bundle validate -o json | grep '"run_as"' diff --git a/acceptance/bundle/run_as/output.txt b/acceptance/bundle/run_as/output.txt index ca8c1b13bce..73e4ba63b7c 100644 --- a/acceptance/bundle/run_as/output.txt +++ b/acceptance/bundle/run_as/output.txt @@ -8,6 +8,14 @@ pipelines.pipeline_three: {"user_name":"user_override"} pipelines.pipeline_two: {"service_principal_name":"sp_override"} >>> [CLI] bundle validate -o json -t with_user_run_as +Warning: run_as identity "user_base" is not in top-level permissions for bundle files + in databricks.yml:39:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: user_base + level: CAN_VIEW + jobs.job_one: {"user_name":"user_base"} jobs.job_three: {"user_name":"user_override"} jobs.job_two: {"service_principal_name":"sp_override"} @@ -16,6 +24,14 @@ pipelines.pipeline_three: {"user_name":"user_override"} pipelines.pipeline_two: {"service_principal_name":"sp_override"} >>> [CLI] bundle validate -o json -t with_sp_run_as +Warning: run_as identity "sp_base" is not in top-level permissions for bundle files + in databricks.yml:43:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: sp_base + level: CAN_VIEW + jobs.job_one: {"service_principal_name":"sp_base"} jobs.job_three: {"user_name":"user_override"} jobs.job_two: {"service_principal_name":"sp_override"} diff --git a/acceptance/bundle/run_as/pipelines/regular_user/output.txt b/acceptance/bundle/run_as/pipelines/regular_user/output.txt index 21faafb4d57..e6855cc663b 100644 --- a/acceptance/bundle/run_as/pipelines/regular_user/output.txt +++ b/acceptance/bundle/run_as/pipelines/regular_user/output.txt @@ -25,21 +25,53 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_user_name_different >>> [CLI] bundle validate -t t_user_name_different +Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: different@databricks.com + level: CAN_VIEW + Name: run_as Target: t_user_name_different Workspace: User: [USERNAME] Path: /Workspace/Users/[USERNAME]/.bundle/run_as/t_user_name_different -Validation OK! +Found 1 warning >>> [CLI] bundle plan -t t_user_name_different +Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: different@databricks.com + level: CAN_VIEW + create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged +Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: different@databricks.com + level: CAN_VIEW + >>> [CLI] bundle deploy -t t_user_name_different +Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: different@databricks.com + level: CAN_VIEW + Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/run_as/t_user_name_different/files... Created pipelines.nyc_taxi_pipeline Created pipelines.nyc_taxi_pipeline.permissions @@ -48,21 +80,53 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_service_principal_name >>> [CLI] bundle validate -t t_service_principal_name +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:10:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: [UUID] + level: CAN_VIEW + Name: run_as Target: t_service_principal_name Workspace: User: [USERNAME] Path: /Workspace/Users/[USERNAME]/.bundle/run_as/t_service_principal_name -Validation OK! +Found 1 warning >>> [CLI] bundle plan -t t_service_principal_name +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:10:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: [UUID] + level: CAN_VIEW + create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:10:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: [UUID] + level: CAN_VIEW + >>> [CLI] bundle deploy -t t_service_principal_name +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:10:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: [UUID] + level: CAN_VIEW + Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/run_as/t_service_principal_name/files... Created pipelines.nyc_taxi_pipeline Created pipelines.nyc_taxi_pipeline.permissions @@ -71,21 +135,53 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_service_principal_name_different >>> [CLI] bundle validate -t t_service_principal_name_different +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:16:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: [UUID] + level: CAN_VIEW + Name: run_as Target: t_service_principal_name_different Workspace: User: [USERNAME] Path: /Workspace/Users/[USERNAME]/.bundle/run_as/t_service_principal_name_different -Validation OK! +Found 1 warning >>> [CLI] bundle plan -t t_service_principal_name_different +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:16:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: [UUID] + level: CAN_VIEW + create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:16:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: [UUID] + level: CAN_VIEW + >>> [CLI] bundle deploy -t t_service_principal_name_different +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:16:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: [UUID] + level: CAN_VIEW + Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/run_as/t_service_principal_name_different/files... Created pipelines.nyc_taxi_pipeline Created pipelines.nyc_taxi_pipeline.permissions diff --git a/acceptance/bundle/run_as/pipelines/service_principal/output.txt b/acceptance/bundle/run_as/pipelines/service_principal/output.txt index 21faafb4d57..f6bd6858a44 100644 --- a/acceptance/bundle/run_as/pipelines/service_principal/output.txt +++ b/acceptance/bundle/run_as/pipelines/service_principal/output.txt @@ -2,21 +2,53 @@ === run_as should succeed in all cases\nProcessing target: t_user_name >>> [CLI] bundle validate -t t_user_name +Warning: run_as identity "tester@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:7:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: tester@databricks.com + level: CAN_VIEW + Name: run_as Target: t_user_name Workspace: User: [USERNAME] Path: /Workspace/Users/[USERNAME]/.bundle/run_as/t_user_name -Validation OK! +Found 1 warning >>> [CLI] bundle plan -t t_user_name +Warning: run_as identity "tester@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:7:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: tester@databricks.com + level: CAN_VIEW + create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged +Warning: run_as identity "tester@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:7:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: tester@databricks.com + level: CAN_VIEW + >>> [CLI] bundle deploy -t t_user_name +Warning: run_as identity "tester@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:7:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: tester@databricks.com + level: CAN_VIEW + Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/run_as/t_user_name/files... Created pipelines.nyc_taxi_pipeline Created pipelines.nyc_taxi_pipeline.permissions @@ -25,21 +57,53 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_user_name_different >>> [CLI] bundle validate -t t_user_name_different +Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: different@databricks.com + level: CAN_VIEW + Name: run_as Target: t_user_name_different Workspace: User: [USERNAME] Path: /Workspace/Users/[USERNAME]/.bundle/run_as/t_user_name_different -Validation OK! +Found 1 warning >>> [CLI] bundle plan -t t_user_name_different +Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: different@databricks.com + level: CAN_VIEW + create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged +Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: different@databricks.com + level: CAN_VIEW + >>> [CLI] bundle deploy -t t_user_name_different +Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files + in databricks.yml:13:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: different@databricks.com + level: CAN_VIEW + Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/run_as/t_user_name_different/files... Created pipelines.nyc_taxi_pipeline Created pipelines.nyc_taxi_pipeline.permissions @@ -71,21 +135,53 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_service_principal_name_different >>> [CLI] bundle validate -t t_service_principal_name_different +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:16:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: [UUID] + level: CAN_VIEW + Name: run_as Target: t_service_principal_name_different Workspace: User: [USERNAME] Path: /Workspace/Users/[USERNAME]/.bundle/run_as/t_service_principal_name_different -Validation OK! +Found 1 warning >>> [CLI] bundle plan -t t_service_principal_name_different +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:16:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: [UUID] + level: CAN_VIEW + create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:16:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: [UUID] + level: CAN_VIEW + >>> [CLI] bundle deploy -t t_service_principal_name_different +Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files + in databricks.yml:16:7 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: [UUID] + level: CAN_VIEW + Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/run_as/t_service_principal_name_different/files... Created pipelines.nyc_taxi_pipeline Created pipelines.nyc_taxi_pipeline.permissions diff --git a/acceptance/bundle/run_as/pipelines_legacy/output.txt b/acceptance/bundle/run_as/pipelines_legacy/output.txt index cfd58c5e866..f9a6faeb160 100644 --- a/acceptance/bundle/run_as/pipelines_legacy/output.txt +++ b/acceptance/bundle/run_as/pipelines_legacy/output.txt @@ -4,6 +4,14 @@ Warning: You are using the legacy mode of run_as. The support for this mode is e at experimental.use_legacy_run_as in databricks.yml:8:22 +Warning: run_as identity "my_service_principal" is not in top-level permissions for bundle files + in databricks.yml:5:3 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: my_service_principal + level: CAN_VIEW + >>> jq .run_as { diff --git a/acceptance/bundle/telemetry/deploy-experimental/output.txt b/acceptance/bundle/telemetry/deploy-experimental/output.txt index dcd99009312..0a6d09e88b8 100644 --- a/acceptance/bundle/telemetry/deploy-experimental/output.txt +++ b/acceptance/bundle/telemetry/deploy-experimental/output.txt @@ -4,6 +4,14 @@ Warning: You are using the legacy mode of run_as. The support for this mode is e at experimental.use_legacy_run_as in databricks.yml:5:22 +Warning: run_as identity "abcd" is not in top-level permissions for bundle files + in databricks.yml:8:3 + +Add a top-level permission so this identity can read deployed files: + permissions: + - user_name: abcd + level: CAN_VIEW + Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files... Created jobs.foo Files: 1 uploaded, 0 deleted diff --git a/acceptance/bundle/telemetry/deploy-run-as/output.txt b/acceptance/bundle/telemetry/deploy-run-as/output.txt index e6b42026853..6f876faf7eb 100644 --- a/acceptance/bundle/telemetry/deploy-run-as/output.txt +++ b/acceptance/bundle/telemetry/deploy-run-as/output.txt @@ -1,5 +1,13 @@ >>> [CLI] bundle deploy +Warning: run_as identity "sp_test" is not in top-level permissions for bundle files + in databricks.yml:5:3 + +Add a top-level permission so this identity can read deployed files: + permissions: + - service_principal_name: sp_test + level: CAN_VIEW + Uploading bundle files to /Workspace/Users/[USERNAME]/.bundle/test-bundle/default/files... Created jobs.test_job Files: 1 uploaded, 0 deleted diff --git a/bundle/permissions/permission_diagnostics.go b/bundle/permissions/permission_diagnostics.go index 0e01f72a0f4..e03f4fa11e5 100644 --- a/bundle/permissions/permission_diagnostics.go +++ b/bundle/permissions/permission_diagnostics.go @@ -7,6 +7,8 @@ import ( "strings" "github.com/databricks/cli/bundle" + "github.com/databricks/cli/bundle/config/resources" + "github.com/databricks/cli/bundle/libraries" "github.com/databricks/cli/libs/diag" "github.com/databricks/cli/libs/iamutil" "github.com/databricks/cli/libs/set" @@ -29,14 +31,15 @@ func (m *permissionDiagnostics) Name() string { } func (m *permissionDiagnostics) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { + diags := runAsFileAccessDiagnostics(b) + // Only recommend deployment-identity access when top-level permissions are explicit. if len(b.Config.Permissions) == 0 { - // Only warn if there is an explicit top-level permissions section - return nil + return diags } canManageBundle, _ := analyzeBundlePermissions(b) if canManageBundle { - return nil + return diags } me := b.Config.Workspace.CurrentUser.User @@ -45,7 +48,7 @@ func (m *permissionDiagnostics) Apply(ctx context.Context, b *bundle.Bundle) dia identityType = "service_principal_name" } - return diag.Diagnostics{{ + return diags.Append(diag.Diagnostic{ Severity: diag.Recommendation, Summary: fmt.Sprintf("permissions section should explicitly include the current deployment identity '%s' or one of its groups\n"+ "If it is not included, CAN_MANAGE permissions are only applied if the present identity is used to deploy.\n\n"+ @@ -60,6 +63,62 @@ func (m *permissionDiagnostics) Apply(ctx context.Context, b *bundle.Bundle) dia ), Locations: []diag.Location{b.Config.GetLocation("permissions")}, ID: diag.PermissionNotIncluded, + }) +} + +func runAsFileAccessDiagnostics(b *bundle.Bundle) diag.Diagnostics { + runAs := b.Config.RunAs + if runAs == nil { + return nil + } + + identityType, identity := "user_name", runAs.UserName + if runAs.ServicePrincipalName != "" { + identityType, identity = "service_principal_name", runAs.ServicePrincipalName + } else if runAs.GroupName != "" { + identityType, identity = "group_name", runAs.GroupName + } + + if identityType != "group_name" && identity == b.Config.Workspace.CurrentUser.UserName { + return nil + } + + if b.IsSourceLinkedDeployment() { + return diag.Diagnostics{{ + Severity: diag.Warning, + Summary: fmt.Sprintf("run_as identity %q may not be able to read source-linked files", identity), + Detail: "Source-linked deployments read files from the source workspace folder. Grant the run_as identity CAN_READ access to that folder; top-level bundle permissions do not manage source-linked files.", + Locations: []diag.Location{b.Config.GetLocation("run_as")}, + }} + } + if libraries.IsWorkspaceSharedPath(b.Config.Workspace.FilePath) { + return diag.Diagnostics{{ + Severity: diag.Warning, + Summary: fmt.Sprintf("run_as identity %q may not be able to read files in /Workspace/Shared", identity), + Detail: fmt.Sprintf("Check that the run_as identity has CAN_READ access to %s. Top-level bundle permissions do not manage files in /Workspace/Shared.", b.Config.Workspace.FilePath), + Locations: []diag.Location{b.Config.GetLocation("run_as")}, + }} + } + + runAsPermission := resources.Permission{ + UserName: runAs.UserName, + ServicePrincipalName: runAs.ServicePrincipalName, + GroupName: runAs.GroupName, + } + for _, permission := range b.Config.Permissions { + if samePrincipal(permission, runAsPermission) { + return nil + } + } + + return diag.Diagnostics{{ + Severity: diag.Warning, + Summary: fmt.Sprintf("run_as identity %q is not in top-level permissions for bundle files", identity), + Detail: fmt.Sprintf("Add a top-level permission so this identity can read deployed files:\n"+ + " permissions:\n"+ + " - %s: %s\n"+ + " level: CAN_VIEW", identityType, identity), + Locations: []diag.Location{b.Config.GetLocation("run_as")}, }} } diff --git a/bundle/permissions/permission_diagnostics_test.go b/bundle/permissions/permission_diagnostics_test.go index e5a9214f437..8093249593f 100644 --- a/bundle/permissions/permission_diagnostics_test.go +++ b/bundle/permissions/permission_diagnostics_test.go @@ -9,6 +9,7 @@ import ( "github.com/databricks/cli/bundle/permissions" "github.com/databricks/cli/libs/diag" "github.com/databricks/databricks-sdk-go/service/iam" + "github.com/databricks/databricks-sdk-go/service/jobs" "github.com/stretchr/testify/require" ) @@ -48,6 +49,165 @@ func TestPermissionDiagnosticsApplyFail(t *testing.T) { require.Contains(t, diags[0].Summary, expectedMsg) } +func TestPermissionDiagnosticsRunAsFileAccess(t *testing.T) { + deployerPermission := resources.Permission{Level: "CAN_MANAGE", UserName: "testuser@databricks.com"} + servicePrincipalName := "aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee" + servicePrincipal := jobs.JobRunAs{ServicePrincipalName: servicePrincipalName} + + testCases := []struct { + name string + runAs jobs.JobRunAs + permissions []resources.Permission + currentUser string + syncMode config.SyncMode + filePath string + wantSummary string + wantSuggestion string + }{ + { + name: "service principal without permissions", + runAs: servicePrincipal, + wantSummary: "is not in top-level permissions for bundle files", + wantSuggestion: "service_principal_name: " + servicePrincipalName + "\n level: CAN_VIEW", + }, + { + name: "user without permissions", + runAs: jobs.JobRunAs{UserName: "runner@example.test"}, + wantSummary: "is not in top-level permissions for bundle files", + wantSuggestion: "user_name: runner@example.test\n level: CAN_VIEW", + }, + { + name: "group without permissions", + runAs: jobs.JobRunAs{GroupName: "runners"}, + wantSummary: "is not in top-level permissions for bundle files", + wantSuggestion: "group_name: runners\n level: CAN_VIEW", + }, + { + name: "unrelated group permission", + runAs: servicePrincipal, + permissions: []resources.Permission{deployerPermission, {Level: "CAN_VIEW", GroupName: "runners"}}, + wantSummary: "is not in top-level permissions for bundle files", + wantSuggestion: "service_principal_name: " + servicePrincipalName, + }, + { + name: "service principal with view permission", + runAs: servicePrincipal, + permissions: []resources.Permission{deployerPermission, {Level: "CAN_VIEW", ServicePrincipalName: servicePrincipalName}}, + }, + { + name: "service principal with run permission", + runAs: servicePrincipal, + permissions: []resources.Permission{deployerPermission, {Level: "CAN_RUN", ServicePrincipalName: servicePrincipalName}}, + }, + { + name: "service principal with manage permission", + runAs: servicePrincipal, + permissions: []resources.Permission{deployerPermission, {Level: "CAN_MANAGE", ServicePrincipalName: servicePrincipalName}}, + }, + { + name: "group with view permission", + runAs: jobs.JobRunAs{GroupName: "runners"}, + permissions: []resources.Permission{deployerPermission, {Level: "CAN_VIEW", GroupName: "runners"}}, + }, + { + name: "run as deployment user", + runAs: jobs.JobRunAs{UserName: "testuser@databricks.com"}, + }, + { + name: "run as deployment service principal", + runAs: servicePrincipal, + currentUser: servicePrincipal.ServicePrincipalName, + }, + { + name: "source-linked files", + runAs: servicePrincipal, + syncMode: config.SyncModeInPlace, + wantSummary: "may not be able to read source-linked files", + wantSuggestion: "CAN_READ access to that folder; top-level bundle permissions do not manage source-linked files", + }, + { + name: "source-linked files with top-level permissions", + runAs: servicePrincipal, + permissions: []resources.Permission{deployerPermission, {Level: "CAN_VIEW", ServicePrincipalName: servicePrincipalName}}, + syncMode: config.SyncModeInPlace, + wantSummary: "may not be able to read source-linked files", + wantSuggestion: "CAN_READ access to that folder", + }, + { + name: "immutable bundle without permissions", + runAs: servicePrincipal, + syncMode: config.SyncModeImmutable, + wantSummary: "is not in top-level permissions for bundle files", + wantSuggestion: "level: CAN_VIEW", + }, + { + name: "files under Shared", + runAs: servicePrincipal, + filePath: "/Workspace/Shared/team/files", + wantSummary: "may not be able to read files in /Workspace/Shared", + wantSuggestion: "Check that the run_as identity has CAN_READ access to /Workspace/Shared/team/files. Top-level bundle permissions do not manage files in /Workspace/Shared.", + }, + { + name: "files under Shared with top-level permissions", + runAs: servicePrincipal, + permissions: []resources.Permission{deployerPermission, {Level: "CAN_VIEW", ServicePrincipalName: servicePrincipalName}}, + filePath: "/Workspace/Shared/team/files", + wantSummary: "may not be able to read files in /Workspace/Shared", + wantSuggestion: "Top-level bundle permissions do not manage files in /Workspace/Shared.", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + deployment := mockBundle(testCase.permissions) + deployment.Config.RunAs = &testCase.runAs + deployment.Config.Workspace.SyncMode = testCase.syncMode + deployment.Config.Workspace.FilePath = testCase.filePath + if testCase.currentUser != "" { + deployment.Config.Workspace.CurrentUser.User.UserName = testCase.currentUser + } + + diags := bundle.Apply(t.Context(), deployment, permissions.PermissionDiagnostics()) + if testCase.wantSummary == "" { + require.Empty(t, diags) + return + } + + require.Len(t, diags, 1) + require.Equal(t, diag.Warning, diags[0].Severity) + require.Contains(t, diags[0].Summary, testCase.wantSummary) + require.Contains(t, diags[0].Detail, testCase.wantSuggestion) + require.NoError(t, diags.Error()) + }) + } +} + +func TestPermissionDiagnosticsResourcePermissionDoesNotCoverRunAsFiles(t *testing.T) { + servicePrincipalName := "aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee" + deployment := mockBundle(nil) + deployment.Config.RunAs = &jobs.JobRunAs{ServicePrincipalName: servicePrincipalName} + deployment.Config.Resources.Jobs = map[string]*resources.Job{ + "job": { + Permissions: []resources.JobPermission{{Level: "CAN_VIEW", ServicePrincipalName: servicePrincipalName}}, + }, + } + + diags := bundle.Apply(t.Context(), deployment, permissions.PermissionDiagnostics()) + require.Len(t, diags, 1) + require.Equal(t, diag.Warning, diags[0].Severity) + require.Contains(t, diags[0].Detail, "level: CAN_VIEW") +} + +func TestPermissionDiagnosticsRunAsAndDeployerWarnings(t *testing.T) { + deployment := mockBundle([]resources.Permission{{Level: "CAN_VIEW", GroupName: "other_group"}}) + deployment.Config.RunAs = &jobs.JobRunAs{UserName: "runner@example.test"} + + diags := bundle.Apply(t.Context(), deployment, permissions.PermissionDiagnostics()) + require.Len(t, diags, 2) + require.Equal(t, diag.Warning, diags[0].Severity) + require.Equal(t, diag.Recommendation, diags[1].Severity) +} + func mockBundle(permissions []resources.Permission) *bundle.Bundle { return &bundle.Bundle{ Config: config.Root{ From 1fb8b4c365851434414fcb859b3a9caa62caf2db Mon Sep 17 00:00:00 2001 From: Lennart Kats Date: Tue, 3 Nov 2026 13:28:00 +0000 Subject: [PATCH 2/3] Link changelog entry to PR #7313 --- .nextchanges/bundles/warn-run-as-file-access.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nextchanges/bundles/warn-run-as-file-access.md b/.nextchanges/bundles/warn-run-as-file-access.md index c802ab9d6e0..9c920aac813 100644 --- a/.nextchanges/bundles/warn-run-as-file-access.md +++ b/.nextchanges/bundles/warn-run-as-file-access.md @@ -1 +1 @@ -* Warn when a bundle's `run_as` identity may lack access to deployed files, with guidance for top-level permissions and source-linked files. +* Warn when a bundle's `run_as` identity may lack access to deployed files, with guidance for top-level permissions and source-linked files. ([#7313](https://github.com/databricks/cli/pull/7313)) From dd70370de52d8e1488cbf8e529ecc1683b976ed9 Mon Sep 17 00:00:00 2001 From: Lennart Kats Date: Tue, 3 Nov 2026 13:46:28 +0000 Subject: [PATCH 3/3] bundle: clarify run_as top-level permission warning --- .../bundle/migrate/command/runas/output.txt | 40 ++++++++++++++++ .../run_as/allowed/regular_user/output.txt | 8 ++-- .../allowed/service_principal/output.txt | 8 ++-- .../bundle/run_as/dashboard_embed/output.txt | 4 +- .../bundle/run_as/empty_override/output.txt | 4 +- acceptance/bundle/run_as/output.txt | 8 ++-- .../run_as/pipelines/regular_user/output.txt | 48 +++++++++---------- .../pipelines/service_principal/output.txt | 48 +++++++++---------- .../bundle/run_as/pipelines_legacy/output.txt | 4 +- .../telemetry/deploy-experimental/output.txt | 4 +- .../bundle/telemetry/deploy-run-as/output.txt | 4 +- bundle/permissions/permission_diagnostics.go | 8 ++-- .../permission_diagnostics_test.go | 14 +++--- 13 files changed, 121 insertions(+), 81 deletions(-) diff --git a/acceptance/bundle/migrate/command/runas/output.txt b/acceptance/bundle/migrate/command/runas/output.txt index c17ffdec425..ff7c313ea5b 100644 --- a/acceptance/bundle/migrate/command/runas/output.txt +++ b/acceptance/bundle/migrate/command/runas/output.txt @@ -4,6 +4,14 @@ >>> print_requests.py //pipelines >>> print_state.py +Warning: run_as identity "[UUID]" is not in bundle top-level permissions + in databricks.yml:22:7 + +Add a top-level permission so this identity can access deployed files and resources: + permissions: + - service_principal_name: [UUID] + level: CAN_VIEW + Recommendation: permissions section should explicitly include the current deployment identity '[USERNAME]' or one of its groups If it is not included, CAN_MANAGE permissions are only applied if the present identity is used to deploy. @@ -21,6 +29,14 @@ Notice: migrating your bundle to direct deployment engine (https://github.com/da >>> [CLI] pipelines get [UUID] >>> DATABRICKS_BUNDLE_ENGINE= [CLI] bundle deployment migrate +Warning: run_as identity "[UUID]" is not in bundle top-level permissions + in databricks.yml:22:7 + +Add a top-level permission so this identity can access deployed files and resources: + permissions: + - service_principal_name: [UUID] + level: CAN_VIEW + Recommendation: permissions section should explicitly include the current deployment identity '[USERNAME]' or one of its groups If it is not included, CAN_MANAGE permissions are only applied if the present identity is used to deploy. @@ -45,6 +61,14 @@ To undo the migration, remove [TEST_TMP_DIR]/.databricks/bundle/production/resou >>> print_state.py >>> DATABRICKS_BUNDLE_ENGINE= [CLI] bundle plan +Warning: run_as identity "[UUID]" is not in bundle top-level permissions + in databricks.yml:22:7 + +Add a top-level permission so this identity can access deployed files and resources: + permissions: + - service_principal_name: [UUID] + level: CAN_VIEW + Recommendation: permissions section should explicitly include the current deployment identity '[USERNAME]' or one of its groups If it is not included, CAN_MANAGE permissions are only applied if the present identity is used to deploy. @@ -60,6 +84,14 @@ See https://docs.databricks.com/dev-tools/bundles/permissions.html to learn more Plan: 0 to add, 0 to change, 0 to delete, 2 unchanged >>> DATABRICKS_BUNDLE_ENGINE= [CLI] bundle plan -o json +Warning: run_as identity "[UUID]" is not in bundle top-level permissions + in databricks.yml:22:7 + +Add a top-level permission so this identity can access deployed files and resources: + permissions: + - service_principal_name: [UUID] + level: CAN_VIEW + Recommendation: permissions section should explicitly include the current deployment identity '[USERNAME]' or one of its groups If it is not included, CAN_MANAGE permissions are only applied if the present identity is used to deploy. @@ -74,6 +106,14 @@ See https://docs.databricks.com/dev-tools/bundles/permissions.html to learn more >>> DATABRICKS_BUNDLE_ENGINE= [CLI] bundle destroy --auto-approve +Warning: run_as identity "[UUID]" is not in bundle top-level permissions + in databricks.yml:22:7 + +Add a top-level permission so this identity can access deployed files and resources: + permissions: + - service_principal_name: [UUID] + level: CAN_VIEW + Recommendation: permissions section should explicitly include the current deployment identity '[USERNAME]' or one of its groups If it is not included, CAN_MANAGE permissions are only applied if the present identity is used to deploy. diff --git a/acceptance/bundle/run_as/allowed/regular_user/output.txt b/acceptance/bundle/run_as/allowed/regular_user/output.txt index aff3856965a..eba8238b68f 100644 --- a/acceptance/bundle/run_as/allowed/regular_user/output.txt +++ b/acceptance/bundle/run_as/allowed/regular_user/output.txt @@ -1,9 +1,9 @@ >>> [CLI] bundle validate -o json -Warning: run_as identity "my_service_principal" is not in top-level permissions for bundle files +Warning: run_as identity "my_service_principal" is not in bundle top-level permissions in databricks.yml:5:3 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: my_service_principal level: CAN_VIEW @@ -46,10 +46,10 @@ Add a top-level permission so this identity can read deployed files: } >>> [CLI] bundle validate -o json -t development -Warning: run_as identity "my_user_name" is not in top-level permissions for bundle files +Warning: run_as identity "my_user_name" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: my_user_name level: CAN_VIEW diff --git a/acceptance/bundle/run_as/allowed/service_principal/output.txt b/acceptance/bundle/run_as/allowed/service_principal/output.txt index aff3856965a..eba8238b68f 100644 --- a/acceptance/bundle/run_as/allowed/service_principal/output.txt +++ b/acceptance/bundle/run_as/allowed/service_principal/output.txt @@ -1,9 +1,9 @@ >>> [CLI] bundle validate -o json -Warning: run_as identity "my_service_principal" is not in top-level permissions for bundle files +Warning: run_as identity "my_service_principal" is not in bundle top-level permissions in databricks.yml:5:3 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: my_service_principal level: CAN_VIEW @@ -46,10 +46,10 @@ Add a top-level permission so this identity can read deployed files: } >>> [CLI] bundle validate -o json -t development -Warning: run_as identity "my_user_name" is not in top-level permissions for bundle files +Warning: run_as identity "my_user_name" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: my_user_name level: CAN_VIEW diff --git a/acceptance/bundle/run_as/dashboard_embed/output.txt b/acceptance/bundle/run_as/dashboard_embed/output.txt index 58a182936c0..c34d8c8ce0d 100644 --- a/acceptance/bundle/run_as/dashboard_embed/output.txt +++ b/acceptance/bundle/run_as/dashboard_embed/output.txt @@ -1,9 +1,9 @@ >>> errcode [CLI] bundle validate --var embed=false -Warning: run_as identity "sp-name" is not in top-level permissions for bundle files +Warning: run_as identity "sp-name" is not in bundle top-level permissions in databricks.yml:5:3 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: sp-name level: CAN_VIEW diff --git a/acceptance/bundle/run_as/empty_override/output.txt b/acceptance/bundle/run_as/empty_override/output.txt index 78e4fc53292..2ff5664cc30 100644 --- a/acceptance/bundle/run_as/empty_override/output.txt +++ b/acceptance/bundle/run_as/empty_override/output.txt @@ -1,7 +1,7 @@ -Warning: run_as identity "my_user_name" is not in top-level permissions for bundle files +Warning: run_as identity "my_user_name" is not in bundle top-level permissions in databricks.yml:5:3 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: my_user_name level: CAN_VIEW diff --git a/acceptance/bundle/run_as/output.txt b/acceptance/bundle/run_as/output.txt index 73e4ba63b7c..9307f9c122c 100644 --- a/acceptance/bundle/run_as/output.txt +++ b/acceptance/bundle/run_as/output.txt @@ -8,10 +8,10 @@ pipelines.pipeline_three: {"user_name":"user_override"} pipelines.pipeline_two: {"service_principal_name":"sp_override"} >>> [CLI] bundle validate -o json -t with_user_run_as -Warning: run_as identity "user_base" is not in top-level permissions for bundle files +Warning: run_as identity "user_base" is not in bundle top-level permissions in databricks.yml:39:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: user_base level: CAN_VIEW @@ -24,10 +24,10 @@ pipelines.pipeline_three: {"user_name":"user_override"} pipelines.pipeline_two: {"service_principal_name":"sp_override"} >>> [CLI] bundle validate -o json -t with_sp_run_as -Warning: run_as identity "sp_base" is not in top-level permissions for bundle files +Warning: run_as identity "sp_base" is not in bundle top-level permissions in databricks.yml:43:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: sp_base level: CAN_VIEW diff --git a/acceptance/bundle/run_as/pipelines/regular_user/output.txt b/acceptance/bundle/run_as/pipelines/regular_user/output.txt index e6855cc663b..00db450fdae 100644 --- a/acceptance/bundle/run_as/pipelines/regular_user/output.txt +++ b/acceptance/bundle/run_as/pipelines/regular_user/output.txt @@ -25,10 +25,10 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_user_name_different >>> [CLI] bundle validate -t t_user_name_different -Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "different@databricks.com" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: different@databricks.com level: CAN_VIEW @@ -42,10 +42,10 @@ Workspace: Found 1 warning >>> [CLI] bundle plan -t t_user_name_different -Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "different@databricks.com" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: different@databricks.com level: CAN_VIEW @@ -54,20 +54,20 @@ create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged -Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "different@databricks.com" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: different@databricks.com level: CAN_VIEW >>> [CLI] bundle deploy -t t_user_name_different -Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "different@databricks.com" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: different@databricks.com level: CAN_VIEW @@ -80,10 +80,10 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_service_principal_name >>> [CLI] bundle validate -t t_service_principal_name -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:10:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: [UUID] level: CAN_VIEW @@ -97,10 +97,10 @@ Workspace: Found 1 warning >>> [CLI] bundle plan -t t_service_principal_name -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:10:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: [UUID] level: CAN_VIEW @@ -109,20 +109,20 @@ create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:10:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: [UUID] level: CAN_VIEW >>> [CLI] bundle deploy -t t_service_principal_name -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:10:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: [UUID] level: CAN_VIEW @@ -135,10 +135,10 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_service_principal_name_different >>> [CLI] bundle validate -t t_service_principal_name_different -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:16:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: [UUID] level: CAN_VIEW @@ -152,10 +152,10 @@ Workspace: Found 1 warning >>> [CLI] bundle plan -t t_service_principal_name_different -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:16:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: [UUID] level: CAN_VIEW @@ -164,20 +164,20 @@ create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:16:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: [UUID] level: CAN_VIEW >>> [CLI] bundle deploy -t t_service_principal_name_different -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:16:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: [UUID] level: CAN_VIEW diff --git a/acceptance/bundle/run_as/pipelines/service_principal/output.txt b/acceptance/bundle/run_as/pipelines/service_principal/output.txt index f6bd6858a44..29eee9029c6 100644 --- a/acceptance/bundle/run_as/pipelines/service_principal/output.txt +++ b/acceptance/bundle/run_as/pipelines/service_principal/output.txt @@ -2,10 +2,10 @@ === run_as should succeed in all cases\nProcessing target: t_user_name >>> [CLI] bundle validate -t t_user_name -Warning: run_as identity "tester@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "tester@databricks.com" is not in bundle top-level permissions in databricks.yml:7:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: tester@databricks.com level: CAN_VIEW @@ -19,10 +19,10 @@ Workspace: Found 1 warning >>> [CLI] bundle plan -t t_user_name -Warning: run_as identity "tester@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "tester@databricks.com" is not in bundle top-level permissions in databricks.yml:7:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: tester@databricks.com level: CAN_VIEW @@ -31,20 +31,20 @@ create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged -Warning: run_as identity "tester@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "tester@databricks.com" is not in bundle top-level permissions in databricks.yml:7:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: tester@databricks.com level: CAN_VIEW >>> [CLI] bundle deploy -t t_user_name -Warning: run_as identity "tester@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "tester@databricks.com" is not in bundle top-level permissions in databricks.yml:7:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: tester@databricks.com level: CAN_VIEW @@ -57,10 +57,10 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_user_name_different >>> [CLI] bundle validate -t t_user_name_different -Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "different@databricks.com" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: different@databricks.com level: CAN_VIEW @@ -74,10 +74,10 @@ Workspace: Found 1 warning >>> [CLI] bundle plan -t t_user_name_different -Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "different@databricks.com" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: different@databricks.com level: CAN_VIEW @@ -86,20 +86,20 @@ create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged -Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "different@databricks.com" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: different@databricks.com level: CAN_VIEW >>> [CLI] bundle deploy -t t_user_name_different -Warning: run_as identity "different@databricks.com" is not in top-level permissions for bundle files +Warning: run_as identity "different@databricks.com" is not in bundle top-level permissions in databricks.yml:13:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: different@databricks.com level: CAN_VIEW @@ -135,10 +135,10 @@ Resources: 2 created, 0 changed, 0 deleted, 0 unchanged \nProcessing target: t_service_principal_name_different >>> [CLI] bundle validate -t t_service_principal_name_different -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:16:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: [UUID] level: CAN_VIEW @@ -152,10 +152,10 @@ Workspace: Found 1 warning >>> [CLI] bundle plan -t t_service_principal_name_different -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:16:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: [UUID] level: CAN_VIEW @@ -164,20 +164,20 @@ create pipelines.nyc_taxi_pipeline create pipelines.nyc_taxi_pipeline.permissions Plan: 2 to add, 0 to change, 0 to delete, 0 unchanged -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:16:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: [UUID] level: CAN_VIEW >>> [CLI] bundle deploy -t t_service_principal_name_different -Warning: run_as identity "[UUID]" is not in top-level permissions for bundle files +Warning: run_as identity "[UUID]" is not in bundle top-level permissions in databricks.yml:16:7 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: [UUID] level: CAN_VIEW diff --git a/acceptance/bundle/run_as/pipelines_legacy/output.txt b/acceptance/bundle/run_as/pipelines_legacy/output.txt index f9a6faeb160..d0debfb9b85 100644 --- a/acceptance/bundle/run_as/pipelines_legacy/output.txt +++ b/acceptance/bundle/run_as/pipelines_legacy/output.txt @@ -4,10 +4,10 @@ Warning: You are using the legacy mode of run_as. The support for this mode is e at experimental.use_legacy_run_as in databricks.yml:8:22 -Warning: run_as identity "my_service_principal" is not in top-level permissions for bundle files +Warning: run_as identity "my_service_principal" is not in bundle top-level permissions in databricks.yml:5:3 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: my_service_principal level: CAN_VIEW diff --git a/acceptance/bundle/telemetry/deploy-experimental/output.txt b/acceptance/bundle/telemetry/deploy-experimental/output.txt index 0a6d09e88b8..d58493a2afb 100644 --- a/acceptance/bundle/telemetry/deploy-experimental/output.txt +++ b/acceptance/bundle/telemetry/deploy-experimental/output.txt @@ -4,10 +4,10 @@ Warning: You are using the legacy mode of run_as. The support for this mode is e at experimental.use_legacy_run_as in databricks.yml:5:22 -Warning: run_as identity "abcd" is not in top-level permissions for bundle files +Warning: run_as identity "abcd" is not in bundle top-level permissions in databricks.yml:8:3 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - user_name: abcd level: CAN_VIEW diff --git a/acceptance/bundle/telemetry/deploy-run-as/output.txt b/acceptance/bundle/telemetry/deploy-run-as/output.txt index 6f876faf7eb..b9f84a3d3a6 100644 --- a/acceptance/bundle/telemetry/deploy-run-as/output.txt +++ b/acceptance/bundle/telemetry/deploy-run-as/output.txt @@ -1,9 +1,9 @@ >>> [CLI] bundle deploy -Warning: run_as identity "sp_test" is not in top-level permissions for bundle files +Warning: run_as identity "sp_test" is not in bundle top-level permissions in databricks.yml:5:3 -Add a top-level permission so this identity can read deployed files: +Add a top-level permission so this identity can access deployed files and resources: permissions: - service_principal_name: sp_test level: CAN_VIEW diff --git a/bundle/permissions/permission_diagnostics.go b/bundle/permissions/permission_diagnostics.go index e03f4fa11e5..fce66c5b8ce 100644 --- a/bundle/permissions/permission_diagnostics.go +++ b/bundle/permissions/permission_diagnostics.go @@ -31,7 +31,7 @@ func (m *permissionDiagnostics) Name() string { } func (m *permissionDiagnostics) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics { - diags := runAsFileAccessDiagnostics(b) + diags := runAsAccessDiagnostics(b) // Only recommend deployment-identity access when top-level permissions are explicit. if len(b.Config.Permissions) == 0 { return diags @@ -66,7 +66,7 @@ func (m *permissionDiagnostics) Apply(ctx context.Context, b *bundle.Bundle) dia }) } -func runAsFileAccessDiagnostics(b *bundle.Bundle) diag.Diagnostics { +func runAsAccessDiagnostics(b *bundle.Bundle) diag.Diagnostics { runAs := b.Config.RunAs if runAs == nil { return nil @@ -113,8 +113,8 @@ func runAsFileAccessDiagnostics(b *bundle.Bundle) diag.Diagnostics { return diag.Diagnostics{{ Severity: diag.Warning, - Summary: fmt.Sprintf("run_as identity %q is not in top-level permissions for bundle files", identity), - Detail: fmt.Sprintf("Add a top-level permission so this identity can read deployed files:\n"+ + Summary: fmt.Sprintf("run_as identity %q is not in bundle top-level permissions", identity), + Detail: fmt.Sprintf("Add a top-level permission so this identity can access deployed files and resources:\n"+ " permissions:\n"+ " - %s: %s\n"+ " level: CAN_VIEW", identityType, identity), diff --git a/bundle/permissions/permission_diagnostics_test.go b/bundle/permissions/permission_diagnostics_test.go index 8093249593f..f4c6fdb3984 100644 --- a/bundle/permissions/permission_diagnostics_test.go +++ b/bundle/permissions/permission_diagnostics_test.go @@ -49,7 +49,7 @@ func TestPermissionDiagnosticsApplyFail(t *testing.T) { require.Contains(t, diags[0].Summary, expectedMsg) } -func TestPermissionDiagnosticsRunAsFileAccess(t *testing.T) { +func TestPermissionDiagnosticsRunAsAccess(t *testing.T) { deployerPermission := resources.Permission{Level: "CAN_MANAGE", UserName: "testuser@databricks.com"} servicePrincipalName := "aaaaaaaa-bbbb-4ccc-dddd-eeeeeeeeeeee" servicePrincipal := jobs.JobRunAs{ServicePrincipalName: servicePrincipalName} @@ -67,26 +67,26 @@ func TestPermissionDiagnosticsRunAsFileAccess(t *testing.T) { { name: "service principal without permissions", runAs: servicePrincipal, - wantSummary: "is not in top-level permissions for bundle files", + wantSummary: "is not in bundle top-level permissions", wantSuggestion: "service_principal_name: " + servicePrincipalName + "\n level: CAN_VIEW", }, { name: "user without permissions", runAs: jobs.JobRunAs{UserName: "runner@example.test"}, - wantSummary: "is not in top-level permissions for bundle files", + wantSummary: "is not in bundle top-level permissions", wantSuggestion: "user_name: runner@example.test\n level: CAN_VIEW", }, { name: "group without permissions", runAs: jobs.JobRunAs{GroupName: "runners"}, - wantSummary: "is not in top-level permissions for bundle files", + wantSummary: "is not in bundle top-level permissions", wantSuggestion: "group_name: runners\n level: CAN_VIEW", }, { name: "unrelated group permission", runAs: servicePrincipal, permissions: []resources.Permission{deployerPermission, {Level: "CAN_VIEW", GroupName: "runners"}}, - wantSummary: "is not in top-level permissions for bundle files", + wantSummary: "is not in bundle top-level permissions", wantSuggestion: "service_principal_name: " + servicePrincipalName, }, { @@ -137,7 +137,7 @@ func TestPermissionDiagnosticsRunAsFileAccess(t *testing.T) { name: "immutable bundle without permissions", runAs: servicePrincipal, syncMode: config.SyncModeImmutable, - wantSummary: "is not in top-level permissions for bundle files", + wantSummary: "is not in bundle top-level permissions", wantSuggestion: "level: CAN_VIEW", }, { @@ -164,7 +164,7 @@ func TestPermissionDiagnosticsRunAsFileAccess(t *testing.T) { deployment.Config.Workspace.SyncMode = testCase.syncMode deployment.Config.Workspace.FilePath = testCase.filePath if testCase.currentUser != "" { - deployment.Config.Workspace.CurrentUser.User.UserName = testCase.currentUser + deployment.Config.Workspace.CurrentUser.UserName = testCase.currentUser } diags := bundle.Apply(t.Context(), deployment, permissions.PermissionDiagnostics())