From aadd2ad050fc089f5eb1d254b36ae7c37c027506 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Thu, 10 Nov 2022 20:46:52 +0300 Subject: [PATCH] [#2028] node: Do not wrap malformed request errors After presenting request statuses on the API level, all the errors are unwrapped before sending to the caller side. It led to a losing invalid request's context. Signed-off-by: Pavel Karpy --- CHANGELOG.md | 3 ++- pkg/services/object/acl/v2/errors.go | 18 ++++++++++++------ pkg/services/object/acl/v2/request.go | 4 ++-- pkg/services/object/acl/v2/service.go | 8 ++++---- pkg/services/object/acl/v2/util.go | 4 ++-- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c616e31a..1efecd9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,8 @@ Changelog for NeoFS Node - `neofs-cli lock object`'s `lifetime` flag handling (#1972) - Do not move write-cache in read-only mode for flushing (#1906) - Child object collection on CLI side with a bearer token (#2000) -- Fix concurrent map writes in `Object.Put` service +- Fix concurrent map writes in `Object.Put` service (#2037) +- Malformed request errors' reasons in the responses (#2028) ### Removed ### Updated diff --git a/pkg/services/object/acl/v2/errors.go b/pkg/services/object/acl/v2/errors.go index 65167311..432894df 100644 --- a/pkg/services/object/acl/v2/errors.go +++ b/pkg/services/object/acl/v2/errors.go @@ -1,18 +1,24 @@ package v2 import ( - "errors" "fmt" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" ) +const invalidRequestMessage = "malformed request" + +func malformedRequestError(reason string) error { + return fmt.Errorf("%s: %s", invalidRequestMessage, reason) +} + var ( - // ErrMalformedRequest is returned when request contains - // invalid data. - ErrMalformedRequest = errors.New("malformed request") - // ErrInvalidVerb is returned when session token verb doesn't include necessary operation. - ErrInvalidVerb = errors.New("session token verb is invalid") + errEmptyBody = malformedRequestError("empty body") + errEmptyVerificationHeader = malformedRequestError("empty verification header") + errEmptyBodySig = malformedRequestError("empty at body signature") + errInvalidSessionSig = malformedRequestError("invalid session token signature") + errInvalidSessionOwner = malformedRequestError("invalid session token owner") + errInvalidVerb = malformedRequestError("session token verb is invalid") ) const accessDeniedACLReasonFmt = "access to operation %s is denied by basic ACL check" diff --git a/pkg/services/object/acl/v2/request.go b/pkg/services/object/acl/v2/request.go index 7eaf9bd0..550d670b 100644 --- a/pkg/services/object/acl/v2/request.go +++ b/pkg/services/object/acl/v2/request.go @@ -110,7 +110,7 @@ type MetaWithToken struct { // according to internal meta information. func (r MetaWithToken) RequestOwner() (*user.ID, *keys.PublicKey, error) { if r.vheader == nil { - return nil, nil, fmt.Errorf("%w: nil verification header", ErrMalformedRequest) + return nil, nil, errEmptyVerificationHeader } // if session token is presented, use it as truth source @@ -122,7 +122,7 @@ func (r MetaWithToken) RequestOwner() (*user.ID, *keys.PublicKey, error) { // otherwise get original body signature bodySignature := originalBodySignature(r.vheader) if bodySignature == nil { - return nil, nil, fmt.Errorf("%w: nil at body signature", ErrMalformedRequest) + return nil, nil, errEmptyBodySig } key, err := unmarshalPublicKey(bodySignature.GetKey()) diff --git a/pkg/services/object/acl/v2/service.go b/pkg/services/object/acl/v2/service.go index b2f7815a..b156e12f 100644 --- a/pkg/services/object/acl/v2/service.go +++ b/pkg/services/object/acl/v2/service.go @@ -445,7 +445,7 @@ func (b Service) GetRangeHash( func (p putStreamBasicChecker) Send(request *objectV2.PutRequest) error { body := request.GetBody() if body == nil { - return ErrMalformedRequest + return errEmptyBody } part := body.GetObjectPart() @@ -574,12 +574,12 @@ func (b Service) findRequestInfo(req MetaWithToken, idCnr cid.ID, op acl.Op) (in return info, errors.New("can't fetch current epoch") } if req.token.ExpiredAt(currentEpoch) { - return info, fmt.Errorf("%w: token has expired (current epoch: %d)", - ErrMalformedRequest, currentEpoch) + return info, fmt.Errorf("%s: token has expired (current epoch: %d)", + invalidRequestMessage, currentEpoch) } if !assertVerb(*req.token, op) { - return info, ErrInvalidVerb + return info, errInvalidVerb } } diff --git a/pkg/services/object/acl/v2/util.go b/pkg/services/object/acl/v2/util.go index ec94caf7..96e08348 100644 --- a/pkg/services/object/acl/v2/util.go +++ b/pkg/services/object/acl/v2/util.go @@ -114,7 +114,7 @@ func getObjectIDFromRequestBody(body interface{ GetAddress() *refsV2.Address }) func ownerFromToken(token *sessionSDK.Object) (*user.ID, *keys.PublicKey, error) { // 1. First check signature of session token. if !token.VerifySignature() { - return nil, nil, fmt.Errorf("%w: invalid session token signature", ErrMalformedRequest) + return nil, nil, errInvalidSessionSig } // 2. Then check if session token owner issued the session token @@ -131,7 +131,7 @@ func ownerFromToken(token *sessionSDK.Object) (*user.ID, *keys.PublicKey, error) if !isOwnerFromKey(tokenIssuer, tokenIssuerKey) { // TODO: #767 in this case we can issue all owner keys from neofs.id and check once again - return nil, nil, fmt.Errorf("%w: invalid session token owner", ErrMalformedRequest) + return nil, nil, errInvalidSessionOwner } return &tokenIssuer, tokenIssuerKey, nil