Skip to content

Reject secret scope permissions with no principal - #6215

Merged
radakam merged 3 commits into
mainfrom
fix-secret-scope-permission-principal
Aug 17, 2026
Merged

Reject secret scope permissions with no principal#6215
radakam merged 3 commits into
mainfrom
fix-secret-scope-permission-principal

Conversation

@radakam

@radakamradakam commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Changes

Add errorForInvalidSecretScopePermissions to validate.Required(). Validate and deploy fail early with:

Error: secret scope permission principal is required
at resources.secret_scopes.<key>.permissions[0]
Set one of user_name, group_name or service_principal_name

Diagnostics point at the scope (ApplyBundlePermissions drops per-entry locations). sortDiagnostics ties on path when locations match.

Why

A secret scope permission with no principal passes bundle validate (only a type warning for wrong-typed values). Three shapes slip through: missing, empty-string, and wrong-typed principal (normalization warns and drops it).

Without this check, failure is late and engine-specific:

Direct — deploy fails in SecretScopeFixups before any //secrets calls:

Error: Failed to collapse permissions for secret scope
at resources.secret_scopes.no_principal
missing principal in permissions for secret scope "test-scope-no-principal"

Terraform — deploy succeeds and creates scopes plus ACLs with "principal": "". Destroy then fails and cannot clean up:

Error: cannot read secret acl: principal cannot be empty
with databricks_secret_acl.secret_acl_no_principal_0,
on bundle.tf.json line 30, in resource.databricks_secret_acl.secret_acl_no_principal_0:
30: },

Found by fuzz testing.

Tests

New acceptance test bundle/validate/secret_scope_required_principal covering the three bad shapes plus a valid one. Asserts early rejection and zero //secrets requests on deploy.

A secret scope permission that names no principal is accepted by
`bundle validate` today, but the backend rejects a secret ACL with an
empty principal. The direct engine only fails later while collapsing
permissions, and Terraform creates the scope before the ACL call fails,
leaving a partial deploy that `destroy` cannot clean up.
Reject the input at validation time so both engines fail early with a
located, actionable error. A principal of the wrong type counts as
missing: normalization only warns and drops the value, so the permission
would otherwise still reach the backend without a principal.
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 65171ea

Run: 31486274522

Env🔄​flaky💚​RECOVERED🙈​SKIP✅​pass🙈​skipTime
💚​aws linux4429411296:33
💚​aws windows4429611276:48
🔄​azure linux44428911297:12
💚​azure windows4429511276:36
🔄​gcp linux11529311298:30
💚​gcp windows1529611276:44
13 interesting tests: 5 flaky, 4 RECOVERED, 4 SKIP
Test Nameaws linuxaws windowsazure linuxazure windowsgcp linuxgcp windows
💚​TestAccept💚​R💚​R💚​R💚​R💚​R💚​R
🙈​TestAccept/bundle/invariant/no_drift🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/ssh/connection🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🔄​TestFsCpFileToFileFileNotOverwritten✅​p✅​p🔄​f✅​p✅​p✅​p
🔄​TestFsCpFileToFileFileNotOverwritten/uc-volumes_to_uc-volumes✅​p✅​p🔄​f✅​p✅​p✅​p
🔄​TestSyncNestedFolderSync✅​p✅​p✅​p✅​p🔄​f✅​p
🔄​TestFilerWorkspaceNotebook✅​p✅​p🔄​f✅​p✅​p✅​p
🔄​TestFilerWorkspaceNotebook/scalaJupyterNb.ipynb✅​p✅​p🔄​f✅​p✅​p✅​p
💚​TestFetchRepositoryInfoAPI_FromRepo💚​R💚​R💚​R💚​R🙈​S🙈​S
💚​TestFetchRepositoryInfoAPI_FromRepo/root💚​R💚​R💚​R💚​R
💚​TestFetchRepositoryInfoAPI_FromRepo/subdir💚​R💚​R💚​R💚​R
Top 6 slowest tests (at least 2 minutes):
durationenvtestname
6:40aws windowsTestAccept
6:36gcp windowsTestAccept
6:27azure windowsTestAccept
3:03azure linuxTestAccept
3:02gcp linuxTestAccept
3:01aws linuxTestAccept

@radakam
radakam marked this pull request as ready for review August 11, 2026 08:18
Drop dyn.MapByPattern in favor of iterating SecretScopes, and keep
comments to the non-obvious bits (wrong-typed drop, without-fix behavior).

@denikdenik left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks!

@radakam
radakam added this pull request to the merge queueAug 17, 2026
Merged via the queue into main with commit 1cfa6b6Aug 17, 2026
26 checks passed
@radakam
radakam deleted the fix-secret-scope-permission-principal branch August 17, 2026 11:23
@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Integration test report

Commit: 1cfa6b6

Run: 32024816334

