frostfs-s3-gw/neofs/layer/util.go
2020-07-03 16:58:49 +03:00

147 lines
3 KiB
Go

package layer
import (
"context"
"crypto/ecdsa"
"strings"
"time"
"github.com/gogo/protobuf/proto"
minio "github.com/minio/minio/cmd"
"github.com/minio/minio/neofs/pool"
"github.com/nspcc-dev/neofs-api-go/object"
"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"
)
type (
tokenParams struct {
cli pool.Client
key *ecdsa.PrivateKey
until uint64
}
queryParams struct {
key *ecdsa.PrivateKey
addr refs.Address
verb service.Token_Info_Verb
}
)
// APIVersion of the neofs
const APIVersion = 1
func userHeaders(h []object.Header) map[string]string {
result := make(map[string]string, len(h))
for i := range h {
switch v := h[i].Value.(type) {
case *object.Header_UserHeader:
result[v.UserHeader.Key] = v.UserHeader.Value
default:
continue
}
}
return result
}
func objectInfoFromMeta(meta *object.Object) minio.ObjectInfo {
aws3name := meta.SystemHeader.ID.String()
userHeaders := userHeaders(meta.Headers)
if name, ok := userHeaders[AWS3NameHeader]; ok {
aws3name = name
delete(userHeaders, name)
}
oi := minio.ObjectInfo{
Bucket: meta.SystemHeader.CID.String(),
Name: aws3name,
ModTime: time.Unix(meta.SystemHeader.CreatedAt.UnixTime, 0),
Size: int64(meta.SystemHeader.PayloadLength),
ETag: "", // ?
ContentType: "", // ?
UserDefined: userHeaders,
UserTags: "", // ignore it
}
return oi
}
func generateToken(ctx context.Context, p tokenParams) (*service.Token, error) {
owner, err := refs.NewOwnerID(&p.key.PublicKey)
if err != nil {
return nil, err
}
token := new(service.Token)
token.SetOwnerID(owner)
token.SetExpirationEpoch(p.until)
token.SetOwnerKey(crypto.MarshalPublicKey(&p.key.PublicKey))
conn, err := p.cli.GetConnection(ctx)
if err != nil {
return nil, err
}
creator, err := session.NewGRPCCreator(conn, p.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) {
token := proto.Clone(t).(*service.Token)
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
}
func parseUserHeaders(h map[string]string) []object.Header {
headers := make([]object.Header, 0, len(h))
for k, v := range h {
uh := &object.UserHeader{Key: k, Value: v}
headers = append(headers, object.Header{
Value: &object.Header_UserHeader{UserHeader: uh},
})
}
return headers
}
func nameFromObject(o *object.Object) (string, string) {
var (
name string
uh = userHeaders(o.Headers)
)
if _, ok := uh[AWS3NameHeader]; !ok {
name = o.SystemHeader.ID.String()
} else {
name = uh[AWS3NameHeader]
}
ind := strings.LastIndex(name, SlashSeparator)
return name[ind+1:], name[:ind+1]
}