69d8b9f828
* uplink: Add a new flag to set the filepath of the file which is used for saving the encryption key and rename the one that hold the encryption key and establish that it has priority over the key stored in the file to make the configuration usable without having a huge refactoring in test-sim. * cmd/uplink: Adapt the setup subcommand for storing the user input key to a file and adapt the rest of the subcommands for reading the key from the key-file when the key isn't explicitly set with a command line flag. * cmd/gateway: Adapt it to read the encryption key from the key-file or use the one passed by a command line flag. * pkg/process: Export the default configuration filename so other packages which use the same value can reference to it rather than having it hardcoded. * Adapt several integrations (scripts, etc.) to consider the changes applied in uplink and cmd packages.
239 lines
5.8 KiB
Go
239 lines
5.8 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package miniogw_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"flag"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/minio/cli"
|
|
minio "github.com/minio/minio/cmd"
|
|
"github.com/spf13/pflag"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zaptest"
|
|
|
|
"storj.io/storj/internal/s3client"
|
|
"storj.io/storj/internal/testcontext"
|
|
"storj.io/storj/internal/testidentity"
|
|
"storj.io/storj/internal/testplanet"
|
|
libuplink "storj.io/storj/lib/uplink"
|
|
"storj.io/storj/pkg/cfgstruct"
|
|
"storj.io/storj/pkg/identity"
|
|
"storj.io/storj/pkg/miniogw"
|
|
"storj.io/storj/pkg/storj"
|
|
"storj.io/storj/satellite/console"
|
|
"storj.io/storj/uplink"
|
|
)
|
|
|
|
type config struct {
|
|
Server miniogw.ServerConfig
|
|
Minio miniogw.MinioConfig
|
|
}
|
|
|
|
func TestUploadDownload(t *testing.T) {
|
|
t.Skip("disable because, keeps stalling CI intermittently")
|
|
|
|
ctx := testcontext.New(t)
|
|
defer ctx.Cleanup()
|
|
|
|
planet, err := testplanet.New(t, 1, 30, 0)
|
|
assert.NoError(t, err)
|
|
|
|
defer ctx.Check(planet.Shutdown)
|
|
|
|
// add project to satisfy constraint
|
|
project, err := planet.Satellites[0].DB.Console().Projects().Insert(context.Background(), &console.Project{
|
|
Name: "testProject",
|
|
})
|
|
|
|
assert.NoError(t, err)
|
|
|
|
apiKey := console.APIKey{}
|
|
apiKeyInfo := console.APIKeyInfo{
|
|
ProjectID: project.ID,
|
|
Name: "testKey",
|
|
}
|
|
|
|
// add api key to db
|
|
_, err = planet.Satellites[0].DB.Console().APIKeys().Create(context.Background(), apiKey, apiKeyInfo)
|
|
assert.NoError(t, err)
|
|
|
|
// bind default values to config
|
|
var gwCfg config
|
|
cfgstruct.Bind(&pflag.FlagSet{}, &gwCfg, cfgstruct.UseDevDefaults())
|
|
var uplinkCfg uplink.Config
|
|
cfgstruct.Bind(&pflag.FlagSet{}, &uplinkCfg, cfgstruct.UseDevDefaults())
|
|
|
|
// minio config directory
|
|
gwCfg.Minio.Dir = ctx.Dir("minio")
|
|
|
|
// addresses
|
|
gwCfg.Server.Address = "127.0.0.1:7777"
|
|
uplinkCfg.Client.SatelliteAddr = planet.Satellites[0].Addr()
|
|
|
|
// keys
|
|
uplinkCfg.Client.APIKey = "apiKey"
|
|
|
|
// Encryption key
|
|
passphrase := make([]byte, rand.Intn(100)+1)
|
|
_, err = rand.Read(passphrase)
|
|
require.NoError(t, err)
|
|
|
|
encryptionKey, err := storj.NewKey(passphrase)
|
|
require.NoError(t, err)
|
|
filename := ctx.File("encryption.key")
|
|
err = ioutil.WriteFile(filename, encryptionKey[:], os.FileMode(0400))
|
|
require.NoError(t, err)
|
|
uplinkCfg.Enc.KeyFilepath = filename
|
|
|
|
// redundancy
|
|
uplinkCfg.RS.MinThreshold = 7
|
|
uplinkCfg.RS.RepairThreshold = 8
|
|
uplinkCfg.RS.SuccessThreshold = 9
|
|
uplinkCfg.RS.MaxThreshold = 10
|
|
|
|
planet.Start(ctx)
|
|
|
|
// create identity for gateway
|
|
ca, err := testidentity.NewTestCA(ctx)
|
|
assert.NoError(t, err)
|
|
identity, err := ca.NewIdentity()
|
|
assert.NoError(t, err)
|
|
|
|
// setup and start gateway
|
|
go func() {
|
|
// TODO: this leaks the gateway server, however it shouldn't
|
|
err := runGateway(ctx, gwCfg, uplinkCfg, zaptest.NewLogger(t), identity)
|
|
if err != nil {
|
|
t.Log(err)
|
|
}
|
|
}()
|
|
|
|
time.Sleep(100 * time.Millisecond)
|
|
|
|
client, err := s3client.NewMinio(s3client.Config{
|
|
S3Gateway: gwCfg.Server.Address,
|
|
Satellite: planet.Satellites[0].Addr(),
|
|
AccessKey: gwCfg.Minio.AccessKey,
|
|
SecretKey: gwCfg.Minio.SecretKey,
|
|
APIKey: uplinkCfg.Client.APIKey,
|
|
EncryptionKey: string(encryptionKey[:]),
|
|
NoSSL: true,
|
|
})
|
|
assert.NoError(t, err)
|
|
|
|
bucket := "bucket"
|
|
|
|
err = client.MakeBucket(bucket, "")
|
|
assert.NoError(t, err)
|
|
|
|
// generate enough data for a remote segment
|
|
data := []byte{}
|
|
for i := 0; i < 5000; i++ {
|
|
data = append(data, 'a')
|
|
}
|
|
|
|
objectName := "testdata"
|
|
|
|
err = client.Upload(bucket, objectName, data)
|
|
assert.NoError(t, err)
|
|
|
|
buffer := make([]byte, len(data))
|
|
|
|
bytes, err := client.Download(bucket, objectName, buffer)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, string(data), string(bytes))
|
|
}
|
|
|
|
// runGateway creates and starts a gateway
|
|
func runGateway(ctx context.Context, gwCfg config, uplinkCfg uplink.Config, log *zap.Logger, ident *identity.FullIdentity) (err error) {
|
|
|
|
// set gateway flags
|
|
flags := flag.NewFlagSet("gateway", flag.ExitOnError)
|
|
flags.String("address", gwCfg.Server.Address, "")
|
|
flags.String("config-dir", gwCfg.Minio.Dir, "")
|
|
flags.Bool("quiet", true, "")
|
|
|
|
// create *cli.Context with gateway flags
|
|
cliCtx := cli.NewContext(cli.NewApp(), flags, nil)
|
|
|
|
// TODO: setting the flag on flagset and cliCtx seems redundant, but output is not quiet otherwise
|
|
err = cliCtx.Set("quiet", "true")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = os.Setenv("MINIO_ACCESS_KEY", gwCfg.Minio.AccessKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = os.Setenv("MINIO_SECRET_KEY", gwCfg.Minio.SecretKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
cfg := libuplink.Config{}
|
|
cfg.Volatile.TLS = struct {
|
|
SkipPeerCAWhitelist bool
|
|
PeerCAWhitelistPath string
|
|
}{
|
|
SkipPeerCAWhitelist: !uplinkCfg.TLS.UsePeerCAWhitelist,
|
|
PeerCAWhitelistPath: uplinkCfg.TLS.PeerCAWhitelistPath,
|
|
}
|
|
cfg.Volatile.MaxInlineSize = uplinkCfg.Client.MaxInlineSize
|
|
cfg.Volatile.MaxMemory = uplinkCfg.RS.MaxBufferMem
|
|
|
|
uplink, err := libuplink.NewUplink(ctx, &cfg)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
apiKey, err := libuplink.ParseAPIKey(uplinkCfg.Client.APIKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var encKey *storj.Key
|
|
{
|
|
rawKey, err := ioutil.ReadFile(uplinkCfg.Enc.KeyFilepath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
encKey, err = storj.NewKey(rawKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
var projectOptions libuplink.ProjectOptions
|
|
projectOptions.Volatile.EncryptionKey = encKey
|
|
project, err := uplink.OpenProject(ctx, uplinkCfg.Client.SatelliteAddr, apiKey, &projectOptions)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
gw := miniogw.NewStorjGateway(
|
|
project,
|
|
encKey,
|
|
storj.Cipher(uplinkCfg.Enc.PathType).ToCipherSuite(),
|
|
uplinkCfg.GetEncryptionScheme().ToEncryptionParameters(),
|
|
uplinkCfg.GetRedundancyScheme(),
|
|
uplinkCfg.Client.SegmentSize,
|
|
)
|
|
|
|
minio.StartGateway(cliCtx, miniogw.Logging(gw, log))
|
|
return errors.New("unexpected minio exit")
|
|
}
|