Skip to content

Commit

Permalink
Add resource info scope
Browse files Browse the repository at this point in the history
  • Loading branch information
ishank011 committed May 26, 2021
1 parent 37eb333 commit 3ba91f0
Show file tree
Hide file tree
Showing 8 changed files with 329 additions and 220 deletions.
1 change: 1 addition & 0 deletions internal/grpc/services/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package loader

import (
// Load core gRPC services.
_ "github.com/cs3org/reva/internal/grpc/services/applicationauth"
_ "github.com/cs3org/reva/internal/grpc/services/appprovider"
_ "github.com/cs3org/reva/internal/grpc/services/appregistry"
_ "github.com/cs3org/reva/internal/grpc/services/authprovider"
Expand Down
2 changes: 1 addition & 1 deletion internal/grpc/services/userprovider/userprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (s *service) Close() error {
}

func (s *service) UnprotectedEndpoints() []string {
return []string{"/cs3.identity.user.v1beta1.UserAPI/GetUser"}
return []string{"/cs3.identity.user.v1beta1.UserAPI/GetUser", "/cs3.identity.user.v1beta1.UserAPI/GetUserByClaim"}
}

func (s *service) Register(ss *grpc.Server) {
Expand Down
28 changes: 6 additions & 22 deletions pkg/auth/manager/publicshares/publicshares.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ import (
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/auth"
"github.com/cs3org/reva/pkg/auth/manager/registry"
"github.com/cs3org/reva/pkg/auth/scope"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
"github.com/cs3org/reva/pkg/utils"
"github.com/mitchellh/mapstructure"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -127,33 +127,17 @@ func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user
return nil, nil, err
}

scope, err := m.getScope(ctx, publicShareResponse.GetShare())
if err != nil {
return nil, nil, err
}

return getUserResponse.GetUser(), scope, nil
}

func (m *manager) getScope(ctx context.Context, share *link.PublicShare) (map[string]*authpb.Scope, error) {
share := publicShareResponse.GetShare()
role := authpb.Role_ROLE_VIEWER
if share.Permissions.Permissions.InitiateFileUpload {
role = authpb.Role_ROLE_EDITOR
}

val, err := utils.MarshalProtoV1ToJSON(share)
scope, err := scope.GetPublicShareScope(share, role)
if err != nil {
return nil, err
return nil, nil, err
}
return map[string]*authpb.Scope{
"publicshare": &authpb.Scope{
Resource: &types.OpaqueEntry{
Decoder: "json",
Value: val,
},
Role: role,
},
}, nil

return getUserResponse.GetUser(), scope, nil
}

// ErrPasswordNotProvided is returned when the public share is password protected, but there was no password on the request
Expand Down
28 changes: 17 additions & 11 deletions pkg/auth/scope/publicshare.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/utils"
)
Expand Down Expand Up @@ -63,7 +64,7 @@ func publicshareScope(scope *authpb.Scope, resource interface{}) (bool, error) {
case *link.GetPublicShareRequest:
return checkPublicShareRef(&share, v.GetRef()), nil
case string:
return checkPath(&share, v), nil
return checkPath(v), nil
}

return false, errtypes.InternalError(fmt.Sprintf("resource type assertion failed: %+v", resource))
Expand All @@ -86,15 +87,20 @@ func checkPublicShareRef(s *link.PublicShare, ref *link.PublicShareReference) bo
return ref.GetToken() == s.Token
}

