forked from TrueCloudLab/frostfs-s3-gw
106 lines
2.5 KiB
Go
106 lines
2.5 KiB
Go
|
package bearer
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"context"
|
||
|
"errors"
|
||
|
"strconv"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
sdk "github.com/nspcc-dev/cdn-sdk"
|
||
|
"github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||
|
"github.com/nspcc-dev/neofs-api-go/pkg/object"
|
||
|
"github.com/nspcc-dev/neofs-api-go/pkg/token"
|
||
|
"github.com/nspcc-dev/neofs-s3-gw/creds/hcs"
|
||
|
"github.com/nspcc-dev/neofs-s3-gw/creds/accessbox"
|
||
|
)
|
||
|
|
||
|
type (
|
||
|
Credentials interface {
|
||
|
Get(context.Context, *object.Address) (*token.BearerToken, error)
|
||
|
Put(context.Context, *container.ID, *token.BearerToken, ...hcs.PublicKey) (*object.Address, error)
|
||
|
}
|
||
|
|
||
|
cred struct {
|
||
|
key hcs.PrivateKey
|
||
|
obj sdk.ObjectClient
|
||
|
}
|
||
|
)
|
||
|
|
||
|
var (
|
||
|
ErrEmptyPublicKeys = errors.New("HCS public keys could not be empty")
|
||
|
ErrEmptyBearerToken = errors.New("Bearer token could not be empty")
|
||
|
)
|
||
|
|
||
|
var bufferPool = sync.Pool{
|
||
|
New: func() interface{} {
|
||
|
return new(bytes.Buffer)
|
||
|
},
|
||
|
}
|
||
|
|
||
|
var _ = New
|
||
|
|
||
|
func New(cli sdk.ObjectClient, key hcs.PrivateKey) Credentials {
|
||
|
return &cred{obj: cli, key: key}
|
||
|
}
|
||
|
|
||
|
func (c *cred) acquireBuffer() *bytes.Buffer {
|
||
|
return bufferPool.Get().(*bytes.Buffer)
|
||
|
}
|
||
|
|
||
|
func (c *cred) releaseBuffer(buf *bytes.Buffer) {
|
||
|
buf.Reset()
|
||
|
bufferPool.Put(buf)
|
||
|
}
|
||
|
|
||
|
func (c *cred) Get(ctx context.Context, address *object.Address) (*token.BearerToken, error) {
|
||
|
buf := c.acquireBuffer()
|
||
|
defer c.releaseBuffer(buf)
|
||
|
|
||
|
box := accessbox.NewBearerBox(nil)
|
||
|
|
||
|
if _, err := c.obj.Get(ctx, address, sdk.WithGetWriter(buf)); err != nil {
|
||
|
return nil, err
|
||
|
} else if err = accessbox.NewDecoder(buf, c.key).Decode(box); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return box.Token(), nil
|
||
|
}
|
||
|
|
||
|
func (c *cred) Put(ctx context.Context, cid *container.ID, tkn *token.BearerToken, keys ...hcs.PublicKey) (*object.Address, error) {
|
||
|
var (
|
||
|
err error
|
||
|
buf = c.acquireBuffer()
|
||
|
box = accessbox.NewBearerBox(tkn)
|
||
|
|
||
|
created = strconv.FormatInt(time.Now().Unix(), 10)
|
||
|
)
|
||
|
|
||
|
defer c.releaseBuffer(buf)
|
||
|
|
||
|
if len(keys) == 0 {
|
||
|
return nil, ErrEmptyPublicKeys
|
||
|
} else if tkn == nil {
|
||
|
return nil, ErrEmptyBearerToken
|
||
|
} else if err = accessbox.NewEncoder(buf, c.key, keys...).Encode(box); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
timestamp := object.NewAttribute()
|
||
|
timestamp.SetKey(object.AttributeTimestamp)
|
||
|
timestamp.SetValue(created)
|
||
|
|
||
|
filename := object.NewAttribute()
|
||
|
filename.SetKey(object.AttributeFileName)
|
||
|
filename.SetValue(created + "_access.box")
|
||
|
|
||
|
raw := object.NewRaw()
|
||
|
raw.SetContainerID(cid)
|
||
|
raw.SetOwnerID(tkn.Issuer())
|
||
|
raw.SetAttributes(filename, timestamp)
|
||
|
|
||
|
return c.obj.Put(ctx, raw.Object(), sdk.WithPutReader(buf))
|
||
|
}
|