mirror of https://github.com/databricks/cli.git
Merge 21799b5d83
into dedec58e41
This commit is contained in:
commit
e35f334f5b
|
@ -1,5 +1,7 @@
|
|||
package resources
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Permission holds the permission level setting for a single principal.
|
||||
// Multiple of these can be defined on any resource.
|
||||
type Permission struct {
|
||||
|
@ -9,3 +11,19 @@ type Permission struct {
|
|||
ServicePrincipalName string `json:"service_principal_name,omitempty"`
|
||||
GroupName string `json:"group_name,omitempty"`
|
||||
}
|
||||
|
||||
func (p Permission) String() string {
|
||||
if p.UserName != "" {
|
||||
return fmt.Sprintf("level: %s, user_name: %s", p.Level, p.UserName)
|
||||
}
|
||||
|
||||
if p.ServicePrincipalName != "" {
|
||||
return fmt.Sprintf("level: %s, service_principal_name: %s", p.Level, p.ServicePrincipalName)
|
||||
}
|
||||
|
||||
if p.GroupName != "" {
|
||||
return fmt.Sprintf("level: %s, group_name: %s", p.Level, p.GroupName)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("level: %s", p.Level)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
package validate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/databricks/cli/bundle"
|
||||
"github.com/databricks/cli/bundle/libraries"
|
||||
"github.com/databricks/cli/bundle/permissions"
|
||||
"github.com/databricks/cli/libs/diag"
|
||||
"github.com/databricks/databricks-sdk-go/apierr"
|
||||
"github.com/databricks/databricks-sdk-go/service/workspace"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
type folderPermissions struct {
|
||||
}
|
||||
|
||||
// Apply implements bundle.ReadOnlyMutator.
|
||||
func (f *folderPermissions) Apply(ctx context.Context, b bundle.ReadOnlyBundle) diag.Diagnostics {
|
||||
if len(b.Config().Permissions) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
rootPath := b.Config().Workspace.RootPath
|
||||
paths := []string{}
|
||||
if !libraries.IsVolumesPath(rootPath) {
|
||||
paths = append(paths, rootPath)
|
||||
}
|
||||
|
||||
if !strings.HasSuffix(rootPath, "/") {
|
||||
rootPath += "/"
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(b.Config().Workspace.ArtifactPath, rootPath) &&
|
||||
!libraries.IsVolumesPath(b.Config().Workspace.ArtifactPath) {
|
||||
paths = append(paths, b.Config().Workspace.ArtifactPath)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(b.Config().Workspace.FilePath, rootPath) &&
|
||||
!libraries.IsVolumesPath(b.Config().Workspace.FilePath) {
|
||||
paths = append(paths, b.Config().Workspace.FilePath)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(b.Config().Workspace.StatePath, rootPath) &&
|
||||
!libraries.IsVolumesPath(b.Config().Workspace.StatePath) {
|
||||
paths = append(paths, b.Config().Workspace.StatePath)
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(b.Config().Workspace.ResourcePath, rootPath) &&
|
||||
!libraries.IsVolumesPath(b.Config().Workspace.ResourcePath) {
|
||||
paths = append(paths, b.Config().Workspace.ResourcePath)
|
||||
}
|
||||
|
||||
var diags diag.Diagnostics
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
results := make([]diag.Diagnostics, len(paths))
|
||||
syncGroup := new(singleflight.Group)
|
||||
for i, p := range paths {
|
||||
g.Go(func() error {
|
||||
diags, err, _ := syncGroup.Do(p, func() (any, error) {
|
||||
diags := checkFolderPermission(ctx, b, p)
|
||||
return diags, nil
|
||||
})
|
||||
results[i] = diags.(diag.Diagnostics)
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
for _, r := range results {
|
||||
diags = diags.Extend(r)
|
||||
}
|
||||
|
||||
return diags
|
||||
}
|
||||
|
||||
func checkFolderPermission(ctx context.Context, b bundle.ReadOnlyBundle, folderPath string) diag.Diagnostics {
|
||||
w := b.WorkspaceClient().Workspace
|
||||
obj, err := getClosestExistingObject(ctx, w, folderPath)
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
objPermissions, err := w.GetPermissions(ctx, workspace.GetWorkspaceObjectPermissionsRequest{
|
||||
WorkspaceObjectId: fmt.Sprint(obj.ObjectId),
|
||||
WorkspaceObjectType: "directories",
|
||||
})
|
||||
if err != nil {
|
||||
return diag.FromErr(err)
|
||||
}
|
||||
|
||||
p := permissions.ObjectAclToResourcePermissions(folderPath, objPermissions.AccessControlList)
|
||||
return p.Compare(b.Config().Permissions)
|
||||
}
|
||||
|
||||
func getClosestExistingObject(ctx context.Context, w workspace.WorkspaceInterface, folderPath string) (*workspace.ObjectInfo, error) {
|
||||
for {
|
||||
obj, err := w.GetStatusByPath(ctx, folderPath)
|
||||
if err == nil {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
if !apierr.IsMissing(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
parent := path.Dir(folderPath)
|
||||
// If the parent is the same as the current folder, then we have reached the root
|
||||
if folderPath == parent {
|
||||
break
|
||||
}
|
||||
|
||||
folderPath = parent
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("folder %s and its parent folders do not exist", folderPath)
|
||||
}
|
||||
|
||||
// Name implements bundle.ReadOnlyMutator.
|
||||
func (f *folderPermissions) Name() string {
|
||||
return "validate:folder_permissions"
|
||||
}
|
||||
|
||||
// ValidateFolderPermissions validates that permissions for the folders in Workspace file system matches
|
||||
// the permissions in the top-level permissions section of the bundle.
|
||||
func ValidateFolderPermissions() bundle.ReadOnlyMutator {
|
||||
return &folderPermissions{}
|
||||
}
|
|
@ -0,0 +1,203 @@
|
|||
package validate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/bundle"
|
||||
"github.com/databricks/cli/bundle/config"
|
||||
"github.com/databricks/cli/bundle/config/resources"
|
||||
"github.com/databricks/cli/bundle/permissions"
|
||||
"github.com/databricks/cli/libs/diag"
|
||||
"github.com/databricks/databricks-sdk-go/apierr"
|
||||
"github.com/databricks/databricks-sdk-go/experimental/mocks"
|
||||
"github.com/databricks/databricks-sdk-go/service/workspace"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestValidateFolderPermissions(t *testing.T) {
|
||||
b := &bundle.Bundle{
|
||||
Config: config.Root{
|
||||
Workspace: config.Workspace{
|
||||
RootPath: "/Workspace/Users/foo@bar.com",
|
||||
ArtifactPath: "/Workspace/Users/foo@bar.com/artifacts",
|
||||
FilePath: "/Workspace/Users/foo@bar.com/files",
|
||||
StatePath: "/Workspace/Users/foo@bar.com/state",
|
||||
ResourcePath: "/Workspace/Users/foo@bar.com/resources",
|
||||
},
|
||||
Permissions: []resources.Permission{
|
||||
{Level: permissions.CAN_MANAGE, UserName: "foo@bar.com"},
|
||||
},
|
||||
},
|
||||
}
|
||||
m := mocks.NewMockWorkspaceClient(t)
|
||||
api := m.GetMockWorkspaceAPI()
|
||||
api.EXPECT().GetStatusByPath(mock.Anything, "/Workspace/Users/foo@bar.com").Return(nil, &apierr.APIError{
|
||||
StatusCode: 404,
|
||||
ErrorCode: "RESOURCE_DOES_NOT_EXIST",
|
||||
})
|
||||
api.EXPECT().GetStatusByPath(mock.Anything, "/Workspace/Users").Return(nil, &apierr.APIError{
|
||||
StatusCode: 404,
|
||||
ErrorCode: "RESOURCE_DOES_NOT_EXIST",
|
||||
})
|
||||
api.EXPECT().GetStatusByPath(mock.Anything, "/Workspace").Return(&workspace.ObjectInfo{
|
||||
ObjectId: 1234,
|
||||
}, nil)
|
||||
|
||||
api.EXPECT().GetPermissions(mock.Anything, workspace.GetWorkspaceObjectPermissionsRequest{
|
||||
WorkspaceObjectId: "1234",
|
||||
WorkspaceObjectType: "directories",
|
||||
}).Return(&workspace.WorkspaceObjectPermissions{
|
||||
ObjectId: "1234",
|
||||
AccessControlList: []workspace.WorkspaceObjectAccessControlResponse{
|
||||
{
|
||||
UserName: "foo@bar.com",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
b.SetWorkpaceClient(m.WorkspaceClient)
|
||||
rb := bundle.ReadOnly(b)
|
||||
|
||||
diags := bundle.ApplyReadOnly(context.Background(), rb, ValidateFolderPermissions())
|
||||
require.Empty(t, diags)
|
||||
}
|
||||
|
||||
func TestValidateFolderPermissionsDifferentCount(t *testing.T) {
|
||||
b := &bundle.Bundle{
|
||||
Config: config.Root{
|
||||
Workspace: config.Workspace{
|
||||
RootPath: "/Workspace/Users/foo@bar.com",
|
||||
ArtifactPath: "/Workspace/Users/foo@bar.com/artifacts",
|
||||
FilePath: "/Workspace/Users/foo@bar.com/files",
|
||||
StatePath: "/Workspace/Users/foo@bar.com/state",
|
||||
ResourcePath: "/Workspace/Users/foo@bar.com/resources",
|
||||
},
|
||||
Permissions: []resources.Permission{
|
||||
{Level: permissions.CAN_MANAGE, UserName: "foo@bar.com"},
|
||||
},
|
||||
},
|
||||
}
|
||||
m := mocks.NewMockWorkspaceClient(t)
|
||||
api := m.GetMockWorkspaceAPI()
|
||||
api.EXPECT().GetStatusByPath(mock.Anything, "/Workspace/Users/foo@bar.com").Return(&workspace.ObjectInfo{
|
||||
ObjectId: 1234,
|
||||
}, nil)
|
||||
|
||||
api.EXPECT().GetPermissions(mock.Anything, workspace.GetWorkspaceObjectPermissionsRequest{
|
||||
WorkspaceObjectId: "1234",
|
||||
WorkspaceObjectType: "directories",
|
||||
}).Return(&workspace.WorkspaceObjectPermissions{
|
||||
ObjectId: "1234",
|
||||
AccessControlList: []workspace.WorkspaceObjectAccessControlResponse{
|
||||
{
|
||||
UserName: "foo@bar.com",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
{
|
||||
UserName: "foo2@bar.com",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
b.SetWorkpaceClient(m.WorkspaceClient)
|
||||
rb := bundle.ReadOnly(b)
|
||||
|
||||
diags := bundle.ApplyReadOnly(context.Background(), rb, ValidateFolderPermissions())
|
||||
require.Len(t, diags, 1)
|
||||
require.Equal(t, "permissions missing", diags[0].Summary)
|
||||
require.Equal(t, diag.Warning, diags[0].Severity)
|
||||
require.Equal(t, "Following permissions set for the workspace folder but not set for bundle /Workspace/Users/foo@bar.com:\n- level: CAN_MANAGE\n user_name: foo2@bar.com\n", diags[0].Detail)
|
||||
}
|
||||
|
||||
func TestValidateFolderPermissionsDifferentPermission(t *testing.T) {
|
||||
b := &bundle.Bundle{
|
||||
Config: config.Root{
|
||||
Workspace: config.Workspace{
|
||||
RootPath: "/Workspace/Users/foo@bar.com",
|
||||
ArtifactPath: "/Workspace/Users/foo@bar.com/artifacts",
|
||||
FilePath: "/Workspace/Users/foo@bar.com/files",
|
||||
StatePath: "/Workspace/Users/foo@bar.com/state",
|
||||
ResourcePath: "/Workspace/Users/foo@bar.com/resources",
|
||||
},
|
||||
Permissions: []resources.Permission{
|
||||
{Level: permissions.CAN_MANAGE, UserName: "foo@bar.com"},
|
||||
},
|
||||
},
|
||||
}
|
||||
m := mocks.NewMockWorkspaceClient(t)
|
||||
api := m.GetMockWorkspaceAPI()
|
||||
api.EXPECT().GetStatusByPath(mock.Anything, "/Workspace/Users/foo@bar.com").Return(&workspace.ObjectInfo{
|
||||
ObjectId: 1234,
|
||||
}, nil)
|
||||
|
||||
api.EXPECT().GetPermissions(mock.Anything, workspace.GetWorkspaceObjectPermissionsRequest{
|
||||
WorkspaceObjectId: "1234",
|
||||
WorkspaceObjectType: "directories",
|
||||
}).Return(&workspace.WorkspaceObjectPermissions{
|
||||
ObjectId: "1234",
|
||||
AccessControlList: []workspace.WorkspaceObjectAccessControlResponse{
|
||||
{
|
||||
UserName: "foo2@bar.com",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
b.SetWorkpaceClient(m.WorkspaceClient)
|
||||
rb := bundle.ReadOnly(b)
|
||||
|
||||
diags := bundle.ApplyReadOnly(context.Background(), rb, ValidateFolderPermissions())
|
||||
require.Len(t, diags, 2)
|
||||
require.Equal(t, "permissions missing", diags[0].Summary)
|
||||
require.Equal(t, diag.Warning, diags[0].Severity)
|
||||
|
||||
require.Equal(t, "permissions missing", diags[1].Summary)
|
||||
require.Equal(t, diag.Warning, diags[1].Severity)
|
||||
}
|
||||
|
||||
func TestNoRootFolder(t *testing.T) {
|
||||
b := &bundle.Bundle{
|
||||
Config: config.Root{
|
||||
Workspace: config.Workspace{
|
||||
RootPath: "/NotExisting",
|
||||
ArtifactPath: "/NotExisting/artifacts",
|
||||
FilePath: "/NotExisting/files",
|
||||
StatePath: "/NotExisting/state",
|
||||
ResourcePath: "/NotExisting/resources",
|
||||
},
|
||||
Permissions: []resources.Permission{
|
||||
{Level: permissions.CAN_MANAGE, UserName: "foo@bar.com"},
|
||||
},
|
||||
},
|
||||
}
|
||||
m := mocks.NewMockWorkspaceClient(t)
|
||||
api := m.GetMockWorkspaceAPI()
|
||||
api.EXPECT().GetStatusByPath(mock.Anything, "/NotExisting").Return(nil, &apierr.APIError{
|
||||
StatusCode: 404,
|
||||
ErrorCode: "RESOURCE_DOES_NOT_EXIST",
|
||||
})
|
||||
api.EXPECT().GetStatusByPath(mock.Anything, "/").Return(nil, &apierr.APIError{
|
||||
StatusCode: 404,
|
||||
ErrorCode: "RESOURCE_DOES_NOT_EXIST",
|
||||
})
|
||||
|
||||
b.SetWorkpaceClient(m.WorkspaceClient)
|
||||
rb := bundle.ReadOnly(b)
|
||||
|
||||
diags := bundle.ApplyReadOnly(context.Background(), rb, ValidateFolderPermissions())
|
||||
require.Len(t, diags, 1)
|
||||
require.Equal(t, "folder / and its parent folders do not exist", diags[0].Summary)
|
||||
require.Equal(t, diag.Error, diags[0].Severity)
|
||||
}
|
|
@ -35,6 +35,7 @@ func (v *validate) Apply(ctx context.Context, b *bundle.Bundle) diag.Diagnostics
|
|||
FilesToSync(),
|
||||
ValidateSyncPatterns(),
|
||||
JobTaskClusterSpec(),
|
||||
ValidateFolderPermissions(),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -36,3 +36,8 @@ func IsWorkspaceLibrary(library *compute.Library) bool {
|
|||
|
||||
return IsWorkspacePath(path)
|
||||
}
|
||||
|
||||
// IsVolumesPath returns true if the specified path indicates that
|
||||
func IsVolumesPath(path string) bool {
|
||||
return strings.HasPrefix(path, "/Volumes/")
|
||||
}
|
|
@ -31,3 +31,13 @@ func TestIsWorkspaceLibrary(t *testing.T) {
|
|||
// Empty.
|
||||
assert.False(t, IsWorkspaceLibrary(&compute.Library{}))
|
||||
}
|
||||
|
||||
func TestIsVolumesPath(t *testing.T) {
|
||||
// Absolute paths with particular prefixes.
|
||||
assert.True(t, IsVolumesPath("/Volumes/path/to/package"))
|
||||
|
||||
// Relative paths.
|
||||
assert.False(t, IsVolumesPath("myfile.txt"))
|
||||
assert.False(t, IsVolumesPath("./myfile.txt"))
|
||||
assert.False(t, IsVolumesPath("../myfile.txt"))
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
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
|
||||
}
|
||||
|
||||
func ObjectAclToResourcePermissions(path string, acl []workspace.WorkspaceObjectAccessControlResponse) *WorkspacePathPermissions {
|
||||
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{
|
||||
Level: convertWorkspaceObjectPermissionLevel(pl.PermissionLevel),
|
||||
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
|
||||
|
||||
// Check the permissions in the bundle and see if they are all set in the workspace.
|
||||
ok, missing := containsAll(perms, p.Permissions)
|
||||
if !ok {
|
||||
diags = diags.Append(diag.Diagnostic{
|
||||
Severity: diag.Warning,
|
||||
Summary: "permissions missing",
|
||||
Detail: fmt.Sprintf("The following permissions are configured in the bundle but are do not (yet) apply to the workspace folder at %q:\n%s", p.Path, toString(missing)),
|
||||
})
|
||||
}
|
||||
|
||||
// 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("The following permissions apply to the workspace folder at %q but are not configured in the bundle:\n%s", p.Path, toString(missing)),
|
||||
})
|
||||
}
|
||||
|
||||
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 {
|
||||
found := false
|
||||
for _, b := range permB {
|
||||
if a == b {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
missing = append(missing, a)
|
||||
}
|
||||
}
|
||||
return len(missing) == 0, missing
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
func toString(p []resources.Permission) string {
|
||||
var sb strings.Builder
|
||||
for _, perm := range p {
|
||||
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
|
||||
}
|
||||
}
|
||||
return sb.String()
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
package permissions
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/databricks/cli/bundle/config/resources"
|
||||
"github.com/databricks/cli/libs/diag"
|
||||
"github.com/databricks/databricks-sdk-go/service/workspace"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestWorkspacePathPermissionsCompare(t *testing.T) {
|
||||
testCases := []struct {
|
||||
perms []resources.Permission
|
||||
acl []workspace.WorkspaceObjectAccessControlResponse
|
||||
expected diag.Diagnostics
|
||||
}{
|
||||
{
|
||||
perms: []resources.Permission{
|
||||
{Level: CAN_MANAGE, UserName: "foo@bar.com"},
|
||||
},
|
||||
acl: []workspace.WorkspaceObjectAccessControlResponse{
|
||||
{
|
||||
UserName: "foo@bar.com",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
perms: []resources.Permission{
|
||||
{Level: CAN_MANAGE, UserName: "foo@bar.com"},
|
||||
},
|
||||
acl: []workspace.WorkspaceObjectAccessControlResponse{
|
||||
{
|
||||
UserName: "foo@bar.com",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
{
|
||||
GroupName: "admin",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: nil,
|
||||
},
|
||||
{
|
||||
perms: []resources.Permission{
|
||||
{Level: CAN_VIEW, UserName: "foo@bar.com"},
|
||||
{Level: CAN_MANAGE, ServicePrincipalName: "sp.com"},
|
||||
},
|
||||
acl: []workspace.WorkspaceObjectAccessControlResponse{
|
||||
{
|
||||
UserName: "foo@bar.com",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_READ"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: diag.Diagnostics{
|
||||
{
|
||||
Severity: diag.Warning,
|
||||
Summary: "permissions missing",
|
||||
Detail: "Following permissions set in the bundle but not set for workspace folder path:\n- level: CAN_MANAGE\n service_principal_name: sp.com\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
perms: []resources.Permission{
|
||||
{Level: CAN_MANAGE, UserName: "foo@bar.com"},
|
||||
},
|
||||
acl: []workspace.WorkspaceObjectAccessControlResponse{
|
||||
{
|
||||
UserName: "foo@bar.com",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
{
|
||||
GroupName: "foo",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: diag.Diagnostics{
|
||||
{
|
||||
Severity: diag.Warning,
|
||||
Summary: "permissions missing",
|
||||
Detail: "Following permissions set for the workspace folder but not set for bundle path:\n- level: CAN_MANAGE\n group_name: foo\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
perms: []resources.Permission{
|
||||
{Level: CAN_MANAGE, UserName: "foo@bar.com"},
|
||||
},
|
||||
acl: []workspace.WorkspaceObjectAccessControlResponse{
|
||||
{
|
||||
UserName: "foo2@bar.com",
|
||||
AllPermissions: []workspace.WorkspaceObjectPermission{
|
||||
{PermissionLevel: "CAN_MANAGE"},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: diag.Diagnostics{
|
||||
{
|
||||
Severity: diag.Warning,
|
||||
Summary: "permissions missing",
|
||||
Detail: "Following permissions set in the bundle but not set for workspace folder path:\n- level: CAN_MANAGE\n user_name: foo@bar.com\n",
|
||||
},
|
||||
{
|
||||
Severity: diag.Warning,
|
||||
Summary: "permissions missing",
|
||||
Detail: "Following permissions set for the workspace folder but not set for bundle path:\n- level: CAN_MANAGE\n user_name: foo2@bar.com\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
wp := ObjectAclToResourcePermissions("path", tc.acl)
|
||||
diags := wp.Compare(tc.perms)
|
||||
require.Equal(t, tc.expected, diags)
|
||||
}
|
||||
|
||||
}
|
|
@ -34,7 +34,7 @@ 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)
|
||||
level, err := GetWorkspaceObjectPermissionLevel(p.Level)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ func giveAccessForWorkspaceRoot(ctx context.Context, b *bundle.Bundle) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func getWorkspaceObjectPermissionLevel(bundlePermission string) (workspace.WorkspaceObjectPermissionLevel, error) {
|
||||
func GetWorkspaceObjectPermissionLevel(bundlePermission string) (workspace.WorkspaceObjectPermissionLevel, error) {
|
||||
switch bundlePermission {
|
||||
case CAN_MANAGE:
|
||||
return workspace.WorkspaceObjectPermissionLevelCanManage, nil
|
||||
|
|
Loading…
Reference in New Issue