frostfs-s3-gw/neofs/api/handler/api.go
2020-07-24 19:10:41 +03:00

131 lines
2.6 KiB
Go

package handler
import (
"context"
"crypto/ecdsa"
"math"
"github.com/minio/minio/neofs/api"
"github.com/minio/minio/neofs/pool"
"github.com/nspcc-dev/neofs-api-go/refs"
"github.com/nspcc-dev/neofs-api-go/service"
"github.com/nspcc-dev/neofs-api-go/session"
crypto "github.com/nspcc-dev/neofs-crypto"
"github.com/pkg/errors"
"go.uber.org/zap"
)
type (
handler struct {
log *zap.Logger
cli pool.Client
uid refs.OwnerID
tkn *service.Token
key *ecdsa.PrivateKey
}
Params struct {
Cli pool.Client
Log *zap.Logger
Key *ecdsa.PrivateKey
}
queryParams struct {
key *ecdsa.PrivateKey
addr refs.Address
verb service.Token_Info_Verb
}
)
var _ api.Handler = (*handler)(nil)
func New(ctx context.Context, p Params) (api.Handler, error) {
var (
err error
uid refs.OwnerID
tkn *service.Token
)
switch {
case p.Key == nil:
return nil, errors.New("empty private key")
case p.Cli == nil:
return nil, errors.New("empty gRPC client")
case p.Log == nil:
return nil, errors.New("empty logger")
}
if uid, err = refs.NewOwnerID(&p.Key.PublicKey); err != nil {
return nil, errors.Wrap(err, "could not fetch OwnerID")
} else if tkn, err = generateToken(ctx, p.Cli, p.Key); err != nil {
return nil, errors.Wrap(err, "could not prepare session token")
}
return &handler{
uid: uid,
tkn: tkn,
key: p.Key,
log: p.Log,
cli: p.Cli,
}, nil
}
func generateToken(ctx context.Context, cli pool.Client, key *ecdsa.PrivateKey) (*service.Token, error) {
owner, err := refs.NewOwnerID(&key.PublicKey)
if err != nil {
return nil, err
}
token := new(service.Token)
token.SetOwnerID(owner)
token.SetExpirationEpoch(math.MaxUint64)
token.SetOwnerKey(crypto.MarshalPublicKey(&key.PublicKey))
conn, err := cli.GetConnection(ctx)
if err != nil {
return nil, err
}
creator, err := session.NewGRPCCreator(conn, key)
if err != nil {
return nil, err
}
res, err := creator.Create(ctx, token)
if err != nil {
return nil, err
}
token.SetID(res.GetID())
token.SetSessionKey(res.GetSessionKey())
return token, nil
}
func prepareToken(t *service.Token, p queryParams) (*service.Token, error) {
sig := make([]byte, len(t.Signature))
copy(sig, t.Signature)
token := &service.Token{
Token_Info: service.Token_Info{
ID: t.ID,
OwnerID: t.OwnerID,
Verb: t.Verb,
Address: t.Address,
TokenLifetime: t.TokenLifetime,
SessionKey: t.SessionKey,
OwnerKey: t.OwnerKey,
},
Signature: sig,
}
token.SetAddress(p.addr)
token.SetVerb(p.verb)
err := service.AddSignatureWithKey(p.key, service.NewSignedSessionToken(token))
if err != nil {
return nil, err
}
return token, nil
}