From 4e222b7bd1810509edab7fa7e2d43b7689a69f4f Mon Sep 17 00:00:00 2001 From: Ishank Arora Date: Tue, 28 Jul 2020 15:02:53 +0200 Subject: [PATCH] Add logic for citrine EOS ACLs --- go.mod | 2 +- go.sum | 2 + .../grpc/services/gateway/userprovider.go | 2 +- .../services/userprovider/userprovider.go | 2 +- pkg/eosclient/eosclient.go | 65 +++++++++++++++++-- pkg/storage/utils/acl/acl.go | 14 ++++ 6 files changed, 80 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 047c21d9061..4c44dcf6b71 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/cheggaaa/pb v1.0.28 github.com/coreos/go-oidc v2.2.1+incompatible github.com/cs3org/cato v0.0.0-20200626150132-28a40e643719 - github.com/cs3org/go-cs3apis v0.0.0-20200720081540-0d96aec81a2e + github.com/cs3org/go-cs3apis v0.0.0-20200728114537-4efa23660dbe github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/eventials/go-tus v0.0.0-20200718001131-45c7ec8f5d59 github.com/go-ldap/ldap/v3 v3.2.3 diff --git a/go.sum b/go.sum index e5ecdb0daf8..f8314ce2e5c 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ github.com/cs3org/go-cs3apis v0.0.0-20200709064917-d96c5f2a42ad h1:XxB0h+UKILRKd github.com/cs3org/go-cs3apis v0.0.0-20200709064917-d96c5f2a42ad/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/cs3org/go-cs3apis v0.0.0-20200720081540-0d96aec81a2e h1:Q1GsuqKBo74Z6WNkUTVmyCATf7WwaTk8Fyx3Xw4CrU4= github.com/cs3org/go-cs3apis v0.0.0-20200720081540-0d96aec81a2e/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= +github.com/cs3org/go-cs3apis v0.0.0-20200728114537-4efa23660dbe h1:CQ/Grq7oVFqwiUg4VA/T+fl3JHZKEyo/RcTE7C23rW4= +github.com/cs3org/go-cs3apis v0.0.0-20200728114537-4efa23660dbe/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/internal/grpc/services/gateway/userprovider.go b/internal/grpc/services/gateway/userprovider.go index 676c950f8d4..87c9e354c15 100644 --- a/internal/grpc/services/gateway/userprovider.go +++ b/internal/grpc/services/gateway/userprovider.go @@ -46,7 +46,7 @@ func (s *svc) GetUser(ctx context.Context, req *user.GetUserRequest) (*user.GetU func (s *svc) GetUserByClaim(ctx context.Context, req *user.GetUserByClaimRequest) (*user.GetUserByClaimResponse, error) { c, err := pool.GetUserProviderServiceClient(s.c.UserProviderEndpoint) if err != nil { - return &user.GetUserGetUserByClaimResponse{ + return &user.GetUserByClaimResponse{ Status: status.NewInternal(ctx, err, "error getting auth client"), }, nil } diff --git a/internal/grpc/services/userprovider/userprovider.go b/internal/grpc/services/userprovider/userprovider.go index 16055d60575..46f31eb9da1 100644 --- a/internal/grpc/services/userprovider/userprovider.go +++ b/internal/grpc/services/userprovider/userprovider.go @@ -127,7 +127,7 @@ func (s *service) GetUserByClaim(ctx context.Context, req *userpb.GetUserByClaim return res, nil } - res := &userpb.GetUserByClaim{ + res := &userpb.GetUserByClaimResponse{ Status: status.NewOK(ctx), User: user, } diff --git a/pkg/eosclient/eosclient.go b/pkg/eosclient/eosclient.go index 44e180d5184..abc8cfc94e5 100644 --- a/pkg/eosclient/eosclient.go +++ b/pkg/eosclient/eosclient.go @@ -41,12 +41,17 @@ import ( const ( versionPrefix = ".sys.v#." + + versionAquamarine = eosVersion("aquamarine") + versionCitrine = eosVersion("citrine") ) // AttrType is the type of extended attribute, // either system (sys) or user (user). type AttrType uint32 +type eosVersion string + const ( // SystemAttr is the system extended attribute. SystemAttr AttrType = iota @@ -260,6 +265,34 @@ func (c *Client) executeEOS(ctx context.Context, cmd *exec.Cmd) (string, string, return outBuf.String(), errBuf.String(), err } +func (c *Client) getVersion(ctx context.Context, rootUID, rootGID string) (eosVersion, error) { + cmd := exec.CommandContext(ctx, c.opt.EosBinary, "-r", rootUID, rootGID, "version") + stdout, _, err := c.executeEOS(ctx, cmd) + if err != nil { + return "", err + } + return c.parseVersion(ctx, stdout), nil +} + +func (c *Client) parseVersion(ctx context.Context, raw string) eosVersion { + var serverVersion string + rawLines := strings.Split(raw, "\n") + for _, rl := range rawLines { + if rl == "" { + continue + } + if strings.HasPrefix(rl, "EOS_SERVER_VERSION") { + serverVersion = strings.Split(strings.Split(rl, " ")[0], "=")[1] + break + } + } + + if strings.HasPrefix(serverVersion, "4.") { + return versionCitrine + } + return versionAquamarine +} + // AddACL adds an new acl to EOS with the given aclType. func (c *Client) AddACL(ctx context.Context, uid, gid, rootUID, rootGID, path string, a *acl.Entry) error { acls, err := c.getACLForPath(ctx, uid, gid, path) @@ -271,9 +304,21 @@ func (c *Client) AddACL(ctx context.Context, uid, gid, rootUID, rootGID, path st if err != nil { return err } - sysACL := acls.Serialize() - cmd := exec.CommandContext(ctx, c.opt.EosBinary, "-r", rootUID, rootGID, "attr", "-r", "set", fmt.Sprintf("sys.acl=%s", sysACL), path) + version, err := c.getVersion(ctx, rootUID, rootGID) + if err != nil { + return err + } + + var cmd *exec.Cmd + if version == versionCitrine { + sysACL := acls.CitrineSerialize() + cmd = exec.CommandContext(ctx, c.opt.EosBinary, "-r", rootUID, rootGID, "acl", "--sys", "--recursive", sysACL, path) + } else { + sysACL := acls.Serialize() + cmd = exec.CommandContext(ctx, c.opt.EosBinary, "-r", rootUID, rootGID, "attr", "-r", "set", fmt.Sprintf("sys.acl=%s", sysACL), path) + } + _, _, err = c.executeEOS(ctx, cmd) return err @@ -281,15 +326,27 @@ func (c *Client) AddACL(ctx context.Context, uid, gid, rootUID, rootGID, path st // RemoveACL removes the acl from EOS. func (c *Client) RemoveACL(ctx context.Context, uid, gid, rootUID, rootGID, path string, aclType string, recipient string) error { + version, err := c.getVersion(ctx, rootUID, rootGID) + if err != nil { + return err + } + acls, err := c.getACLForPath(ctx, uid, gid, path) if err != nil { return err } acls.DeleteEntry(aclType, recipient) - sysACL := acls.Serialize() - cmd := exec.CommandContext(ctx, c.opt.EosBinary, "-r", rootUID, rootGID, "attr", "-r", "set", fmt.Sprintf("sys.acl=%s", sysACL), path) + var cmd *exec.Cmd + if version == versionCitrine { + sysACL := acls.CitrineSerialize() + cmd = exec.CommandContext(ctx, c.opt.EosBinary, "-r", rootUID, rootGID, "acl", "--sys", "--recursive", sysACL, path) + } else { + sysACL := acls.Serialize() + cmd = exec.CommandContext(ctx, c.opt.EosBinary, "-r", rootUID, rootGID, "attr", "-r", "set", fmt.Sprintf("sys.acl=%s", sysACL), path) + } + _, _, err = c.executeEOS(ctx, cmd) return err diff --git a/pkg/storage/utils/acl/acl.go b/pkg/storage/utils/acl/acl.go index d9150e3acad..f1a28bd77b3 100644 --- a/pkg/storage/utils/acl/acl.go +++ b/pkg/storage/utils/acl/acl.go @@ -20,6 +20,7 @@ package acl import ( "errors" + "fmt" "strings" ) @@ -81,6 +82,15 @@ func (m *ACLs) Serialize() string { return strings.Join(sysACL, ShortTextForm) } +// Serialize always serializes to short text form +func (m *ACLs) CitrineSerialize() string { + sysACL := []string{} + for _, e := range m.Entries { + sysACL = append(sysACL, e.citrineSerialize()) + } + return strings.Join(sysACL, ShortTextForm) +} + // DeleteEntry removes an entry uniquely identified by acl type and qualifier func (m *ACLs) DeleteEntry(aclType string, qualifier string) { aclType = getShortType(aclType) @@ -145,3 +155,7 @@ func getShortType(aclType string) string { func (a *Entry) serialize() string { return strings.Join([]string{a.Type, a.Qualifier, a.Permissions}, ":") } + +func (a *Entry) citrineSerialize() string { + return fmt.Sprintf("%s:%s=%s", a.Type, a.Qualifier, a.Permissions) +}