Airat Arifullin
9b13a18aac
* Update version within go.mod; * Fix deprecated frostfs-api-go/v2 package and use frostfs-sdk-go/api instead. Signed-off-by: Airat Arifullin <a.arifullin@yadro.com>
76 lines
2 KiB
Go
76 lines
2 KiB
Go
package util
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"errors"
|
|
"fmt"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/session"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/api/signature"
|
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
|
)
|
|
|
|
type RequestMessage interface {
|
|
GetMetaHeader() *session.RequestMetaHeader
|
|
}
|
|
|
|
// ResponseMessage is an interface of FrostFS response message.
|
|
type ResponseMessage interface {
|
|
GetMetaHeader() *session.ResponseMetaHeader
|
|
SetMetaHeader(*session.ResponseMetaHeader)
|
|
}
|
|
|
|
type SignService struct {
|
|
key *ecdsa.PrivateKey
|
|
}
|
|
|
|
var ErrAbortStream = errors.New("abort message stream")
|
|
|
|
func NewUnarySignService(key *ecdsa.PrivateKey) *SignService {
|
|
return &SignService{
|
|
key: key,
|
|
}
|
|
}
|
|
|
|
// SignResponse response with private key via signature.SignServiceMessage.
|
|
// The signature error affects the result depending on the protocol version:
|
|
// - if status return is supported, panics since we cannot return the failed status, because it will not be signed.
|
|
// - otherwise, returns error in order to transport it directly.
|
|
func (s *SignService) SignResponse(resp ResponseMessage, err error) error {
|
|
if err != nil {
|
|
setStatusV2(resp, err)
|
|
}
|
|
|
|
err = signature.SignServiceMessage(s.key, resp)
|
|
if err != nil {
|
|
return fmt.Errorf("could not sign response: %w", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *SignService) VerifyRequest(req RequestMessage) error {
|
|
if err := signature.VerifyServiceMessage(req); err != nil {
|
|
sigErr := new(apistatus.SignatureVerification)
|
|
sigErr.SetMessage(err.Error())
|
|
return sigErr
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// EnsureNonNilResponse creates an appropriate response struct if it is nil.
|
|
func EnsureNonNilResponse[T any](resp *T, err error) (*T, error) {
|
|
if resp != nil {
|
|
return resp, err
|
|
}
|
|
return new(T), err
|
|
}
|
|
|
|
func setStatusV2(resp ResponseMessage, err error) {
|
|
// unwrap error
|
|
for e := errors.Unwrap(err); e != nil; e = errors.Unwrap(err) {
|
|
err = e
|
|
}
|
|
|
|
session.SetStatus(resp, apistatus.ToStatusV2(apistatus.ErrToStatus(err)))
|
|
}
|