diff --git a/CHANGELOG.md b/CHANGELOG.md index ca5130c251..5fcfb0404d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ Changelog for NeoFS Node - Add objects sanity checker to neofs-lens (#2506) - Support for 0.20.0+ neofs-contract archive format (#2872) - `neofs-cli control object status` command (#2886) +- Check the account alongside the public key in ACL (#2883) ### Fixed - Control service's Drop call does not clean metabase (#2822) diff --git a/pkg/services/object/acl/acl.go b/pkg/services/object/acl/acl.go index 423f7360ac..60e19dda9c 100644 --- a/pkg/services/object/acl/acl.go +++ b/pkg/services/object/acl/acl.go @@ -194,14 +194,19 @@ func (c *Checker) CheckEACL(msg any, reqInfo v2.RequestInfo) error { eaclRole = eaclSDK.RoleOthers } - action, _ := c.validator.CalculateAction(new(eaclSDK.ValidationUnit). + vu := new(eaclSDK.ValidationUnit). WithRole(eaclRole). WithOperation(eaclSDK.Operation(reqInfo.Operation())). WithContainerID(&cnr). WithSenderKey(reqInfo.SenderKey()). WithHeaderSource(hdrSrc). - WithEACLTable(&table), - ) + WithEACLTable(&table) + + if sa := reqInfo.SenderAccount(); sa != nil && !sa.IsZero() { + vu.WithAccount(*sa) + } + + action, _ := c.validator.CalculateAction(vu) if action != eaclSDK.ActionAllow { return errEACLDeniedByRule diff --git a/pkg/services/object/acl/v2/classifier.go b/pkg/services/object/acl/v2/classifier.go index c08d0b9667..3d48f9747d 100644 --- a/pkg/services/object/acl/v2/classifier.go +++ b/pkg/services/object/acl/v2/classifier.go @@ -8,6 +8,7 @@ import ( "github.com/nspcc-dev/neofs-sdk-go/container/acl" cid "github.com/nspcc-dev/neofs-sdk-go/container/id" "github.com/nspcc-dev/neofs-sdk-go/netmap" + "github.com/nspcc-dev/neofs-sdk-go/user" "go.uber.org/zap" ) @@ -18,8 +19,9 @@ type senderClassifier struct { } type classifyResult struct { - role acl.Role - key []byte + role acl.Role + key []byte + account *user.ID } func (c senderClassifier) classify( @@ -38,8 +40,9 @@ func (c senderClassifier) classify( // if request owner is the same as container owner, return RoleUser if ownerID.Equals(cnr.Owner()) { return &classifyResult{ - role: acl.RoleOwner, - key: ownerKey, + role: acl.RoleOwner, + key: ownerKey, + account: ownerID, }, nil } @@ -50,8 +53,9 @@ func (c senderClassifier) classify( zap.String("error", err.Error())) } else if isInnerRingNode { return &classifyResult{ - role: acl.RoleInnerRing, - key: ownerKey, + role: acl.RoleInnerRing, + key: ownerKey, + account: ownerID, }, nil } @@ -64,15 +68,17 @@ func (c senderClassifier) classify( zap.String("error", err.Error())) } else if isContainerNode { return &classifyResult{ - role: acl.RoleContainer, - key: ownerKey, + role: acl.RoleContainer, + key: ownerKey, + account: ownerID, }, nil } // if none of above, return RoleOthers return &classifyResult{ - role: acl.RoleOthers, - key: ownerKey, + role: acl.RoleOthers, + key: ownerKey, + account: ownerID, }, nil } diff --git a/pkg/services/object/acl/v2/request.go b/pkg/services/object/acl/v2/request.go index 16985a83e6..ff74351f89 100644 --- a/pkg/services/object/acl/v2/request.go +++ b/pkg/services/object/acl/v2/request.go @@ -29,7 +29,8 @@ type RequestInfo struct { // e.g. Put, Search obj *oid.ID - senderKey []byte + senderKey []byte + senderAccount *user.ID bearer *bearer.Token // bearer token of request @@ -88,6 +89,11 @@ func (r RequestInfo) SenderKey() []byte { return r.senderKey } +// SenderAccount returns account of the request's sender. +func (r RequestInfo) SenderAccount() *user.ID { + return r.senderAccount +} + // Operation returns request's operation. func (r RequestInfo) Operation() acl.Op { return r.operation diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index 2ed3ef880c..c8a34cd581 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -628,6 +628,7 @@ func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (in // it is assumed that at the moment the key will be valid, // otherwise the request would not pass validation info.senderKey = res.key + info.senderAccount = res.account // add bearer token if it is present in request info.bearer = req.bearer