func checkPath(s *link.PublicShare, path string) bool {
paths := []string{
"/dataprovider",
"/data",
}
for _, p := range paths {
if strings.HasPrefix(path, p) {
return true
}
// GetPublicShareScope returns the scope to allow access to a public share and
// the shared resource.
func GetPublicShareScope(share *link.PublicShare, role authpb.Role) (map[string]*authpb.Scope, error) {
val, err := utils.MarshalProtoV1ToJSON(share)
if err != nil {
return nil, err
}
return false
return map[string]*authpb.Scope{
"publicshare:" + share.Id.OpaqueId: &authpb.Scope{
Resource: &types.OpaqueEntry{
Decoder: "json",
Value: val,
},
Role: role,
},
}, nil
}
110 changes: 110 additions & 0 deletions pkg/auth/scope/resourceinfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// 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 scope

import (
"fmt"
"strings"

authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/utils"
)

func resourceinfoScope(scope *authpb.Scope, resource interface{}) (bool, error) {
var r provider.ResourceInfo
err := utils.UnmarshalJSONToProtoV1(scope.Resource.Value, &r)
if err != nil {
return false, err
}

switch v := resource.(type) {
// Viewer role
case *registry.GetStorageProvidersRequest:
return checkResourceInfo(&r, v.GetRef()), nil
case *provider.StatRequest:
return checkResourceInfo(&r, v.GetRef()), nil
case *provider.ListContainerRequest:
return checkResourceInfo(&r, v.GetRef()), nil
case *provider.InitiateFileDownloadRequest:
return checkResourceInfo(&r, v.GetRef()), nil

// Editor role
// TODO(ishank011): Add role checks,
// need to return appropriate status codes in the ocs/ocdav layers.
case *provider.CreateContainerRequest:
return checkResourceInfo(&r, v.GetRef()), nil
case *provider.DeleteRequest:
return checkResourceInfo(&r, v.GetRef()), nil
case *provider.MoveRequest:
return checkResourceInfo(&r, v.GetSource()) && checkResourceInfo(&r, v.GetDestination()), nil
case *provider.InitiateFileUploadRequest:
return checkResourceInfo(&r, v.GetRef()), nil

case string:
return checkPath(v), nil
}

return false, errtypes.InternalError(fmt.Sprintf("resource type assertion failed: %+v", resource))
}

func checkResourceInfo(inf *provider.ResourceInfo, ref *provider.Reference) bool {
// ref: <id:<storage_id:$storageID opaque_id:$opaqueID > >
if ref.GetId() != nil {
return inf.Id.StorageId == ref.GetId().StorageId && inf.Id.OpaqueId == ref.GetId().OpaqueId
}
// ref: <path:$path >
if strings.HasPrefix(ref.GetPath(), inf.Path) {
return true
}
return false
}

func checkPath(path string) bool {
paths := []string{
"/dataprovider",
"/data",
}
for _, p := range paths {
if strings.HasPrefix(path, p) {
return true
}
}
return false
}

// GetResourceInfoScope returns the scope to allow access to a resource info object.
func GetResourceInfoScope(r *provider.ResourceInfo, role authpb.Role) (map[string]*authpb.Scope, error) {
val, err := utils.MarshalProtoV1ToJSON(r)
if err != nil {
return nil, err
}
return map[string]*authpb.Scope{
"resourceinfo:" + r.Id.String(): &authpb.Scope{
Resource: &types.OpaqueEntry{
Decoder: "json",
Value: val,
},
Role: role,
},
}, nil
}
49 changes: 15 additions & 34 deletions pkg/auth/scope/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,54 +19,35 @@
package scope

import (
"strings"

authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/utils"
)

// Verifier is the function signature which every scope verifier should implement.
type Verifier func(*authpb.Scope, interface{}) (bool, error)

var supportedScopes = map[string]Verifier{
"user": userScope,
"publicshare": publicshareScope,
"user": userScope,
"publicshare": publicshareScope,
"resourceinfo": resourceinfoScope,
}

// VerifyScope is the function to be called when dismantling tokens to check if
// the token has access to a particular resource.
func VerifyScope(scopeMap map[string]*authpb.Scope, resource interface{}) (bool, error) {
for k, scope := range scopeMap {
verifierFunc := supportedScopes[k]
valid, err := verifierFunc(scope, resource)
if err != nil {
continue
}
if valid {
return true, nil
for s, f := range supportedScopes {
if strings.HasPrefix(k, s) {
valid, err := f(scope, resource)
if err != nil {
continue
}
if valid {
return true, nil
}
}
}
}
return false, nil
}

// GetOwnerScope returns the default owner scope with access to all resources.
func GetOwnerScope() (map[string]*authpb.Scope, error) {
ref := &provider.Reference{
Spec: &provider.Reference_Path{
Path: "/",
},
}
val, err := utils.MarshalProtoV1ToJSON(ref)
if err != nil {
return nil, err
}
return map[string]*authpb.Scope{
"user": &authpb.Scope{
Resource: &types.OpaqueEntry{
Decoder: "json",
Value: val,
},
Role: authpb.Role_ROLE_OWNER,
},
}, nil
}
29 changes: 28 additions & 1 deletion pkg/auth/scope/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,37 @@

package scope

import authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
import (
authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/cs3org/reva/pkg/utils"
)

func userScope(scope *authpb.Scope, resource interface{}) (bool, error) {
// Always return true. Registered users can access all paths.
// TODO(ishank011): Add checks for read/write permissions.
return true, nil
}

// GetOwnerScope returns the default owner scope with access to all resources.
func GetOwnerScope() (map[string]*authpb.Scope, error) {
ref := &provider.Reference{
Spec: &provider.Reference_Path{
Path: "/",
},
}
val, err := utils.MarshalProtoV1ToJSON(ref)
if err != nil {
return nil, err
}
return map[string]*authpb.Scope{
"user": &authpb.Scope{
Resource: &types.OpaqueEntry{
Decoder: "json",
Value: val,
},
Role: authpb.Role_ROLE_OWNER,
},
}, nil
}
Loading

0 comments on commit 3ba91f0

Please sign in to comment.