databricks-cli/bundle/permissions/check.go

113 lines
3.3 KiB
Go
Raw Normal View History

2024-10-14 10:33:47 +00:00
package permissions
import (
"fmt"
"strings"
"github.com/databricks/cli/bundle/config/resources"
"github.com/databricks/cli/libs/diag"
"github.com/databricks/databricks-sdk-go/service/workspace"
)
type WorkspacePathPermissions struct {
Path string
Permissions []resources.Permission
}
2024-10-16 12:32:20 +00:00
func ObjectAclToResourcePermissions(path string, acl []workspace.WorkspaceObjectAccessControlResponse) *WorkspacePathPermissions {
2024-10-14 10:33:47 +00:00
permissions := make([]resources.Permission, 0)
for _, a := range acl {
// Skip the admin group because it's added to all resources by default.
if a.GroupName == "admin" {
continue
}
for _, pl := range a.AllPermissions {
permissions = append(permissions, resources.Permission{
2024-10-16 12:32:20 +00:00
Level: convertWorkspaceObjectPermissionLevel(pl.PermissionLevel),
2024-10-14 10:33:47 +00:00
GroupName: a.GroupName,
UserName: a.UserName,
ServicePrincipalName: a.ServicePrincipalName,
})
}
}
return &WorkspacePathPermissions{Permissions: permissions, Path: path}
}
func (p WorkspacePathPermissions) Compare(perms []resources.Permission) diag.Diagnostics {
var diags diag.Diagnostics
2024-10-16 12:32:20 +00:00
// Check the permissions in the bundle and see if they are all set in the workspace.
ok, missing := containsAll(perms, p.Permissions)
if !ok {
2024-10-14 10:33:47 +00:00
diags = diags.Append(diag.Diagnostic{
Severity: diag.Warning,
2024-10-16 12:32:20 +00:00
Summary: "permissions missing",
Detail: fmt.Sprintf("Following permissions set in the bundle but not set for workspace folder %s:\n%s", p.Path, toString(missing)),
2024-10-14 10:33:47 +00:00
})
}
2024-10-16 12:32:20 +00:00
// Check the permissions in the workspace and see if they are all set in the bundle.
ok, missing = containsAll(p.Permissions, perms)
if !ok {
diags = diags.Append(diag.Diagnostic{
Severity: diag.Warning,
Summary: "permissions missing",
Detail: fmt.Sprintf("Following permissions set for the workspace folder but not set for bundle %s:\n%s", p.Path, toString(missing)),
})
}
2024-10-14 10:33:47 +00:00
2024-10-16 12:32:20 +00:00
return diags
}
// containsAll checks if permA contains all permissions in permB.
func containsAll(permA []resources.Permission, permB []resources.Permission) (bool, []resources.Permission) {
missing := make([]resources.Permission, 0)
for _, a := range permA {
2024-10-14 10:33:47 +00:00
found := false
2024-10-16 12:32:20 +00:00
for _, b := range permB {
if a == b {
2024-10-14 10:33:47 +00:00
found = true
break
}
}
if !found {
2024-10-16 12:32:20 +00:00
missing = append(missing, a)
2024-10-14 10:33:47 +00:00
}
}
2024-10-16 12:32:20 +00:00
return len(missing) == 0, missing
}
2024-10-14 10:33:47 +00:00
2024-10-16 12:32:20 +00:00
// convertWorkspaceObjectPermissionLevel converts matching object permission levels to bundle ones.
// If there is no matching permission level, it returns permission level as is, for example, CAN_EDIT.
func convertWorkspaceObjectPermissionLevel(level workspace.WorkspaceObjectPermissionLevel) string {
switch level {
case workspace.WorkspaceObjectPermissionLevelCanRead:
return CAN_VIEW
default:
return string(level)
}
2024-10-14 10:33:47 +00:00
}
2024-10-16 12:32:20 +00:00
func toString(p []resources.Permission) string {
2024-10-14 10:33:47 +00:00
var sb strings.Builder
for _, perm := range p {
2024-10-16 12:32:20 +00:00
if perm.ServicePrincipalName != "" {
sb.WriteString(fmt.Sprintf("- level: %s\n service_principal_name: %s\n", perm.Level, perm.ServicePrincipalName))
continue
}
if perm.GroupName != "" {
sb.WriteString(fmt.Sprintf("- level: %s\n group_name: %s\n", perm.Level, perm.GroupName))
continue
}
if perm.UserName != "" {
sb.WriteString(fmt.Sprintf("- level: %s\n user_name: %s\n", perm.Level, perm.UserName))
continue
}
2024-10-14 10:33:47 +00:00
}
return sb.String()
}