From ed156cd738111c46d91da7fa5609cce19927ac42 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Thu, 20 Jan 2022 12:45:58 +0300 Subject: [PATCH] [#1096] eacl: Use validator from SDK Signed-off-by: Pavel Karpy --- cmd/neofs-node/object.go | 6 +- go.mod | 4 +- go.sum | 8 +- pkg/services/object/acl/acl.go | 25 ++- pkg/services/object/acl/eacl/opts.go | 17 -- pkg/services/object/acl/eacl/types.go | 81 -------- pkg/services/object/acl/eacl/v2/eacl_test.go | 55 ++--- pkg/services/object/acl/eacl/v2/headers.go | 23 +-- pkg/services/object/acl/eacl/v2/object.go | 8 +- pkg/services/object/acl/eacl/validator.go | 189 ------------------ .../object/acl/eacl/validator_test.go | 52 ----- pkg/services/object/acl/opts.go | 6 +- 12 files changed, 61 insertions(+), 413 deletions(-) delete mode 100644 pkg/services/object/acl/eacl/opts.go delete mode 100644 pkg/services/object/acl/eacl/validator.go delete mode 100644 pkg/services/object/acl/eacl/validator_test.go diff --git a/cmd/neofs-node/object.go b/cmd/neofs-node/object.go index cd0e40ddb..410eb3823 100644 --- a/cmd/neofs-node/object.go +++ b/cmd/neofs-node/object.go @@ -20,7 +20,6 @@ import ( objectTransportGRPC "github.com/nspcc-dev/neofs-node/pkg/network/transport/object/grpc" objectService "github.com/nspcc-dev/neofs-node/pkg/services/object" "github.com/nspcc-dev/neofs-node/pkg/services/object/acl" - "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl" deletesvc "github.com/nspcc-dev/neofs-node/pkg/services/object/delete" deletesvcV2 "github.com/nspcc-dev/neofs-node/pkg/services/object/delete/v2" getsvc "github.com/nspcc-dev/neofs-node/pkg/services/object/get" @@ -365,10 +364,7 @@ func initObjectService(c *cfg) { ), acl.WithNextService(splitSvc), acl.WithLocalStorage(ls), - acl.WithEACLValidatorOptions( - eacl.WithEACLSource(c.cfgObject.eaclSource), - eacl.WithLogger(c.log), - ), + acl.WithEACLSource(c.cfgObject.eaclSource), acl.WithNetmapState(c.cfgNetmap.state), ) diff --git a/go.mod b/go.mod index 8c219baf1..e6b38e6fa 100644 --- a/go.mod +++ b/go.mod @@ -12,8 +12,8 @@ require ( github.com/multiformats/go-multiaddr v0.4.0 github.com/nspcc-dev/hrw v1.0.9 github.com/nspcc-dev/neo-go v0.98.0 - github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 - github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 + github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220114101721-227a871a04ac + github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220119080627-f83ff628fb19 github.com/nspcc-dev/tzhash v1.4.0 github.com/panjf2000/ants/v2 v2.4.0 github.com/paulmach/orb v0.2.2 diff --git a/go.sum b/go.sum index c621221d1..36b0eb479 100644 --- a/go.sum +++ b/go.sum @@ -364,15 +364,15 @@ github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1: github.com/nspcc-dev/neo-go v0.98.0 h1:yyW4sgY88/pLf0949qmgfkQXzRKC3CI/WyhqXNnwMd8= github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.1 h1:SVqc523pZsSaS9vnPS1mm3VV6b6xY0gvdA0uYJ/GWZQ= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= +github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220114101721-227a871a04ac h1:65C4z7pybLT2HjtY96abZj6kbgVp34AbrApn5DD+ZxY= +github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220114101721-227a871a04ac/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-crypto v0.3.0 h1:zlr3pgoxuzrmGCxc5W8dGVfA9Rro8diFvVnBg0L4ifM= github.com/nspcc-dev/neofs-crypto v0.3.0/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-sdk-go v0.0.0-20211201182451-a5b61c4f6477/go.mod h1:dfMtQWmBHYpl9Dez23TGtIUKiFvCIxUZq/CkSIhEpz4= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659 h1:rpMCoRa7expLc9gMiOP724gz6YSykZzmMALR/CmiwnU= -github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220113123743-7f3162110659/go.mod h1:/jay1lr3w7NQd/VDBkEhkJmDmyPNsu4W+QV2obsUV40= +github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220119080627-f83ff628fb19 h1:VuOztHAvvu0ZK7ng6EillhlEunHy34TQr5/13k0fSUU= +github.com/nspcc-dev/neofs-sdk-go v0.0.0-20220119080627-f83ff628fb19/go.mod h1:fhs4v6uts7bEgwYP05NXbAQlQ0YhK4WVjJRKQKFKBxY= github.com/nspcc-dev/rfc6979 v0.1.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= github.com/nspcc-dev/rfc6979 v0.2.0 h1:3e1WNxrN60/6N0DW7+UYisLeZJyfqZTNOjeV/toYvOE= github.com/nspcc-dev/rfc6979 v0.2.0/go.mod h1:exhIh1PdpDC5vQmyEsGvc4YDM/lyQp/452QxGq/UEso= diff --git a/pkg/services/object/acl/acl.go b/pkg/services/object/acl/acl.go index c7701fe07..5664a8da0 100644 --- a/pkg/services/object/acl/acl.go +++ b/pkg/services/object/acl/acl.go @@ -12,6 +12,7 @@ import ( "github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-api-go/v2/session" v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature" + "github.com/nspcc-dev/neofs-node/pkg/core/container" core "github.com/nspcc-dev/neofs-node/pkg/core/container" "github.com/nspcc-dev/neofs-node/pkg/core/netmap" "github.com/nspcc-dev/neofs-node/pkg/local_object_storage/engine" @@ -95,9 +96,9 @@ type cfg struct { } type eACLCfg struct { - eACLOpts []eacl.Option + eaclSource eacl.Source - eACL *eacl.Validator + eACL *acl.Validator localStorage *engine.StorageEngine @@ -130,7 +131,7 @@ func New(opts ...Option) Service { opts[i](cfg) } - cfg.eACL = eacl.NewValidator(cfg.eACLOpts...) + cfg.eACL = acl.NewValidator() return Service{ cfg: cfg, @@ -610,6 +611,20 @@ func eACLCheck(msg interface{}, reqInfo requestInfo, cfg *eACLCfg) bool { reqInfo.bearer = nil } + var ( + table *acl.Table + err error + ) + + if reqInfo.bearer == nil { + table, err = cfg.eaclSource.GetEACL(reqInfo.cid) + if err != nil { + return errors.Is(err, container.ErrEACLNotFound) + } + } else { + table = acl.NewTableFromV2(reqInfo.bearer.GetBody().GetEACL()) + } + // if bearer token is not present, isValidBearer returns true if !isValidBearer(reqInfo, cfg.state) { return false @@ -637,7 +652,7 @@ func eACLCheck(msg interface{}, reqInfo requestInfo, cfg *eACLCfg) bool { ) } - action := cfg.eACL.CalculateAction(new(eacl.ValidationUnit). + action := cfg.eACL.CalculateAction(new(acl.ValidationUnit). WithRole(reqInfo.requestRole). WithOperation(reqInfo.operation). WithContainerID(reqInfo.cid). @@ -645,7 +660,7 @@ func eACLCheck(msg interface{}, reqInfo requestInfo, cfg *eACLCfg) bool { WithHeaderSource( eaclV2.NewMessageHeaderSource(hdrSrcOpts...), ). - WithBearerToken(reqInfo.bearer), + WithEACLTable(table), ) return action == acl.ActionAllow diff --git a/pkg/services/object/acl/eacl/opts.go b/pkg/services/object/acl/eacl/opts.go deleted file mode 100644 index 1b5b40d50..000000000 --- a/pkg/services/object/acl/eacl/opts.go +++ /dev/null @@ -1,17 +0,0 @@ -package eacl - -import ( - "github.com/nspcc-dev/neofs-node/pkg/util/logger" -) - -func WithLogger(v *logger.Logger) Option { - return func(c *cfg) { - c.logger = v - } -} - -func WithEACLSource(v Source) Option { - return func(c *cfg) { - c.storage = v - } -} diff --git a/pkg/services/object/acl/eacl/types.go b/pkg/services/object/acl/eacl/types.go index 3a90a667b..700428baf 100644 --- a/pkg/services/object/acl/eacl/types.go +++ b/pkg/services/object/acl/eacl/types.go @@ -1,7 +1,6 @@ package eacl import ( - bearer "github.com/nspcc-dev/neofs-api-go/v2/acl" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/eacl" ) @@ -18,83 +17,3 @@ type Source interface { // eACL table is not in source. GetEACL(*cid.ID) (*eacl.Table, error) } - -// Header is an interface of string key-value header. -type Header interface { - Key() string - Value() string -} - -// TypedHeaderSource is the interface that wraps -// method for selecting typed headers by type. -type TypedHeaderSource interface { - // HeadersOfType returns the list of key-value headers - // of particular type. - // - // It returns any problem encountered through the boolean - // false value. - HeadersOfType(eacl.FilterHeaderType) ([]Header, bool) -} - -// ValidationUnit represents unit of check for Validator. -type ValidationUnit struct { - cid *cid.ID - - role eacl.Role - - op eacl.Operation - - hdrSrc TypedHeaderSource - - key []byte - - bearer *bearer.BearerToken -} - -func (u *ValidationUnit) WithContainerID(v *cid.ID) *ValidationUnit { - if u != nil { - u.cid = v - } - - return u -} - -func (u *ValidationUnit) WithRole(v eacl.Role) *ValidationUnit { - if u != nil { - u.role = v - } - - return u -} - -func (u *ValidationUnit) WithOperation(v eacl.Operation) *ValidationUnit { - if u != nil { - u.op = v - } - - return u -} - -func (u *ValidationUnit) WithHeaderSource(v TypedHeaderSource) *ValidationUnit { - if u != nil { - u.hdrSrc = v - } - - return u -} - -func (u *ValidationUnit) WithSenderKey(v []byte) *ValidationUnit { - if u != nil { - u.key = v - } - - return u -} - -func (u *ValidationUnit) WithBearerToken(bearer *bearer.BearerToken) *ValidationUnit { - if u != nil { - u.bearer = bearer - } - - return u -} diff --git a/pkg/services/object/acl/eacl/v2/eacl_test.go b/pkg/services/object/acl/eacl/v2/eacl_test.go index faf244e36..44c5db480 100644 --- a/pkg/services/object/acl/eacl/v2/eacl_test.go +++ b/pkg/services/object/acl/eacl/v2/eacl_test.go @@ -10,10 +10,8 @@ import ( objectV2 "github.com/nspcc-dev/neofs-api-go/v2/object" "github.com/nspcc-dev/neofs-api-go/v2/session" "github.com/nspcc-dev/neofs-node/pkg/core/object" - eacl2 "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl" - cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" - "github.com/nspcc-dev/neofs-sdk-go/eacl" + eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" "github.com/stretchr/testify/require" ) @@ -26,20 +24,6 @@ type testLocalStorage struct { obj *object.Object } -type testEACLStorage struct { - t *testing.T - - expCID *cid.ID - - table *eacl.Table -} - -func (s *testEACLStorage) GetEACL(id *cid.ID) (*eacl.Table, error) { - require.True(s.t, s.expCID.Equal(id)) - - return s.table, nil -} - func (s *testLocalStorage) Head(addr *objectSDK.Address) (*object.Object, error) { require.True(s.t, addr.ContainerID().Equal(addr.ContainerID()) && addr.ObjectID().Equal(addr.ObjectID())) @@ -109,18 +93,18 @@ func TestHeadRequest(t *testing.T) { attr.SetValue(attrVal) obj.SetAttributes(attr) - table := new(eacl.Table) + table := new(eaclSDK.Table) priv, err := keys.NewPrivateKey() require.NoError(t, err) senderKey := priv.PublicKey() - r := eacl.NewRecord() - r.SetOperation(eacl.OperationHead) - r.SetAction(eacl.ActionDeny) - r.AddFilter(eacl.HeaderFromObject, eacl.MatchStringEqual, attrKey, attrVal) - r.AddFilter(eacl.HeaderFromRequest, eacl.MatchStringEqual, xKey, xVal) - eacl.AddFormedTarget(r, eacl.RoleUnknown, (ecdsa.PublicKey)(*senderKey)) + r := eaclSDK.NewRecord() + r.SetOperation(eaclSDK.OperationHead) + r.SetAction(eaclSDK.ActionDeny) + r.AddFilter(eaclSDK.HeaderFromObject, eaclSDK.MatchStringEqual, attrKey, attrVal) + r.AddFilter(eaclSDK.HeaderFromRequest, eaclSDK.MatchStringEqual, xKey, xVal) + eaclSDK.AddFormedTarget(r, eaclSDK.RoleUnknown, (ecdsa.PublicKey)(*senderKey)) table.AddRecord(r) @@ -131,36 +115,29 @@ func TestHeadRequest(t *testing.T) { } cid := addr.ContainerID() - unit := new(eacl2.ValidationUnit). + unit := new(eaclSDK.ValidationUnit). WithContainerID(cid). - WithOperation(eacl.OperationHead). + WithOperation(eaclSDK.OperationHead). WithSenderKey(senderKey.Bytes()). WithHeaderSource( NewMessageHeaderSource( WithObjectStorage(lStorage), WithServiceRequest(req), ), - ) + ). + WithEACLTable(table) - eStorage := &testEACLStorage{ - t: t, - expCID: cid, - table: table, - } + validator := eaclSDK.NewValidator() - validator := eacl2.NewValidator( - eacl2.WithEACLSource(eStorage), - ) - - require.Equal(t, eacl.ActionDeny, validator.CalculateAction(unit)) + require.Equal(t, eaclSDK.ActionDeny, validator.CalculateAction(unit)) meta.SetXHeaders(nil) - require.Equal(t, eacl.ActionAllow, validator.CalculateAction(unit)) + require.Equal(t, eaclSDK.ActionAllow, validator.CalculateAction(unit)) meta.SetXHeaders(xHdrs) obj.SetAttributes(nil) - require.Equal(t, eacl.ActionAllow, validator.CalculateAction(unit)) + require.Equal(t, eaclSDK.ActionAllow, validator.CalculateAction(unit)) } diff --git a/pkg/services/object/acl/eacl/v2/headers.go b/pkg/services/object/acl/eacl/v2/headers.go index 6f23f6a5d..ba9118b7c 100644 --- a/pkg/services/object/acl/eacl/v2/headers.go +++ b/pkg/services/object/acl/eacl/v2/headers.go @@ -8,7 +8,6 @@ import ( "github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-api-go/v2/session" "github.com/nspcc-dev/neofs-node/pkg/core/object" - "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" @@ -47,7 +46,7 @@ func defaultCfg() *cfg { } } -func NewMessageHeaderSource(opts ...Option) eacl.TypedHeaderSource { +func NewMessageHeaderSource(opts ...Option) eaclSDK.TypedHeaderSource { cfg := defaultCfg() for i := range opts { @@ -59,7 +58,7 @@ func NewMessageHeaderSource(opts ...Option) eacl.TypedHeaderSource { } } -func (h *headerSource) HeadersOfType(typ eaclSDK.FilterHeaderType) ([]eacl.Header, bool) { +func (h *headerSource) HeadersOfType(typ eaclSDK.FilterHeaderType) ([]eaclSDK.Header, bool) { switch typ { default: return nil, true @@ -70,10 +69,10 @@ func (h *headerSource) HeadersOfType(typ eaclSDK.FilterHeaderType) ([]eacl.Heade } } -func requestHeaders(msg xHeaderSource) []eacl.Header { +func requestHeaders(msg xHeaderSource) []eaclSDK.Header { xHdrs := msg.GetXHeaders() - res := make([]eacl.Header, 0, len(xHdrs)) + res := make([]eaclSDK.Header, 0, len(xHdrs)) for i := range xHdrs { res = append(res, sessionSDK.NewXHeaderFromV2(xHdrs[i])) @@ -82,7 +81,7 @@ func requestHeaders(msg xHeaderSource) []eacl.Header { return res } -func (h *headerSource) objectHeaders() ([]eacl.Header, bool) { +func (h *headerSource) objectHeaders() ([]eaclSDK.Header, bool) { var addr *objectSDK.Address if h.addr != nil { addr = objectSDK.NewAddressFromV2(h.addr) @@ -119,7 +118,7 @@ func (h *headerSource) objectHeaders() ([]eacl.Header, bool) { return hs, true } case *objectV2.SearchRequest: - return []eacl.Header{cidHeader( + return []eaclSDK.Header{cidHeader( cid.NewFromV2( req.GetBody().GetContainerID()), )}, true @@ -165,7 +164,7 @@ func (h *headerSource) objectHeaders() ([]eacl.Header, bool) { return nil, true } -func (h *headerSource) localObjectHeaders(addrV2 *refs.Address) ([]eacl.Header, bool) { +func (h *headerSource) localObjectHeaders(addrV2 *refs.Address) ([]eaclSDK.Header, bool) { addr := objectSDK.NewAddressFromV2(addrV2) obj, err := h.storage.Head(addr) @@ -176,22 +175,22 @@ func (h *headerSource) localObjectHeaders(addrV2 *refs.Address) ([]eacl.Header, return addressHeaders(addr), false } -func cidHeader(cid *cid.ID) eacl.Header { +func cidHeader(cid *cid.ID) eaclSDK.Header { return &sysObjHdr{ k: acl.FilterObjectContainerID, v: cidValue(cid), } } -func oidHeader(oid *objectSDK.ID) eacl.Header { +func oidHeader(oid *objectSDK.ID) eaclSDK.Header { return &sysObjHdr{ k: acl.FilterObjectID, v: idValue(oid), } } -func addressHeaders(addr *objectSDK.Address) []eacl.Header { - res := make([]eacl.Header, 1, 2) +func addressHeaders(addr *objectSDK.Address) []eaclSDK.Header { + res := make([]eaclSDK.Header, 1, 2) res[0] = cidHeader(addr.ContainerID()) if oid := addr.ObjectID(); oid != nil { diff --git a/pkg/services/object/acl/eacl/v2/object.go b/pkg/services/object/acl/eacl/v2/object.go index 21c4605cf..a31059de8 100644 --- a/pkg/services/object/acl/eacl/v2/object.go +++ b/pkg/services/object/acl/eacl/v2/object.go @@ -5,8 +5,8 @@ import ( "github.com/nspcc-dev/neofs-api-go/v2/acl" "github.com/nspcc-dev/neofs-node/pkg/core/object" - "github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" + eaclSDK "github.com/nspcc-dev/neofs-sdk-go/eacl" objectSDK "github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/owner" ) @@ -39,9 +39,9 @@ func u64Value(v uint64) string { return strconv.FormatUint(v, 10) } -func headersFromObject(obj *object.Object, addr *objectSDK.Address) []eacl.Header { +func headersFromObject(obj *object.Object, addr *objectSDK.Address) []eaclSDK.Header { // TODO: optimize allocs - res := make([]eacl.Header, 0) + res := make([]eaclSDK.Header, 0) for ; obj != nil; obj = obj.GetParent() { res = append(res, @@ -85,7 +85,7 @@ func headersFromObject(obj *object.Object, addr *objectSDK.Address) []eacl.Heade ) attrs := obj.Attributes() - hs := make([]eacl.Header, 0, len(attrs)) + hs := make([]eaclSDK.Header, 0, len(attrs)) for i := range attrs { hs = append(hs, attrs[i]) diff --git a/pkg/services/object/acl/eacl/validator.go b/pkg/services/object/acl/eacl/validator.go deleted file mode 100644 index 2174aa3a4..000000000 --- a/pkg/services/object/acl/eacl/validator.go +++ /dev/null @@ -1,189 +0,0 @@ -package eacl - -import ( - "bytes" - "errors" - - "github.com/nspcc-dev/neofs-node/pkg/core/container" - "github.com/nspcc-dev/neofs-node/pkg/util/logger" - "github.com/nspcc-dev/neofs-sdk-go/eacl" - "go.uber.org/zap" -) - -// Validator is a tool that calculates -// the action on a request according -// to the extended ACL rule table. -type Validator struct { - *cfg -} - -// Option represents Validator option. -type Option func(*cfg) - -type cfg struct { - logger *logger.Logger - - storage Source -} - -func defaultCfg() *cfg { - return &cfg{ - logger: zap.L(), - } -} - -// NewValidator creates and initializes a new Validator using options. -func NewValidator(opts ...Option) *Validator { - cfg := defaultCfg() - - for i := range opts { - opts[i](cfg) - } - - return &Validator{ - cfg: cfg, - } -} - -// CalculateAction calculates action on the request according -// to its information represented in ValidationUnit. -// -// The action is calculated according to the application of -// eACL table of rules to the request. -// -// If the eACL table is not available at the time of the call, -// eacl.ActionUnknown is returned. -// -// If no matching table entry is found, ActionAllow is returned. -func (v *Validator) CalculateAction(unit *ValidationUnit) eacl.Action { - var ( - err error - table *eacl.Table - ) - - if unit.bearer != nil { - table = eacl.NewTableFromV2(unit.bearer.GetBody().GetEACL()) - } else { - // get eACL table by container ID - table, err = v.storage.GetEACL(unit.cid) - if err != nil { - if errors.Is(err, container.ErrEACLNotFound) { - return eacl.ActionAllow - } - - v.logger.Error("could not get eACL table", - zap.String("error", err.Error()), - ) - - return eacl.ActionUnknown - } - } - - return tableAction(unit, table) -} - -// calculates action on the request based on the eACL rules. -func tableAction(unit *ValidationUnit, table *eacl.Table) eacl.Action { - for _, record := range table.Records() { - // check type of operation - if record.Operation() != unit.op { - continue - } - - // check target - if !targetMatches(unit, record) { - continue - } - - // check headers - switch val := matchFilters(unit.hdrSrc, record.Filters()); { - case val < 0: - // headers of some type could not be composed => allow - return eacl.ActionAllow - case val == 0: - return record.Action() - } - } - - return eacl.ActionAllow -} - -// returns: -// - positive value if no matching header is found for at least one filter; -// - zero if at least one suitable header is found for all filters; -// - negative value if the headers of at least one filter cannot be obtained. -func matchFilters(hdrSrc TypedHeaderSource, filters []*eacl.Filter) int { - matched := 0 - - for _, filter := range filters { - headers, ok := hdrSrc.HeadersOfType(filter.From()) - if !ok { - return -1 - } - - // get headers of filtering type - for _, header := range headers { - // prevent NPE - if header == nil { - continue - } - - // check header name - if header.Key() != filter.Key() { - continue - } - - // get match function - matchFn, ok := mMatchFns[filter.Matcher()] - if !ok { - continue - } - - // check match - if !matchFn(header, filter) { - continue - } - - // increment match counter - matched++ - - break - } - } - - return len(filters) - matched -} - -// returns true if one of ExtendedACLTarget has -// suitable target OR suitable public key. -func targetMatches(unit *ValidationUnit, record *eacl.Record) bool { - for _, target := range record.Targets() { - // check public key match - if pubs := target.BinaryKeys(); len(pubs) != 0 { - for _, key := range pubs { - if bytes.Equal(key, unit.key) { - return true - } - } - continue - } - - // check target group match - if unit.role == target.Role() { - return true - } - } - - return false -} - -// Maps match type to corresponding function. -var mMatchFns = map[eacl.Match]func(Header, *eacl.Filter) bool{ - eacl.MatchStringEqual: func(header Header, filter *eacl.Filter) bool { - return header.Value() == filter.Value() - }, - - eacl.MatchStringNotEqual: func(header Header, filter *eacl.Filter) bool { - return header.Value() != filter.Value() - }, -} diff --git a/pkg/services/object/acl/eacl/validator_test.go b/pkg/services/object/acl/eacl/validator_test.go deleted file mode 100644 index adb31f3f1..000000000 --- a/pkg/services/object/acl/eacl/validator_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package eacl - -import ( - "math/rand" - "testing" - - "github.com/nspcc-dev/neofs-sdk-go/eacl" - "github.com/stretchr/testify/require" -) - -func TestTargetMatches(t *testing.T) { - pubs := make([][]byte, 3) - for i := range pubs { - pubs[i] = make([]byte, 33) - pubs[i][0] = 0x02 - - _, err := rand.Read(pubs[i][1:]) - require.NoError(t, err) - } - - tgt1 := eacl.NewTarget() - tgt1.SetBinaryKeys(pubs[0:2]) - tgt1.SetRole(eacl.RoleUser) - - tgt2 := eacl.NewTarget() - tgt2.SetRole(eacl.RoleOthers) - - r := eacl.NewRecord() - r.SetTargets(tgt1, tgt2) - - u := newValidationUnit(eacl.RoleUser, pubs[0]) - require.True(t, targetMatches(u, r)) - - u = newValidationUnit(eacl.RoleUser, pubs[2]) - require.False(t, targetMatches(u, r)) - - u = newValidationUnit(eacl.RoleUnknown, pubs[1]) - require.True(t, targetMatches(u, r)) - - u = newValidationUnit(eacl.RoleOthers, pubs[2]) - require.True(t, targetMatches(u, r)) - - u = newValidationUnit(eacl.RoleSystem, pubs[2]) - require.False(t, targetMatches(u, r)) -} - -func newValidationUnit(role eacl.Role, key []byte) *ValidationUnit { - return &ValidationUnit{ - role: role, - key: key, - } -} diff --git a/pkg/services/object/acl/opts.go b/pkg/services/object/acl/opts.go index 85bae0520..3d51c3d5f 100644 --- a/pkg/services/object/acl/opts.go +++ b/pkg/services/object/acl/opts.go @@ -29,10 +29,10 @@ func WithNextService(v objectSvc.ServiceServer) Option { } } -// WithEACLValidatorOptions returns options to set eACL validator options. -func WithEACLValidatorOptions(v ...eacl.Option) Option { +// WithEACLSource returns options to set eACL table source. +func WithEACLSource(v eacl.Source) Option { return func(c *cfg) { - c.eACLOpts = v + c.eACLCfg.eaclSource = v } }