[#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 <carpawell@nspcc.ru>
This commit is contained in:
Pavel Karpy 2022-11-10 20:46:52 +03:00 committed by fyrchik
parent 2522d924b9
commit aadd2ad050
5 changed files with 22 additions and 15 deletions

View file

@ -21,7 +21,8 @@ Changelog for NeoFS Node
- `neofs-cli lock object`'s `lifetime` flag handling (#1972) - `neofs-cli lock object`'s `lifetime` flag handling (#1972)
- Do not move write-cache in read-only mode for flushing (#1906) - Do not move write-cache in read-only mode for flushing (#1906)
- Child object collection on CLI side with a bearer token (#2000) - 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 ### Removed
### Updated ### Updated

View file

@ -1,18 +1,24 @@
package v2 package v2
import ( import (
"errors"
"fmt" "fmt"
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" 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 ( var (
// ErrMalformedRequest is returned when request contains errEmptyBody = malformedRequestError("empty body")
// invalid data. errEmptyVerificationHeader = malformedRequestError("empty verification header")
ErrMalformedRequest = errors.New("malformed request") errEmptyBodySig = malformedRequestError("empty at body signature")
// ErrInvalidVerb is returned when session token verb doesn't include necessary operation. errInvalidSessionSig = malformedRequestError("invalid session token signature")
ErrInvalidVerb = errors.New("session token verb is invalid") 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" const accessDeniedACLReasonFmt = "access to operation %s is denied by basic ACL check"

View file

@ -110,7 +110,7 @@ type MetaWithToken struct {
// according to internal meta information. // according to internal meta information.
func (r MetaWithToken) RequestOwner() (*user.ID, *keys.PublicKey, error) { func (r MetaWithToken) RequestOwner() (*user.ID, *keys.PublicKey, error) {
if r.vheader == nil { 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 // 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 // otherwise get original body signature
bodySignature := originalBodySignature(r.vheader) bodySignature := originalBodySignature(r.vheader)
if bodySignature == nil { if bodySignature == nil {
return nil, nil, fmt.Errorf("%w: nil at body signature", ErrMalformedRequest) return nil, nil, errEmptyBodySig
} }
key, err := unmarshalPublicKey(bodySignature.GetKey()) key, err := unmarshalPublicKey(bodySignature.GetKey())

View file

@ -445,7 +445,7 @@ func (b Service) GetRangeHash(
func (p putStreamBasicChecker) Send(request *objectV2.PutRequest) error { func (p putStreamBasicChecker) Send(request *objectV2.PutRequest) error {
body := request.GetBody() body := request.GetBody()
if body == nil { if body == nil {
return ErrMalformedRequest return errEmptyBody
} }
part := body.GetObjectPart() 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") return info, errors.New("can't fetch current epoch")
} }
if req.token.ExpiredAt(currentEpoch) { if req.token.ExpiredAt(currentEpoch) {
return info, fmt.Errorf("%w: token has expired (current epoch: %d)", return info, fmt.Errorf("%s: token has expired (current epoch: %d)",
ErrMalformedRequest, currentEpoch) invalidRequestMessage, currentEpoch)
} }
if !assertVerb(*req.token, op) { if !assertVerb(*req.token, op) {
return info, ErrInvalidVerb return info, errInvalidVerb
} }
} }

View file

@ -114,7 +114,7 @@ func getObjectIDFromRequestBody(body interface{ GetAddress() *refsV2.Address })
func ownerFromToken(token *sessionSDK.Object) (*user.ID, *keys.PublicKey, error) { func ownerFromToken(token *sessionSDK.Object) (*user.ID, *keys.PublicKey, error) {
// 1. First check signature of session token. // 1. First check signature of session token.
if !token.VerifySignature() { 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 // 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) { if !isOwnerFromKey(tokenIssuer, tokenIssuerKey) {
// TODO: #767 in this case we can issue all owner keys from neofs.id and check once again // 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 return &tokenIssuer, tokenIssuerKey, nil