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 {
}
func ApplyWorkspaceRootPermissions ( ) bundle . Mutator {
return & workspaceRootPermissions { }
}
// Apply implements bundle.Mutator.
2024-03-25 14:18:47 +00:00
func ( * workspaceRootPermissions ) Apply ( ctx context . Context , b * bundle . Bundle ) diag . Diagnostics {
2024-10-10 11:52:13 +00:00
diags := checkWorkspaceRootPermissions ( b )
if len ( diags ) > 0 {
return diags
}
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
}
func ( * workspaceRootPermissions ) Name ( ) string {
return "ApplyWorkspaceRootPermissions"
}
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
// checkWorkspaceRootPermissions checks that if permissions are set for the workspace root, and workspace root starts with /Workspace/Shared, then permissions should be set for group: users
func checkWorkspaceRootPermissions ( b * bundle . Bundle ) diag . Diagnostics {
var diags diag . Diagnostics
2024-10-10 13:18:40 +00:00
if ! strings . HasPrefix ( b . Config . Workspace . RootPath , "/Workspace/Shared/" ) {
2024-10-10 11:52:13 +00:00
return nil
}
allUsers := false
for _ , p := range b . Config . Permissions {
if p . GroupName == "users" && p . Level == CAN_MANAGE {
allUsers = true
}
}
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-10 11:52:13 +00:00
Detail : "bundle is configured to /Workspace/Shared, which will give read/write access to all users. If all users should have access, 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 /Users/<username or principal name>" ,
} )
}
return diags
}