forked from TrueCloudLab/frostfs-s3-gw
148 lines
3 KiB
Go
148 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]
|
||
|
}
|