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

Fixes for apps in public shares, project spaces for EOS driver #2371

Merged
merged 2 commits into from
Jan 5, 2022
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
3 changes: 3 additions & 0 deletions changelog/unreleased/eos-fixes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Bugfix: Fixes for apps in public shares, project spaces for EOS driver

https://github.com/cs3org/reva/pull/2370
Original file line number Diff line number Diff line change
Expand Up @@ -563,8 +563,10 @@ func (s *service) augmentStatResponse(ctx context.Context, res *provider.StatRes
}

func (s *service) setPublicStorageID(info *provider.ResourceInfo, shareToken string) {
info.Id.StorageId = s.mountID
info.Id.OpaqueId = shareToken + "/" + info.Id.OpaqueId
if s.mountID != "" {
info.Id.StorageId = s.mountID
info.Id.OpaqueId = shareToken + "/" + info.Id.OpaqueId
}
}

func addShare(i *provider.ResourceInfo, ls *link.PublicShare) error {
Expand Down
15 changes: 9 additions & 6 deletions internal/http/interceptors/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package auth
import (
"fmt"
"net/http"
"strings"
"time"

"github.com/bluele/gcache"
Expand Down Expand Up @@ -297,14 +298,16 @@ func getCredsForUserAgent(ua string, uam map[string]string, creds []string) []st
return creds
}

cred, ok := uam[ua]
if ok {
for _, v := range creds {
if v == cred {
return []string{cred}
for u, cred := range uam {
if strings.Contains(ua, u) {
for _, v := range creds {
if v == cred {
return []string{cred}
}
}
return creds

}
return creds
}

return creds
Expand Down
14 changes: 12 additions & 2 deletions pkg/app/provider/wopi/wopi.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,20 @@ func (p *wopiProvider) GetAppURL(ctx context.Context, resource *provider.Resourc
q.Add("fileid", resource.GetId().OpaqueId)
q.Add("endpoint", resource.GetId().StorageId)
q.Add("viewmode", viewMode.String())

u, ok := ctxpkg.ContextGetUser(ctx)
if ok { // else defaults to "Guest xyz"
q.Add("username", u.Username)
q.Add("userid", u.Id.OpaqueId+"@"+u.Id.Idp)
var isPublicShare bool
if u.Opaque != nil {
if _, ok := u.Opaque.Map["public-share-role"]; ok {
isPublicShare = true
}
}

if !isPublicShare {
q.Add("username", u.Username)
q.Add("userid", u.Id.OpaqueId+"@"+u.Id.Idp)
}
}

q.Add("appname", p.conf.AppName)
Expand Down
14 changes: 13 additions & 1 deletion pkg/auth/manager/publicshares/publicshares.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,27 @@ func (m *manager) Authenticate(ctx context.Context, token, secret string) (*user

share := publicShareResponse.GetShare()
role := authpb.Role_ROLE_VIEWER
roleStr := "viewer"
if share.Permissions.Permissions.InitiateFileUpload {
role = authpb.Role_ROLE_EDITOR
roleStr = "editor"
}
scope, err := scope.AddPublicShareScope(share, role, nil)
if err != nil {
return nil, nil, err
}

return getUserResponse.GetUser(), scope, nil
u := getUserResponse.GetUser()
u.Opaque = &types.Opaque{
Map: map[string]*types.OpaqueEntry{
"public-share-role": {
Decoder: "plain",
Value: []byte(roleStr),
},
},
}

return u, scope, nil
}

// ErrPasswordNotProvided is returned when the public share is password protected, but there was no password on the request
Expand Down
10 changes: 8 additions & 2 deletions pkg/auth/scope/publicshare.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ import (
"fmt"
"strings"

appprovider "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1"
appregistry "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1"
authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
Expand Down Expand Up @@ -52,9 +54,13 @@ func publicshareScope(ctx context.Context, scope *authpb.Scope, resource interfa
return checkStorageRef(ctx, &share, v.GetRef()), nil
case *provider.InitiateFileDownloadRequest:
return checkStorageRef(ctx, &share, v.GetRef()), nil
case *appprovider.OpenInAppRequest:
return checkStorageRef(ctx, &share, &provider.Reference{ResourceId: v.ResourceInfo.Id}), nil
case *gateway.OpenInAppRequest:
return checkStorageRef(ctx, &share, v.GetRef()), nil

// Editor role
// need to return appropriate status codes in the ocs/ocdav layers.
// Editor role
// need to return appropriate status codes in the ocs/ocdav layers.
case *provider.CreateContainerRequest:
return hasRoleEditor(*scope) && checkStorageRef(ctx, &share, v.GetRef()), nil
case *provider.DeleteRequest:
Expand Down
10 changes: 8 additions & 2 deletions pkg/auth/scope/resourceinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ import (
"fmt"
"strings"

appprovider "github.com/cs3org/go-cs3apis/cs3/app/provider/v1beta1"
authpb "github.com/cs3org/go-cs3apis/cs3/auth/provider/v1beta1"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
"github.com/rs/zerolog"
Expand All @@ -50,9 +52,13 @@ func resourceinfoScope(_ context.Context, scope *authpb.Scope, resource interfac
return checkResourceInfo(&r, v.GetRef()), nil
case *provider.InitiateFileDownloadRequest:
return checkResourceInfo(&r, v.GetRef()), nil
case *appprovider.OpenInAppRequest:
return checkResourceInfo(&r, &provider.Reference{ResourceId: v.ResourceInfo.Id}), nil
case *gateway.OpenInAppRequest:
return checkResourceInfo(&r, v.GetRef()), nil

// Editor role
// need to return appropriate status codes in the ocs/ocdav layers.
// Editor role
// need to return appropriate status codes in the ocs/ocdav layers.
case *provider.CreateContainerRequest:
return hasRoleEditor(*scope) && checkResourceInfo(&r, v.GetRef()), nil
case *provider.DeleteRequest:
Expand Down
2 changes: 1 addition & 1 deletion pkg/cbox/favorite/sql/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func (m *mgr) SetFavorite(ctx context.Context, userID *user.UserId, resourceInfo
// The primary key is just the ID in the table, it should ideally be (uid, fileid_prefix, fileid, tag_key)
// For the time being, just check if the favorite already exists. If it does, return early
var id int
query := `"SELECT id FROM cbox_metadata WHERE uid=? AND fileid_prefix=? AND fileid=? AND tag_key="fav"`
query := `SELECT id FROM cbox_metadata WHERE uid=? AND fileid_prefix=? AND fileid=? AND tag_key="fav"`
if err := m.db.QueryRow(query, user.Id.OpaqueId, resourceInfo.Id.StorageId, resourceInfo.Id.OpaqueId).Scan(&id); err == nil {
// Favorite is already set, return
return nil
Expand Down
1 change: 1 addition & 0 deletions pkg/cbox/storage/eoswrapper/eoswrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ func (w *wrapper) setProjectSharingPermissions(ctx context.Context, r *provider.
r.PermissionSet.RemoveGrant = true
r.PermissionSet.UpdateGrant = true
r.PermissionSet.ListGrants = true
r.PermissionSet.GetQuota = true
return nil
}
}
Expand Down
15 changes: 13 additions & 2 deletions pkg/cbox/utils/conversions.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,12 @@ func ResourceTypeToItemInt(r provider.ResourceType) int {
// SharePermToInt maps read/write permissions to an integer
func SharePermToInt(p *provider.ResourcePermissions) int {
var perm int
if p.CreateContainer || p.InitiateFileUpload {
switch {
case p.InitiateFileUpload && !p.InitiateFileDownload:
perm = 4
case p.InitiateFileUpload:
perm = 15
} else if p.ListContainer || p.InitiateFileDownload {
case p.InitiateFileDownload:
perm = 1
}
// TODO map denials and resharing; currently, denials are mapped to 0
Expand Down Expand Up @@ -158,6 +161,14 @@ func IntTosharePerm(p int, itemType string) *provider.ResourcePermissions {
perm.PurgeRecycle = true
}
return perm
case 4:
return &provider.ResourcePermissions{
Stat: true,
ListContainer: true,
GetPath: true,
CreateContainer: true,
InitiateFileUpload: true,
}
default:
// TODO we may have other options, for now this is a denial
return &provider.ResourcePermissions{}
Expand Down
12 changes: 8 additions & 4 deletions pkg/eosclient/eosbinary/eosbinary.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,12 +535,16 @@ func (c *Client) SetAttr(ctx context.Context, auth eosclient.Authorization, attr
}

// UnsetAttr unsets an extended attribute on a path.
func (c *Client) UnsetAttr(ctx context.Context, auth eosclient.Authorization, attr *eosclient.Attribute, path string) error {
func (c *Client) UnsetAttr(ctx context.Context, auth eosclient.Authorization, attr *eosclient.Attribute, recursive bool, path string) error {
if !isValidAttribute(attr) {
return errors.New("eos: attr is invalid: " + serializeAttribute(attr))
}

args := []string{"attr", "-r", "rm", fmt.Sprintf("%d.%s", attr.Type, attr.Key), path}
var args []string
if recursive {
args = []string{"attr", "-r", "rm", fmt.Sprintf("%s.%s", attrTypeToString(attr.Type), attr.Key), path}
} else {
args = []string{"attr", "rm", fmt.Sprintf("%s.%s", attrTypeToString(attr.Type), attr.Key), path}
}
_, _, err := c.executeEOS(ctx, args, auth)
if err != nil {
return err
Expand Down Expand Up @@ -911,7 +915,7 @@ func (c *Client) parseFind(ctx context.Context, auth eosclient.Authorization, di
for _, fi := range finfos {
// For files, inherit ACLs from the parent
// And set the inode to that of their version folder
if !fi.IsDir {
if !fi.IsDir && !isVersionFolder(dirPath) {
if parent != nil {
fi.SysACL.Entries = append(fi.SysACL.Entries, parent.SysACL.Entries...)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/eosclient/eosclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ type EOSClient interface {
GetFileInfoByFXID(ctx context.Context, auth Authorization, fxid string) (*FileInfo, error)
GetFileInfoByPath(ctx context.Context, auth Authorization, path string) (*FileInfo, error)
SetAttr(ctx context.Context, auth Authorization, attr *Attribute, recursive bool, path string) error
UnsetAttr(ctx context.Context, auth Authorization, attr *Attribute, path string) error
UnsetAttr(ctx context.Context, auth Authorization, attr *Attribute, recursive bool, path string) error
GetAttr(ctx context.Context, auth Authorization, key, path string) (*Attribute, error)
GetQuota(ctx context.Context, username string, rootAuth Authorization, path string) (*QuotaInfo, error)
SetQuota(ctx context.Context, rooAuth Authorization, info *SetQuotaInfo) error
Expand Down
3 changes: 2 additions & 1 deletion pkg/eosclient/eosgrpc/eosgrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ func (c *Client) SetAttr(ctx context.Context, auth eosclient.Authorization, attr
}

// UnsetAttr unsets an extended attribute on a path.
func (c *Client) UnsetAttr(ctx context.Context, auth eosclient.Authorization, attr *eosclient.Attribute, path string) error {
func (c *Client) UnsetAttr(ctx context.Context, auth eosclient.Authorization, attr *eosclient.Attribute, recursive bool, path string) error {
log := appctx.GetLogger(ctx)
log.Info().Str("func", "UnsetAttr").Str("uid,gid", auth.Role.UID+","+auth.Role.GID).Str("path", path).Msg("")

Expand All @@ -586,6 +586,7 @@ func (c *Client) UnsetAttr(ctx context.Context, auth eosclient.Authorization, at

var ktd = []string{attr.Key}
msg.Keystodelete = ktd
msg.Recursive = recursive

msg.Id = new(erpc.MDId)
msg.Id.Path = []byte(path)
Expand Down
45 changes: 41 additions & 4 deletions pkg/storage/utils/eosfs/eosfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ func (fs *eosfs) UnsetArbitraryMetadata(ctx context.Context, ref *provider.Refer
Key: k,
}

err := fs.c.UnsetAttr(ctx, auth, attr, fn)
err := fs.c.UnsetAttr(ctx, auth, attr, false, fn)
if err != nil {
return errors.Wrap(err, "eosfs: error unsetting xattr in eos driver")
}
Expand Down Expand Up @@ -776,7 +776,7 @@ func (fs *eosfs) ListGrants(ctx context.Context, ref *provider.Reference) ([]*pr

grantList = append(grantList, &provider.Grant{
Grantee: grantee,
Permissions: grants.GetGrantPermissionSet(a.Permissions, true),
Permissions: grants.GetGrantPermissionSet(a.Permissions),
})
}

Expand Down Expand Up @@ -1627,7 +1627,7 @@ func (fs *eosfs) convertToFileReference(ctx context.Context, eosFileInfo *eoscli
return nil, err
}
info.Type = provider.ResourceType_RESOURCE_TYPE_REFERENCE
val, ok := eosFileInfo.Attrs["user.reva.target"]
val, ok := eosFileInfo.Attrs["reva.target"]
if !ok || val == "" {
return nil, errtypes.InternalError("eosfs: reference does not contain target: target=" + val + " file=" + eosFileInfo.File)
}
Expand All @@ -1645,6 +1645,43 @@ func (fs *eosfs) permissionSet(ctx context.Context, eosFileInfo *eosclient.FileI
}

if owner != nil && u.Id.OpaqueId == owner.OpaqueId && u.Id.Idp == owner.Idp {
// The logged-in user is the owner but we may be impersonating them
// on behalf of a public share accessor.

if u.Opaque != nil {
if publicShare, ok := u.Opaque.Map["public-share-role"]; ok {
if string(publicShare.Value) == "editor" {
return &provider.ResourcePermissions{
CreateContainer: true,
Delete: true,
GetPath: true,
GetQuota: true,
InitiateFileDownload: true,
InitiateFileUpload: true,
ListContainer: true,
ListFileVersions: true,
ListGrants: true,
ListRecycle: true,
Move: true,
PurgeRecycle: true,
RestoreFileVersion: true,
RestoreRecycleItem: true,
Stat: true,
}
}
return &provider.ResourcePermissions{
GetPath: true,
GetQuota: true,
InitiateFileDownload: true,
ListContainer: true,
ListFileVersions: true,
ListRecycle: true,
ListGrants: true,
Stat: true,
}
}
}

return &provider.ResourcePermissions{
// owner has all permissions
AddGrant: true,
Expand Down Expand Up @@ -1695,7 +1732,7 @@ func (fs *eosfs) permissionSet(ctx context.Context, eosFileInfo *eosclient.FileI
}

if (e.Type == acl.TypeUser && e.Qualifier == auth.Role.UID) || (e.Type == acl.TypeLightweight && e.Qualifier == u.Id.OpaqueId) || userInGroup {
mergePermissions(&perm, grants.GetGrantPermissionSet(e.Permissions, eosFileInfo.IsDir))
mergePermissions(&perm, grants.GetGrantPermissionSet(e.Permissions))
}
}

Expand Down
10 changes: 3 additions & 7 deletions pkg/storage/utils/grants/grants.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func GetACLPerm(set *provider.ResourcePermissions) (string, error) {
// TODO(labkode): add more fine grained controls.
// EOS acls are a mix of ACLs and POSIX permissions. More details can be found in
// https://github.com/cern-eos/eos/blob/master/doc/configuration/permission.rst
func GetGrantPermissionSet(perm string, isDir bool) *provider.ResourcePermissions {
func GetGrantPermissionSet(perm string) *provider.ResourcePermissions {
var rp provider.ResourcePermissions // default to 0 == all denied

if strings.Contains(perm, "r") && !strings.Contains(perm, "!r") {
Expand All @@ -82,17 +82,13 @@ func GetGrantPermissionSet(perm string, isDir bool) *provider.ResourcePermission
rp.InitiateFileUpload = true
rp.RestoreFileVersion = true
rp.RestoreRecycleItem = true
if isDir {
rp.CreateContainer = true
}
rp.CreateContainer = true
}

if strings.Contains(perm, "x") && !strings.Contains(perm, "!x") {
rp.ListFileVersions = true
rp.ListRecycle = true
if isDir {
rp.ListContainer = true
}
rp.ListContainer = true
}

if strings.Contains(perm, "!d") {
Expand Down
2 changes: 1 addition & 1 deletion pkg/storage/utils/localfs/localfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ func (fs *localfs) ListGrants(ctx context.Context, ref *provider.Reference) ([]*
} else if grantSplit[0] == acl.TypeGroup {
grantee.Id = &provider.Grantee_GroupId{GroupId: &grouppb.GroupId{OpaqueId: parts[0], Idp: parts[1]}}
}
permissions := grants.GetGrantPermissionSet(role, true)
permissions := grants.GetGrantPermissionSet(role)

grantList = append(grantList, &provider.Grant{
Grantee: grantee,
Expand Down