diff --git a/.nextchanges/bundles/secret-scope-invalid-permission-level.md b/.nextchanges/bundles/secret-scope-invalid-permission-level.md new file mode 100644 index 00000000000..4e1a6c86cd1 --- /dev/null +++ b/.nextchanges/bundles/secret-scope-invalid-permission-level.md @@ -0,0 +1 @@ +Warn on invalid `secret_scopes` permission levels (`READ`, `WRITE`, `MANAGE`); fail under `bundle validate --strict`. diff --git a/acceptance/bundle/validate/secret_scope_invalid_permission_level/databricks.yml b/acceptance/bundle/validate/secret_scope_invalid_permission_level/databricks.yml new file mode 100644 index 00000000000..b80dc842d6e --- /dev/null +++ b/acceptance/bundle/validate/secret_scope_invalid_permission_level/databricks.yml @@ -0,0 +1,18 @@ +bundle: + name: test-bundle + +resources: + secret_scopes: + bad_levels: + name: test-scope-bad-levels + permissions: + # YAML int is coerced to string; must still fail enum validation. + - level: 12 + group_name: users + - level: fuzz_badlevel + service_principal_name: 12345678-1234-1234-1234-123456789abc + valid: + name: test-scope-valid + permissions: + - level: READ + group_name: users diff --git a/acceptance/bundle/validate/secret_scope_invalid_permission_level/out.test.toml b/acceptance/bundle/validate/secret_scope_invalid_permission_level/out.test.toml new file mode 100644 index 00000000000..98ea5040486 --- /dev/null +++ b/acceptance/bundle/validate/secret_scope_invalid_permission_level/out.test.toml @@ -0,0 +1,2 @@ +Cloud = false +EnvMatrix.DATABRICKS_BUNDLE_ENGINE = ["terraform", "direct"] diff --git a/acceptance/bundle/validate/secret_scope_invalid_permission_level/output.txt b/acceptance/bundle/validate/secret_scope_invalid_permission_level/output.txt new file mode 100644 index 00000000000..ce3a523536f --- /dev/null +++ b/acceptance/bundle/validate/secret_scope_invalid_permission_level/output.txt @@ -0,0 +1,31 @@ + +>>> [CLI] bundle validate +Warning: invalid value "12" for enum field. Valid values are [READ WRITE MANAGE] + at resources.secret_scopes.bad_levels.permissions[0].level + +Warning: invalid value "fuzz_badlevel" for enum field. Valid values are [READ WRITE MANAGE] + at resources.secret_scopes.bad_levels.permissions[1].level + +Name: test-bundle +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/test-bundle/default + +Found 2 warnings + +>>> [CLI] bundle validate --strict +Warning: invalid value "12" for enum field. Valid values are [READ WRITE MANAGE] + at resources.secret_scopes.bad_levels.permissions[0].level + +Warning: invalid value "fuzz_badlevel" for enum field. Valid values are [READ WRITE MANAGE] + at resources.secret_scopes.bad_levels.permissions[1].level + +Name: test-bundle +Target: default +Workspace: + User: [USERNAME] + Path: /Workspace/Users/[USERNAME]/.bundle/test-bundle/default + +Found 2 warnings +Error: 2 warnings were found. Warnings are not allowed in strict mode diff --git a/acceptance/bundle/validate/secret_scope_invalid_permission_level/script b/acceptance/bundle/validate/secret_scope_invalid_permission_level/script new file mode 100644 index 00000000000..9bfb2b86d2c --- /dev/null +++ b/acceptance/bundle/validate/secret_scope_invalid_permission_level/script @@ -0,0 +1,3 @@ +# Invalid levels warn (same as other enum fields); --strict must fail. +trace $CLI bundle validate +musterr trace $CLI bundle validate --strict diff --git a/bundle/config/resources/secret_scope.go b/bundle/config/resources/secret_scope.go index 702ee914f8a..30d0ebd901d 100644 --- a/bundle/config/resources/secret_scope.go +++ b/bundle/config/resources/secret_scope.go @@ -13,10 +13,19 @@ type SecretScopePermissionLevel string const ( SecretScopePermissionLevelRead SecretScopePermissionLevel = "READ" - SecretScopePermissionLevelManage SecretScopePermissionLevel = "MANAGE" SecretScopePermissionLevelWrite SecretScopePermissionLevel = "WRITE" + SecretScopePermissionLevelManage SecretScopePermissionLevel = "MANAGE" ) +// Values enables generated enum validation. Order matches privilege rank (READ < WRITE < MANAGE). +func (SecretScopePermissionLevel) Values() []SecretScopePermissionLevel { + return []SecretScopePermissionLevel{ + SecretScopePermissionLevelRead, + SecretScopePermissionLevelWrite, + SecretScopePermissionLevelManage, + } +} + // SecretScopePermission holds the permission level setting for a single principal. // Multiple of these can be defined on any secret scope. // Secret scopes permissions are mapped to Secret ACLs diff --git a/bundle/internal/validation/generated/enum_fields.go b/bundle/internal/validation/generated/enum_fields.go index 5dadaece243..ecdef3afa24 100644 --- a/bundle/internal/validation/generated/enum_fields.go +++ b/bundle/internal/validation/generated/enum_fields.go @@ -233,7 +233,8 @@ var EnumFields = map[string][]string{ "resources.schemas.*.grants[*].privileges[*]": {"ACCESS", "ALL_PRIVILEGES", "APPLY_TAG", "BROWSE", "CREATE", "CREATE_CATALOG", "CREATE_CLEAN_ROOM", "CREATE_CONNECTION", "CREATE_EXTERNAL_LOCATION", "CREATE_EXTERNAL_TABLE", "CREATE_EXTERNAL_VOLUME", "CREATE_FOREIGN_CATALOG", "CREATE_FOREIGN_SECURABLE", "CREATE_FUNCTION", "CREATE_MANAGED_STORAGE", "CREATE_MATERIALIZED_VIEW", "CREATE_MODEL", "CREATE_PROVIDER", "CREATE_RECIPIENT", "CREATE_SCHEMA", "CREATE_SERVICE_CREDENTIAL", "CREATE_SHARE", "CREATE_STORAGE_CREDENTIAL", "CREATE_TABLE", "CREATE_VIEW", "CREATE_VOLUME", "EXECUTE", "EXECUTE_CLEAN_ROOM_TASK", "EXTERNAL_USE_SCHEMA", "MANAGE", "MANAGE_ALLOWLIST", "MODIFY", "MODIFY_CLEAN_ROOM", "READ_FILES", "READ_METADATA", "READ_PRIVATE_FILES", "READ_VOLUME", "REFRESH", "SELECT", "SET_SHARE_PERMISSION", "USAGE", "USE_CATALOG", "USE_CONNECTION", "USE_MARKETPLACE_ASSETS", "USE_PROVIDER", "USE_RECIPIENT", "USE_SCHEMA", "USE_SHARE", "WRITE_FILES", "WRITE_PRIVATE_FILES", "WRITE_VOLUME"}, - "resources.secret_scopes.*.backend_type": {"AZURE_KEYVAULT", "DATABRICKS"}, + "resources.secret_scopes.*.backend_type": {"AZURE_KEYVAULT", "DATABRICKS"}, + "resources.secret_scopes.*.permissions[*].level": {"READ", "WRITE", "MANAGE"}, "resources.secrets.*.grants[*].privileges[*]": {"ACCESS", "ALL_PRIVILEGES", "APPLY_TAG", "BROWSE", "CREATE", "CREATE_CATALOG", "CREATE_CLEAN_ROOM", "CREATE_CONNECTION", "CREATE_EXTERNAL_LOCATION", "CREATE_EXTERNAL_TABLE", "CREATE_EXTERNAL_VOLUME", "CREATE_FOREIGN_CATALOG", "CREATE_FOREIGN_SECURABLE", "CREATE_FUNCTION", "CREATE_MANAGED_STORAGE", "CREATE_MATERIALIZED_VIEW", "CREATE_MODEL", "CREATE_PROVIDER", "CREATE_RECIPIENT", "CREATE_SCHEMA", "CREATE_SERVICE_CREDENTIAL", "CREATE_SHARE", "CREATE_STORAGE_CREDENTIAL", "CREATE_TABLE", "CREATE_VIEW", "CREATE_VOLUME", "EXECUTE", "EXECUTE_CLEAN_ROOM_TASK", "EXTERNAL_USE_SCHEMA", "MANAGE", "MANAGE_ALLOWLIST", "MODIFY", "MODIFY_CLEAN_ROOM", "READ_FILES", "READ_METADATA", "READ_PRIVATE_FILES", "READ_VOLUME", "REFRESH", "SELECT", "SET_SHARE_PERMISSION", "USAGE", "USE_CATALOG", "USE_CONNECTION", "USE_MARKETPLACE_ASSETS", "USE_PROVIDER", "USE_RECIPIENT", "USE_SCHEMA", "USE_SHARE", "WRITE_FILES", "WRITE_PRIVATE_FILES", "WRITE_VOLUME"},