Env❌​FAIL🟨​KNOWN🔄​flaky💚​RECOVERED🙈​SKIP✅​pass🙈​skipTime
❌​aws linux154221161954203:19
❌​aws windows944221102973249:43
❌​azure linux942221059991207:15
❌​azure windows911529991010233:40
❌​gcp linux918231043995224:50
❌​gcp windows912239881014236:46
38 interesting tests: 15 flaky, 15 FAIL, 4 KNOWN, 2 RECOVERED, 2 SKIP
Test Nameaws linuxaws windowsazure linuxazure windowsgcp linuxgcp windows
🟨​TestAccept🟨​K🟨​K🟨​K🟨​K🟨​K🟨​K
💚​TestAccept/bundle/invariant/no_drift💚​R💚​R💚​R💚​R💚​R💚​R
🔄​TestAccept/bundle/resources/dashboards/change-name✅​p✅​p✅​p✅​p🔄​f🔄​f
🔄​TestAccept/bundle/resources/dashboards/change-name/DATABRICKS_BUNDLE_ENGINE=terraform✅​p✅​p✅​p✅​p🔄​f🔄​f
❌​TestAccept/bundle/resources/dashboards/dataset-catalog-schema❌​F❌​F❌​F❌​F❌​F❌​F
❌​TestAccept/bundle/resources/dashboards/dataset-catalog-schema/DATABRICKS_BUNDLE_ENGINE=direct❌​F❌​F❌​F❌​F❌​F❌​F
❌​TestAccept/bundle/resources/dashboards/dataset-catalog-schema/DATABRICKS_BUNDLE_ENGINE=terraform❌​F❌​F❌​F❌​F❌​F❌​F
❌​TestAccept/bundle/resources/dashboards/delete-trashed-out-of-band❌​F❌​F❌​F❌​F❌​F❌​F
❌​TestAccept/bundle/resources/dashboards/delete-trashed-out-of-band/DATABRICKS_BUNDLE_ENGINE=direct❌​F❌​F❌​F❌​F❌​F❌​F
❌​TestAccept/bundle/resources/dashboards/delete-trashed-out-of-band/DATABRICKS_BUNDLE_ENGINE=terraform❌​F❌​F❌​F❌​F❌​F❌​F
❌​TestAccept/bundle/resources/dashboards/simple❌​F❌​F❌​F❌​F❌​F❌​F
❌​TestAccept/bundle/resources/dashboards/simple/DATABRICKS_BUNDLE_ENGINE=direct❌​F❌​F❌​F❌​F❌​F❌​F
❌​TestAccept/bundle/resources/dashboards/simple/DATABRICKS_BUNDLE_ENGINE=terraform❌​F❌​F❌​F❌​F❌​F❌​F
🔄​TestAccept/bundle/resources/dashboards/simple_syncroot✅​p🔄​f✅​p✅​p✅​p✅​p
🔄​TestAccept/bundle/resources/dashboards/simple_syncroot/DATABRICKS_BUNDLE_ENGINE=direct✅​p🔄​f✅​p✅​p✅​p✅​p
🔄​TestAccept/bundle/resources/grants/schemas/remove_all✅​p✅​p✅​p✅​p🔄​f✅​p
🔄​TestAccept/bundle/resources/grants/schemas/remove_all/DATABRICKS_BUNDLE_ENGINE=direct✅​p✅​p✅​p✅​p🔄​f✅​p
🔄​TestAccept/bundle/resources/grants/schemas/remove_principal✅​p✅​p✅​p✅​p🔄​f✅​p
🔄​TestAccept/bundle/resources/grants/schemas/remove_principal/DATABRICKS_BUNDLE_ENGINE=terraform✅​p✅​p✅​p✅​p🔄​f✅​p
❌​TestAccept/bundle/resources/permissions/dashboards/create❌​F✅​p✅​p✅​p🙈​s🙈​s
❌​TestAccept/bundle/resources/permissions/dashboards/create/DATABRICKS_BUNDLE_ENGINE=terraform❌​F✅​p✅​p✅​p
❌​TestAccept/bundle/resources/permissions/jobs/delete_one❌​F✅​p✅​p✅​p✅​p✅​p
❌​TestAccept/bundle/resources/permissions/jobs/delete_one/DATABRICKS_BUNDLE_ENGINE=direct❌​F✅​p✅​p✅​p✅​p✅​p
🔄​TestAccept/bundle/resources/postgres_branches/recreate✅​p🔄​f🙈​s🙈​s🙈​s🙈​s
🔄​TestAccept/bundle/resources/postgres_branches/recreate/DATABRICKS_BUNDLE_ENGINE=terraform✅​p🔄​f
🔄​TestAccept/bundle/resources/quality_monitors/change_output_schema_name✅​p✅​p✅​p✅​p🔄​f✅​p
🔄​TestAccept/bundle/resources/quality_monitors/change_output_schema_name/DATABRICKS_BUNDLE_ENGINE=direct✅​p✅​p✅​p✅​p🔄​f✅​p
❌​TestAccept/bundle/resources/secret_scopes/basic❌​F✅​p✅​p✅​p✅​p✅​p
❌​TestAccept/bundle/resources/secret_scopes/basic/DATABRICKS_BUNDLE_ENGINE=terraform❌​F✅​p✅​p✅​p✅​p✅​p
🔄​TestAccept/bundle/resources/secret_scopes/delete_scope✅​p✅​p🔄​f✅​p✅​p✅​p
🔄​TestAccept/bundle/resources/secret_scopes/delete_scope/DATABRICKS_BUNDLE_ENGINE=terraform✅​p✅​p🔄​f✅​p✅​p✅​p
💚​TestAccept/bundle/resources/vector_search_endpoints/drift/recreated_same_name💚​R💚​R💚​R💚​R💚​R💚​R
🙈​TestAccept/bundle/resources/vector_search_indexes/recreate/embedding_dimension🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🙈​TestAccept/ssh/connection🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🔄​TestSyncIncrementalFileOverwritesFolder✅​p✅​p✅​p🔄​f✅​p✅​p
🟨​TestFetchRepositoryInfoAPI_FromRepo🟨​K🟨​K🟨​K💚​R🙈​S🙈​S
🟨​TestFetchRepositoryInfoAPI_FromRepo/root🟨​K🟨​K🟨​K💚​R
🟨​TestFetchRepositoryInfoAPI_FromRepo/subdir🟨​K🟨​K🟨​K💚​R
Top 50 slowest tests (at least 2 minutes):
durationenvtestname
13:09gcp windowsTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
12:27gcp linuxTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
11:22azure windowsTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
9:31azure windowsTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
9:12aws windowsTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
9:02gcp windowsTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
8:41aws linuxTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
7:58gcp linuxTestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster_apply_policy_default_values.yml.tmpl/READPLAN=
7:54gcp linuxTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:52azure linuxTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:45gcp linuxTestAccept/bundle/invariant/destroy_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=
7:38gcp linuxTestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct
7:37gcp linuxTestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=direct
7:36aws linuxTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:32aws windowsTestAccept/bundle/resources/apps/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:20azure windowsTestAccept/bundle/resources/clusters/resize-terminated-fallback/DATABRICKS_BUNDLE_ENGINE=direct
7:08azure linuxTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
7:01aws linuxTestAccept/bundle/resources/clusters/deploy/simple/DATABRICKS_BUNDLE_ENGINE=direct
6:48gcp windowsTestAccept/bundle/resources/clusters/deploy/local_ssd_count/DATABRICKS_BUNDLE_ENGINE=direct
6:45aws linuxTestAccept/bundle/resources/clusters/lifecycle-started/DATABRICKS_BUNDLE_ENGINE=direct
6:42aws linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
6:41aws windowsTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=terraform
6:38azure linuxTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
6:02aws windowsTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
6:01gcp windowsTestAccept/bundle/resources/apps/lifecycle-started-omitted/DATABRICKS_BUNDLE_ENGINE=direct
6:00aws linuxTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=terraform
5:51aws windowsTestAccept/bundle/resources/postgres_endpoints/update_autoscaling/DATABRICKS_BUNDLE_ENGINE=terraform
5:46gcp windowsTestAccept/bundle/resources/apps/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
5:41aws windowsTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=direct
5:39aws linuxTestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=terraform
5:32gcp windowsTestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=secret.yml.tmpl/READPLAN=1
5:31gcp windowsTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
5:30gcp linuxTestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=terraform
5:29aws linuxTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=direct
5:28gcp windowsTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=direct
5:11gcp windowsTestAccept/bundle/deploy/spark-jar-task/DATABRICKS_BUNDLE_ENGINE=terraform
5:03aws linuxTestAccept/bundle/resources/registered_models/basic/DATABRICKS_BUNDLE_ENGINE=terraform
4:59gcp windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
4:59gcp linuxTestAccept/bundle/resources/apps/lifecycle-started-omitted/DATABRICKS_BUNDLE_ENGINE=direct
4:56aws linuxTestAccept/bundle/resources/clusters/deploy/data_security_mode/DATABRICKS_BUNDLE_ENGINE=direct
4:56gcp linuxTestAccept/bundle/resources/apps/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
4:51gcp linuxTestAccept/bundle/resources/clusters/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
4:49aws windowsTestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=job_pydabs_1000_tasks.yml.tmpl/READPLAN=
4:44azure linuxTestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=app.yml.tmpl/READPLAN=1
4:41gcp windowsTestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=schema_uppercase_name.yml.tmpl/READPLAN=1
4:39azure windowsTestAccept/bundle/resources/apps/lifecycle-started-toggle/DATABRICKS_BUNDLE_ENGINE=direct
4:37gcp linuxTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=no/PY=yes/READPLAN=
4:37aws windowsTestAccept/bundle/invariant/delete_idempotent/DATABRICKS_BUNDLE_ENGINE=direct/INPUT_CONFIG=cluster.yml.tmpl/READPLAN=1
4:37azure linuxTestAccept/bundle/config-remote-sync/multiple_resources/DATABRICKS_BUNDLE_ENGINE=direct
4:36gcp windowsTestAccept/bundle/resources/grants/schemas/all_privileges_coexist/DATABRICKS_BUNDLE_ENGINE=direct

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@radakam@eng-dev-ecosystem-bot@denik