Skip to content

Commit

Permalink
first prototype of a CS3 permissions service
Browse files Browse the repository at this point in the history
  • Loading branch information
David Christofas committed Nov 17, 2021
1 parent 17606d3 commit f3f17c3
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 9 deletions.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,5 @@ replace (
github.com/oleiade/reflections => github.com/oleiade/reflections v1.0.1
google.golang.org/grpc => google.golang.org/grpc v1.26.0 // temporary downgrade
)

replace github.com/cs3org/go-cs3apis => /home/corby/work/go/src/github.com/c0rby/cs3apis/build/go-cs3apis/
1 change: 1 addition & 0 deletions internal/grpc/services/gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type config struct {
TokenManagers map[string]map[string]interface{} `mapstructure:"token_managers"`
EtagCacheTTL int `mapstructure:"etag_cache_ttl"`
CreateHomeCacheTTL int `mapstructure:"create_home_cache_ttl"`
PermissionsEndpoint string `mapstructure:"permissionssvc"`
}

// sets defaults
Expand Down
39 changes: 39 additions & 0 deletions internal/grpc/services/gateway/permissions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2018-2021 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

package gateway

import (
"context"

permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1"
"github.com/cs3org/reva/pkg/rgrpc/status"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/pkg/errors"
)

func (s *svc) CheckPermission(ctx context.Context, req *permissions.CheckPermissionRequest) (*permissions.CheckPermissionResponse, error) {
c, err := pool.GetPermissionsClient(s.c.PermissionsEndpoint)
if err != nil {
err = errors.Wrap(err, "gateway: error calling GetPermissionssClient")
return &permissions.CheckPermissionResponse{
Status: status.NewInternal(ctx, err, "error getting permissions client"),
}, nil
}
return c.CheckPermission(ctx, req)
}
21 changes: 21 additions & 0 deletions pkg/rgrpc/todo/pool/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
ocmcore "github.com/cs3org/go-cs3apis/cs3/ocm/core/v1beta1"
invitepb "github.com/cs3org/go-cs3apis/cs3/ocm/invite/v1beta1"
ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1"
permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1"
preferences "github.com/cs3org/go-cs3apis/cs3/preferences/v1beta1"
collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1"
link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
Expand Down Expand Up @@ -70,6 +71,7 @@ var (
ocmCores = newProvider()
publicShareProviders = newProvider()
preferencesProviders = newProvider()
permissionsProviders = newProvider()
appRegistries = newProvider()
appProviders = newProvider()
storageRegistries = newProvider()
Expand Down Expand Up @@ -349,6 +351,25 @@ func GetPreferencesClient(endpoint string) (preferences.PreferencesAPIClient, er
return v, nil
}

// GetPermissionsClient returns a new PermissionsClient.
func GetPermissionsClient(endpoint string) (permissions.PermissionsAPIClient, error) {
permissionsProviders.m.Lock()
defer permissionsProviders.m.Unlock()

if c, ok := permissionsProviders.conn[endpoint]; ok {
return c.(permissions.PermissionsAPIClient), nil
}

conn, err := NewConn(endpoint)
if err != nil {
return nil, err
}

v := permissions.NewPermissionsAPIClient(conn)
permissionsProviders.conn[endpoint] = v
return v, nil
}

// GetAppRegistryClient returns a new AppRegistryClient.
func GetAppRegistryClient(endpoint string) (appregistry.RegistryAPIClient, error) {
appRegistries.m.Lock()
Expand Down
3 changes: 3 additions & 0 deletions pkg/storage/utils/decomposedfs/decomposedfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import (
ctxpkg "github.com/cs3org/reva/pkg/ctx"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/logger"
"github.com/cs3org/reva/pkg/sharedconf"
"github.com/cs3org/reva/pkg/storage"
"github.com/cs3org/reva/pkg/storage/utils/chunking"
"github.com/cs3org/reva/pkg/storage/utils/decomposedfs/node"
Expand Down Expand Up @@ -100,6 +101,8 @@ func NewDefault(m map[string]interface{}, bs tree.Blobstore) (storage.FS, error)
lu.Options = o

tp := tree.New(o.Root, o.TreeTimeAccounting, o.TreeSizeAccounting, lu, bs)

o.GatewayAddr = sharedconf.GetGatewaySVC(o.GatewayAddr)
return New(o, lu, p, tp)
}

Expand Down
2 changes: 2 additions & 0 deletions pkg/storage/utils/decomposedfs/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ type Options struct {
Owner string `mapstructure:"owner"`
OwnerIDP string `mapstructure:"owner_idp"`
OwnerType string `mapstructure:"owner_type"`

GatewayAddr string `mapstructure:"gateway_addr"`
}

// New returns a new Options instance for the given configuration
Expand Down
43 changes: 34 additions & 9 deletions pkg/storage/utils/decomposedfs/spaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ import (
"strings"

userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
permissionsv1beta1 "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1"
v1beta11 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
ocsconv "github.com/cs3org/reva/internal/http/services/owncloud/ocs/conversions"
"github.com/cs3org/reva/pkg/appctx"
ctxpkg "github.com/cs3org/reva/pkg/ctx"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/pkg/storage/utils/decomposedfs/node"
"github.com/cs3org/reva/pkg/storage/utils/decomposedfs/xattrs"
"github.com/cs3org/reva/pkg/utils"
Expand Down Expand Up @@ -200,6 +202,28 @@ func (fs *Decomposedfs) ListStorageSpaces(ctx context.Context, filter []*provide
return spaces, nil
}

client, err := pool.GetGatewayServiceClient(fs.o.GatewayAddr)
if err != nil {
return nil, err
}

checkRes, err := client.CheckPermission(ctx, &permissionsv1beta1.CheckPermissionRequest{
Permission: "list-all-spaces",
SubjectRef: &permissionsv1beta1.SubjectReference{
Spec: &permissionsv1beta1.SubjectReference_UserId{
UserId: u.Id,
},
},
})
if err != nil {
return nil, err
}

canListAllSpaces := false
if checkRes.Status.Code == v1beta11.Code_CODE_OK {
canListAllSpaces = true
}

for i := range matches {
// always read link in case storage space id != node id
if target, err := os.Readlink(matches[i]); err != nil {
Expand All @@ -226,7 +250,7 @@ func (fs *Decomposedfs) ListStorageSpaces(ctx context.Context, filter []*provide
}

// TODO apply more filters
space, err := fs.storageSpaceFromNode(ctx, n, matches[i], spaceType, permissions)
space, err := fs.storageSpaceFromNode(ctx, n, matches[i], spaceType, canListAllSpaces)
if err != nil {
appctx.GetLogger(ctx).Error().Err(err).Interface("node", n).Msg("could not convert to storage space")
continue
Expand Down Expand Up @@ -318,7 +342,7 @@ func (fs *Decomposedfs) createStorageSpace(ctx context.Context, spaceType, nodeI
return nil
}

func (fs *Decomposedfs) storageSpaceFromNode(ctx context.Context, node *node.Node, nodePath, spaceType string, permissions map[string]struct{}) (*provider.StorageSpace, error) {
func (fs *Decomposedfs) storageSpaceFromNode(ctx context.Context, node *node.Node, nodePath, spaceType string, canListAllSpaces bool) (*provider.StorageSpace, error) {
owner, err := node.Owner()
if err != nil {
return nil, err
Expand Down Expand Up @@ -346,13 +370,14 @@ func (fs *Decomposedfs) storageSpaceFromNode(ctx context.Context, node *node.Nod
user := ctxpkg.ContextMustGetUser(ctx)

// filter out spaces user cannot access (currently based on stat permission)
_, canListAllSpaces := permissions["list-all-spaces"]
p, err := node.ReadUserPermissions(ctx, user)
if err != nil {
return nil, err
}
if !(canListAllSpaces || p.Stat) {
return nil, errors.New("user is not allowed to Stat the space")
if !canListAllSpaces {
p, err := node.ReadUserPermissions(ctx, user)
if err != nil {
return nil, err
}
if !p.Stat {
return nil, errors.New("user is not allowed to Stat the space")
}
}

space.Owner = &userv1beta1.User{ // FIXME only return a UserID, not a full blown user object
Expand Down

0 comments on commit f3f17c3

Please sign in to comment.