forked from TrueCloudLab/frostfs-s3-gw
189 lines
4.9 KiB
Go
189 lines
4.9 KiB
Go
package modules
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/authmate"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/frostfs/util"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/internal/logs"
|
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
"github.com/spf13/viper"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
type PoolConfig struct {
|
|
Key *keys.PrivateKey
|
|
Address string
|
|
DialTimeout time.Duration
|
|
HealthcheckTimeout time.Duration
|
|
StreamTimeout time.Duration
|
|
RebalanceInterval time.Duration
|
|
}
|
|
|
|
func createFrostFS(ctx context.Context, log *zap.Logger, cfg PoolConfig) (*frostfs.AuthmateFrostFS, error) {
|
|
log.Debug(logs.PrepareConnectionPool)
|
|
|
|
var prm pool.InitParameters
|
|
prm.SetKey(&cfg.Key.PrivateKey)
|
|
prm.SetNodeDialTimeout(cfg.DialTimeout)
|
|
prm.SetHealthcheckTimeout(cfg.HealthcheckTimeout)
|
|
prm.SetNodeStreamTimeout(cfg.StreamTimeout)
|
|
prm.SetClientRebalanceInterval(cfg.RebalanceInterval)
|
|
prm.SetLogger(log)
|
|
prm.AddNode(pool.NewNodeParam(1, cfg.Address, 1))
|
|
|
|
p, err := pool.NewPool(prm)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("create pool: %w", err)
|
|
}
|
|
|
|
if err = p.Dial(ctx); err != nil {
|
|
return nil, fmt.Errorf("dial pool: %w", err)
|
|
}
|
|
|
|
return frostfs.NewAuthmateFrostFS(frostfs.NewFrostFS(p, cfg.Key), log), nil
|
|
}
|
|
|
|
func parsePolicies(val string) (authmate.ContainerPolicies, error) {
|
|
if val == "" {
|
|
return nil, nil
|
|
}
|
|
|
|
var (
|
|
data = []byte(val)
|
|
err error
|
|
)
|
|
|
|
if !json.Valid(data) {
|
|
if data, err = os.ReadFile(val); err != nil {
|
|
return nil, fmt.Errorf("coudln't read json file or provided json is invalid")
|
|
}
|
|
}
|
|
|
|
var policies authmate.ContainerPolicies
|
|
if err = json.Unmarshal(data, &policies); err != nil {
|
|
return nil, fmt.Errorf("unmarshal policies: %w", err)
|
|
}
|
|
if _, ok := policies[api.DefaultLocationConstraint]; ok {
|
|
return nil, fmt.Errorf("config overrides %s location constraint", api.DefaultLocationConstraint)
|
|
}
|
|
|
|
return policies, nil
|
|
}
|
|
|
|
func getJSONRules(val string) ([]byte, error) {
|
|
if val == "" {
|
|
return nil, nil
|
|
}
|
|
data := []byte(val)
|
|
if json.Valid(data) {
|
|
return data, nil
|
|
}
|
|
|
|
if data, err := os.ReadFile(val); err == nil {
|
|
if json.Valid(data) {
|
|
return data, nil
|
|
}
|
|
}
|
|
|
|
return nil, fmt.Errorf("coudln't read json file or provided json is invalid")
|
|
}
|
|
|
|
// getSessionRules reads json session rules.
|
|
// It returns true if rules must be skipped.
|
|
func getSessionRules(r string) ([]byte, bool, error) {
|
|
if r == "none" {
|
|
return nil, true, nil
|
|
}
|
|
|
|
data, err := getJSONRules(r)
|
|
return data, false, err
|
|
}
|
|
|
|
// getLogger returns new logger depending on appropriate values in viper.Viper
|
|
// if logger cannot be built it panics.
|
|
func getLogger() *zap.Logger {
|
|
if !viper.GetBool(withLogFlag) {
|
|
return zap.NewNop()
|
|
}
|
|
|
|
var zapConfig = zap.Config{
|
|
Development: true,
|
|
Encoding: "console",
|
|
Level: zap.NewAtomicLevelAt(zapcore.FatalLevel),
|
|
OutputPaths: []string{"stdout"},
|
|
EncoderConfig: zapcore.EncoderConfig{
|
|
MessageKey: "message",
|
|
LevelKey: "level",
|
|
EncodeLevel: zapcore.CapitalLevelEncoder,
|
|
TimeKey: "time",
|
|
EncodeTime: zapcore.ISO8601TimeEncoder,
|
|
CallerKey: "caller",
|
|
EncodeCaller: zapcore.ShortCallerEncoder,
|
|
},
|
|
}
|
|
|
|
if viper.GetBool(debugFlag) {
|
|
zapConfig.Level = zap.NewAtomicLevelAt(zapcore.DebugLevel)
|
|
}
|
|
|
|
log, err := zapConfig.Build()
|
|
if err != nil {
|
|
panic(fmt.Errorf("create logger: %w", err))
|
|
}
|
|
|
|
return log
|
|
}
|
|
|
|
func parseObjectAttrs(attributes string) ([]object.Attribute, error) {
|
|
if len(attributes) == 0 {
|
|
return nil, nil
|
|
}
|
|
|
|
rawAttrs := strings.Split(attributes, ",")
|
|
|
|
attrs := make([]object.Attribute, len(rawAttrs))
|
|
for i := range rawAttrs {
|
|
k, v, found := strings.Cut(rawAttrs[i], "=")
|
|
if !found {
|
|
return nil, fmt.Errorf("invalid attribute format: %s", rawAttrs[i])
|
|
}
|
|
attrs[i].SetKey(k)
|
|
attrs[i].SetValue(v)
|
|
}
|
|
|
|
return attrs, nil
|
|
}
|
|
|
|
func getAccessBoxID() (cid.ID, string, bool, error) {
|
|
accessKeyID := viper.GetString(accessKeyIDFlag)
|
|
|
|
var accessBoxAddress oid.Address
|
|
if err := accessBoxAddress.DecodeString(strings.Replace(accessKeyID, "0", "/", 1)); err == nil {
|
|
return accessBoxAddress.Container(), accessKeyID, false, nil
|
|
}
|
|
|
|
if !viper.IsSet(containerIDFlag) {
|
|
return cid.ID{}, "", false, errors.New("accessbox parameter must be set when custom access key id is used")
|
|
}
|
|
|
|
accessBox, err := util.ResolveContainerID(viper.GetString(containerIDFlag), viper.GetString(rpcEndpointFlag))
|
|
if err != nil {
|
|
return cid.ID{}, "", false, fmt.Errorf("resolve accessbox container id (make sure you provided %s): %w", rpcEndpointFlag, err)
|
|
}
|
|
|
|
return accessBox, accessKeyID, true, nil
|
|
}
|