Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow sharemanager to disable reshares #4516

Merged
merged 1 commit into from
Feb 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelog/unreleased/allow-disabling-resharing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Bugfix: the sharemanager can now reject grants with resharing permissions

When disabling resharing we also need to prevent grants from allowing any grant permissions.

https://github.com/cs3org/reva/pull/4516
26 changes: 24 additions & 2 deletions internal/grpc/services/usershareprovider/usershareprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type config struct {
Drivers map[string]map[string]interface{} `mapstructure:"drivers"`
GatewayAddr string `mapstructure:"gateway_addr"`
AllowedPathsForShares []string `mapstructure:"allowed_paths_for_shares"`
DisableResharing bool `mapstructure:"disable_resharing"`
}

func (c *config) init() {
Expand All @@ -67,6 +68,7 @@ type service struct {
sm share.Manager
gatewaySelector pool.Selectable[gateway.GatewayAPIClient]
allowedPathsForShares []*regexp.Regexp
disableResharing bool
}

func getShareManager(c *config) (share.Manager, error) {
Expand Down Expand Up @@ -127,15 +129,16 @@ func NewDefault(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error
return nil, err
}

return New(gatewaySelector, sm, allowedPathsForShares), nil
return New(gatewaySelector, sm, allowedPathsForShares, c.DisableResharing), nil
}

// New creates a new user share provider svc
func New(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], sm share.Manager, allowedPathsForShares []*regexp.Regexp) rgrpc.Service {
func New(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], sm share.Manager, allowedPathsForShares []*regexp.Regexp, disableResharing bool) rgrpc.Service {
service := &service{
sm: sm,
gatewaySelector: gatewaySelector,
allowedPathsForShares: allowedPathsForShares,
disableResharing: disableResharing,
}

return service
Expand All @@ -157,6 +160,13 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar
log := appctx.GetLogger(ctx)
user := ctxpkg.ContextMustGetUser(ctx)

// when resharing is disabled grants must not allow grant permissions
if s.disableResharing && HasGrantPermissions(req.GetGrant().GetPermissions().GetPermissions()) {
return &collaboration.CreateShareResponse{
Status: status.NewInvalidArg(ctx, "resharing not supported"),
}, nil
}

gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
Expand Down Expand Up @@ -235,6 +245,10 @@ func (s *service) CreateShare(ctx context.Context, req *collaboration.CreateShar
}, nil
}

func HasGrantPermissions(p *provider.ResourcePermissions) bool {
return p.GetAddGrant() || p.GetUpdateGrant() || p.GetRemoveGrant() || p.GetDenyGrant()
}

func (s *service) RemoveShare(ctx context.Context, req *collaboration.RemoveShareRequest) (*collaboration.RemoveShareResponse, error) {
log := appctx.GetLogger(ctx)
user := ctxpkg.ContextMustGetUser(ctx)
Expand Down Expand Up @@ -327,6 +341,14 @@ func (s *service) ListShares(ctx context.Context, req *collaboration.ListSharesR
func (s *service) UpdateShare(ctx context.Context, req *collaboration.UpdateShareRequest) (*collaboration.UpdateShareResponse, error) {
log := appctx.GetLogger(ctx)
user := ctxpkg.ContextMustGetUser(ctx)

// when resharing is disabled grants must not allow grant permissions
if s.disableResharing && HasGrantPermissions(req.GetShare().GetPermissions().GetPermissions()) {
return &collaboration.UpdateShareResponse{
Status: status.NewInvalidArg(ctx, "resharing not supported"),
}, nil
}

gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ var _ = Describe("user share provider service", func() {
}
manager.On("GetShare", mock.Anything, mock.Anything).Return(getShareResponse, nil)

rgrpcService := usershareprovider.New(gatewaySelector, manager, []*regexp.Regexp{})
rgrpcService := usershareprovider.New(gatewaySelector, manager, []*regexp.Regexp{}, false)

provider = rgrpcService.(collaborationpb.CollaborationAPIServer)
Expect(provider).ToNot(BeNil())
Expand Down Expand Up @@ -183,6 +183,52 @@ var _ = Describe("user share provider service", func() {
0,
),
)
Context("resharing disabled", func() {
JustBeforeEach(func() {
// disable resharing
rgrpcService := usershareprovider.New(gatewaySelector, manager, []*regexp.Regexp{}, true)

provider = rgrpcService.(collaborationpb.CollaborationAPIServer)
Expect(provider).ToNot(BeNil())

// user has list grants access
statResourceResponse.Info.PermissionSet = &providerpb.ResourcePermissions{
AddGrant: true,
ListGrants: true,
}
})
DescribeTable("rejects shares with any grant changing permissions",
func(
resourceInfoPermissions *providerpb.ResourcePermissions,
grantPermissions *providerpb.ResourcePermissions,
responseCode rpcpb.Code,
expectedCalls int,
) {
manager.On("Share", mock.Anything, mock.Anything, mock.Anything).Return(&collaborationpb.Share{}, nil)

createShareResponse, err := provider.CreateShare(ctx, &collaborationpb.CreateShareRequest{
ResourceInfo: &providerpb.ResourceInfo{
PermissionSet: resourceInfoPermissions,
},
Grant: &collaborationpb.ShareGrant{
Permissions: &collaborationpb.SharePermissions{
Permissions: grantPermissions,
},
},
})

Expect(err).ToNot(HaveOccurred())
Expect(createShareResponse.Status.Code).To(Equal(responseCode))

manager.AssertNumberOfCalls(GinkgoT(), "Share", expectedCalls)
},
Entry("AddGrant", conversions.RoleFromName("manager", true).CS3ResourcePermissions(), &providerpb.ResourcePermissions{AddGrant: true}, rpcpb.Code_CODE_INVALID_ARGUMENT, 0),
Entry("UpdateGrant", conversions.RoleFromName("manager", true).CS3ResourcePermissions(), &providerpb.ResourcePermissions{UpdateGrant: true}, rpcpb.Code_CODE_INVALID_ARGUMENT, 0),
Entry("RemoveGrant", conversions.RoleFromName("manager", true).CS3ResourcePermissions(), &providerpb.ResourcePermissions{RemoveGrant: true}, rpcpb.Code_CODE_INVALID_ARGUMENT, 0),
Entry("DenyGrant", conversions.RoleFromName("manager", true).CS3ResourcePermissions(), &providerpb.ResourcePermissions{DenyGrant: true}, rpcpb.Code_CODE_INVALID_ARGUMENT, 0),
Entry("ListGrants", conversions.RoleFromName("manager", true).CS3ResourcePermissions(), &providerpb.ResourcePermissions{ListGrants: true}, rpcpb.Code_CODE_OK, 1),
)
})
})
Describe("UpdateShare", func() {
It("fails without WriteShare permission in user role", func() {
Expand Down
Loading