2023-11-13 11:29:40 +00:00
package permissions
import (
"context"
"fmt"
2024-10-10 11:52:13 +00:00
"strings"
2023-11-13 11:29:40 +00:00
"github.com/databricks/cli/bundle"
2024-03-25 14:18:47 +00:00
"github.com/databricks/cli/libs/diag"
2023-11-13 11:29:40 +00:00
"github.com/databricks/databricks-sdk-go/service/workspace"
)
type workspaceRootPermissions struct {
}
2024-10-16 09:14:01 +00:00
type validateSharedRootPermissions struct {
}
2023-11-13 11:29:40 +00:00
func ApplyWorkspaceRootPermissions ( ) bundle . Mutator {
return & workspaceRootPermissions { }
}
2024-10-16 09:14:01 +00:00
func ( * workspaceRootPermissions ) Name ( ) string {
return "ApplyWorkspaceRootPermissions"
}
2024-10-10 11:52:13 +00:00
2024-10-16 09:14:01 +00:00
func ValidateSharedRootPermissions ( ) bundle . Mutator {
return & validateSharedRootPermissions { }
}
2024-10-10 11:52:13 +00:00
2024-10-16 09:14:01 +00:00
func ( * validateSharedRootPermissions ) Name ( ) string {
return "ValidateSharedRootPermissions"
}
// Apply implements bundle.Mutator.
func ( * workspaceRootPermissions ) Apply ( ctx context . Context , b * bundle . Bundle ) diag . Diagnostics {
2023-11-13 11:29:40 +00:00
err := giveAccessForWorkspaceRoot ( ctx , b )
if err != nil {
2024-03-25 14:18:47 +00:00
return diag . FromErr ( err )
2023-11-13 11:29:40 +00:00
}
return nil
}
2024-10-16 09:14:01 +00:00
func ( * validateSharedRootPermissions ) Apply ( ctx context . Context , b * bundle . Bundle ) diag . Diagnostics {
if isWorkspaceSharedRoot ( b . Config . Workspace . RootPath ) {
return isUsersGroupPermissionSet ( b )
}
return nil
2023-11-13 11:29:40 +00:00
}
func giveAccessForWorkspaceRoot ( ctx context . Context , b * bundle . Bundle ) error {
permissions := make ( [ ] workspace . WorkspaceObjectAccessControlRequest , 0 )
for _ , p := range b . Config . Permissions {
level , err := getWorkspaceObjectPermissionLevel ( p . Level )
if err != nil {
return err
}
permissions = append ( permissions , workspace . WorkspaceObjectAccessControlRequest {
GroupName : p . GroupName ,
UserName : p . UserName ,
ServicePrincipalName : p . ServicePrincipalName ,
PermissionLevel : level ,
} )
}
if len ( permissions ) == 0 {
return nil
}
w := b . WorkspaceClient ( ) . Workspace
obj , err := w . GetStatusByPath ( ctx , b . Config . Workspace . RootPath )
if err != nil {
return err
}
_ , err = w . UpdatePermissions ( ctx , workspace . WorkspaceObjectPermissionsRequest {
WorkspaceObjectId : fmt . Sprint ( obj . ObjectId ) ,
WorkspaceObjectType : "directories" ,
AccessControlList : permissions ,
} )
return err
}
func getWorkspaceObjectPermissionLevel ( bundlePermission string ) ( workspace . WorkspaceObjectPermissionLevel , error ) {
switch bundlePermission {
case CAN_MANAGE :
return workspace . WorkspaceObjectPermissionLevelCanManage , nil
case CAN_RUN :
return workspace . WorkspaceObjectPermissionLevelCanRun , nil
case CAN_VIEW :
return workspace . WorkspaceObjectPermissionLevelCanRead , nil
default :
return "" , fmt . Errorf ( "unsupported bundle permission level %s" , bundlePermission )
}
}
2024-10-10 11:52:13 +00:00
2024-10-14 09:05:16 +00:00
func isWorkspaceSharedRoot ( path string ) bool {
return strings . HasPrefix ( path , "/Workspace/Shared/" )
}
2024-10-16 09:14:01 +00:00
// isUsersGroupPermissionSet checks that top-level permissions set for bundle contain group_name: users with CAN_MANAGE permission.
func isUsersGroupPermissionSet ( b * bundle . Bundle ) diag . Diagnostics {
2024-10-10 11:52:13 +00:00
var diags diag . Diagnostics
allUsers := false
for _ , p := range b . Config . Permissions {
if p . GroupName == "users" && p . Level == CAN_MANAGE {
allUsers = true
2024-10-16 09:14:01 +00:00
break
2024-10-10 11:52:13 +00:00
}
}
if ! allUsers {
diags = diags . Append ( diag . Diagnostic {
Severity : diag . Warning ,
2024-10-10 13:21:50 +00:00
Summary : fmt . Sprintf ( "the bundle root path %s is writable by all workspace users" , b . Config . Workspace . RootPath ) ,
2024-10-14 09:05:55 +00:00
Detail : "The bundle is configured to use /Workspace/Shared, which will give read/write access to all users. If this is intentional, add CAN_MANAGE for 'group_name: users' permission to your bundle configuration. If the deployment should be restricted, move it to a restricted folder such as /Workspace/Users/<username or principal name>." ,
2024-10-10 11:52:13 +00:00
} )
}
return diags
}