2020-07-03 13:52:04 +00:00
|
|
|
package layer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"math"
|
|
|
|
"time"
|
|
|
|
|
2020-07-09 09:23:09 +00:00
|
|
|
minio "github.com/minio/minio/legacy"
|
2020-07-03 13:52:04 +00:00
|
|
|
"github.com/minio/minio/neofs/pool"
|
|
|
|
"github.com/minio/minio/pkg/auth"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/chain"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/refs"
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/service"
|
|
|
|
crypto "github.com/nspcc-dev/neofs-crypto"
|
2020-07-07 11:31:55 +00:00
|
|
|
"github.com/pkg/errors"
|
2020-07-13 11:23:23 +00:00
|
|
|
"go.uber.org/zap"
|
2020-07-03 13:52:04 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// neofsObjects implements gateway for MinIO and S3
|
|
|
|
// compatible object storage server.
|
|
|
|
neofsObject struct {
|
|
|
|
minio.GatewayUnsupported // placeholder for unimplemented functions
|
|
|
|
|
|
|
|
cli pool.Client
|
2020-07-13 11:23:23 +00:00
|
|
|
log *zap.Logger
|
2020-07-03 13:52:04 +00:00
|
|
|
key *ecdsa.PrivateKey
|
|
|
|
owner refs.OwnerID
|
|
|
|
token *service.Token
|
|
|
|
|
|
|
|
// Concurrency must be resolved by creating one lock per object, but
|
|
|
|
// it may be unnecessary in neofs, because objects are immutable. So
|
|
|
|
// there are no any mutexes and locks right now but it might be
|
|
|
|
// useful during parallel execution from one client (different clients
|
|
|
|
// have different `neofsObject` instances).
|
|
|
|
|
|
|
|
// todo: add fast expired cache to store list of containers or
|
|
|
|
// even short objects during sequential reading
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
// NewGatewayLayer creates instance of neofsObject. It checks credentials
|
|
|
|
// and establishes gRPC connection with node.
|
2020-07-13 11:23:23 +00:00
|
|
|
func NewLayer(cli pool.Client, log *zap.Logger, cred auth.Credentials) (minio.ObjectLayer, error) {
|
2020-07-03 13:52:04 +00:00
|
|
|
// check if wif is correct
|
|
|
|
key, err := crypto.WIFDecode(cred.SecretKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("can't decode secret key, it must be WIF")
|
|
|
|
}
|
|
|
|
// check if wif corresponds wallet address
|
|
|
|
if cred.AccessKey != chain.KeysToAddress(&key.PublicKey) {
|
|
|
|
return nil, errors.New("wif and wallet are not corresponded")
|
|
|
|
}
|
|
|
|
// format public key into owner
|
|
|
|
owner, err := refs.NewOwnerID(&key.PublicKey)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.New("can't create owner id from key")
|
|
|
|
}
|
|
|
|
|
|
|
|
// setup gRPC connection
|
|
|
|
// todo: think about getting timeout parameters from cli args
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
|
|
defer cancel()
|
|
|
|
|
|
|
|
token, err := generateToken(ctx, tokenParams{
|
|
|
|
cli: cli,
|
|
|
|
key: key,
|
|
|
|
until: math.MaxInt64,
|
|
|
|
})
|
|
|
|
if err != nil {
|
2020-07-07 11:31:55 +00:00
|
|
|
return nil, errors.Wrap(err, "can't establish neofs session with remote host")
|
2020-07-03 13:52:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return &neofsObject{
|
|
|
|
cli: cli,
|
|
|
|
key: key,
|
2020-07-13 11:23:23 +00:00
|
|
|
log: log,
|
2020-07-03 13:52:04 +00:00
|
|
|
owner: owner,
|
|
|
|
token: token,
|
|
|
|
}, nil
|
|
|
|
}
|