[#380] creds: Increase test coverage #380
7 changed files with 511 additions and 16 deletions
|
@ -8,6 +8,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
||||||
|
@ -377,6 +378,43 @@ func (t *TestFrostFS) ContainerEACL(_ context.Context, prm PrmContainerEACL) (*e
|
||||||
return table, nil
|
return table, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TestFrostFS) SearchObjects(_ context.Context, prm PrmObjectSearch) ([]oid.ID, error) {
|
||||||
|
filters := object.NewSearchFilters()
|
||||||
|
filters.AddRootFilter()
|
||||||
|
|
||||||
|
if prm.ExactAttribute[0] != "" {
|
||||||
|
filters.AddFilter(prm.ExactAttribute[0], prm.ExactAttribute[1], object.MatchStringEqual)
|
||||||
|
}
|
||||||
|
|
||||||
|
cidStr := prm.Container.EncodeToString()
|
||||||
|
|
||||||
|
var res []oid.ID
|
||||||
|
|
||||||
|
if len(filters) == 1 {
|
||||||
|
for k, v := range t.objects {
|
||||||
|
if strings.Contains(k, cidStr) {
|
||||||
|
id, _ := v.ID()
|
||||||
|
res = append(res, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
filter := filters[1]
|
||||||
|
if len(filters) != 2 || filter.Operation() != object.MatchStringEqual {
|
||||||
|
return nil, fmt.Errorf("usupported filters")
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range t.objects {
|
||||||
|
if strings.Contains(k, cidStr) && isMatched(v.Attributes(), filter) {
|
||||||
|
id, _ := v.ID()
|
||||||
|
res = append(res, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (t *TestFrostFS) checkAccess(cnrID cid.ID, owner user.ID, op eacl.Operation, obj *object.Object) bool {
|
func (t *TestFrostFS) checkAccess(cnrID cid.ID, owner user.ID, op eacl.Operation, obj *object.Object) bool {
|
||||||
cnr, ok := t.containers[cnrID.EncodeToString()]
|
cnr, ok := t.containers[cnrID.EncodeToString()]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -448,3 +486,12 @@ func getBearerOwner(ctx context.Context) user.ID {
|
||||||
|
|
||||||
return user.ID{}
|
return user.ID{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isMatched(attributes []object.Attribute, filter object.SearchFilter) bool {
|
||||||
|
for _, attr := range attributes {
|
||||||
|
if attr.Key() == filter.Header() && attr.Value() == filter.Value() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ type PoolConfig struct {
|
||||||
RebalanceInterval time.Duration
|
RebalanceInterval time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFrostFS(ctx context.Context, log *zap.Logger, cfg PoolConfig) (authmate.FrostFS, error) {
|
func createFrostFS(ctx context.Context, log *zap.Logger, cfg PoolConfig) (*frostfs.AuthmateFrostFS, error) {
|
||||||
log.Debug(logs.PrepareConnectionPool)
|
log.Debug(logs.PrepareConnectionPool)
|
||||||
|
|
||||||
var prm pool.InitParameters
|
var prm pool.InitParameters
|
||||||
|
@ -51,7 +51,7 @@ func createFrostFS(ctx context.Context, log *zap.Logger, cfg PoolConfig) (authma
|
||||||
return nil, fmt.Errorf("dial pool: %w", err)
|
return nil, fmt.Errorf("dial pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return frostfs.NewAuthmateFrostFS(p, cfg.Key), nil
|
return frostfs.NewAuthmateFrostFS(frostfs.NewFrostFS(p, cfg.Key)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parsePolicies(val string) (authmate.ContainerPolicies, error) {
|
func parsePolicies(val string) (authmate.ContainerPolicies, error) {
|
||||||
|
|
|
@ -127,7 +127,7 @@ func newApp(ctx context.Context, log *Logger, v *viper.Viper) *App {
|
||||||
objPool, treePool, key := getPools(ctx, log.logger, v)
|
objPool, treePool, key := getPools(ctx, log.logger, v)
|
||||||
|
|
||||||
cfg := tokens.Config{
|
cfg := tokens.Config{
|
||||||
FrostFS: frostfs.NewAuthmateFrostFS(objPool, key),
|
FrostFS: frostfs.NewAuthmateFrostFS(frostfs.NewFrostFS(objPool, key)),
|
||||||
Key: key,
|
Key: key,
|
||||||
CacheConfig: getAccessBoxCacheConfig(v, log.logger),
|
CacheConfig: getAccessBoxCacheConfig(v, log.logger),
|
||||||
RemovingCheckAfterDurations: fetchRemovingCheckInterval(v, log.logger),
|
RemovingCheckAfterDurations: fetchRemovingCheckInterval(v, log.logger),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package accessbox
|
package accessbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/hex"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
|
@ -170,3 +171,148 @@ func TestUnknownKey(t *testing.T) {
|
||||||
_, err = box.GetTokens(wrongCred)
|
_, err = box.GetTokens(wrongCred)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGateDataSessionToken(t *testing.T) {
|
||||||
|
cred, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var tkn bearer.Token
|
||||||
|
gate := NewGateData(cred.PublicKey(), &tkn)
|
||||||
|
require.Equal(t, cred.PublicKey(), gate.GateKey)
|
||||||
|
assertBearerToken(t, tkn, *gate.BearerToken)
|
||||||
|
|
||||||
|
t.Run("session token for put", func(t *testing.T) {
|
||||||
|
gate.SessionTokens = []*session.Container{}
|
||||||
|
sessionTkn := gate.SessionTokenForPut()
|
||||||
|
require.Nil(t, sessionTkn)
|
||||||
|
|
||||||
|
sessionTknPut := new(session.Container)
|
||||||
|
sessionTknPut.ForVerb(session.VerbContainerPut)
|
||||||
|
gate.SessionTokens = []*session.Container{sessionTknPut}
|
||||||
|
sessionTkn = gate.SessionTokenForPut()
|
||||||
|
require.Equal(t, sessionTknPut, sessionTkn)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("session token for delete", func(t *testing.T) {
|
||||||
|
gate.SessionTokens = []*session.Container{}
|
||||||
|
sessionTkn := gate.SessionTokenForDelete()
|
||||||
|
require.Nil(t, sessionTkn)
|
||||||
|
|
||||||
|
sessionTknDelete := new(session.Container)
|
||||||
|
sessionTknDelete.ForVerb(session.VerbContainerDelete)
|
||||||
|
gate.SessionTokens = []*session.Container{sessionTknDelete}
|
||||||
|
sessionTkn = gate.SessionTokenForDelete()
|
||||||
|
require.Equal(t, sessionTknDelete, sessionTkn)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("session token for set eACL", func(t *testing.T) {
|
||||||
|
gate.SessionTokens = []*session.Container{}
|
||||||
|
sessionTkn := gate.SessionTokenForSetEACL()
|
||||||
|
require.Nil(t, sessionTkn)
|
||||||
|
|
||||||
|
sessionTknSetEACL := new(session.Container)
|
||||||
|
sessionTknSetEACL.ForVerb(session.VerbContainerSetEACL)
|
||||||
|
gate.SessionTokens = []*session.Container{sessionTknSetEACL}
|
||||||
|
sessionTkn = gate.SessionTokenForSetEACL()
|
||||||
|
require.Equal(t, sessionTknSetEACL, sessionTkn)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("session token", func(t *testing.T) {
|
||||||
|
gate.SessionTokens = []*session.Container{}
|
||||||
|
sessionTkn := gate.SessionToken()
|
||||||
|
require.Nil(t, sessionTkn)
|
||||||
|
|
||||||
|
sessionTknPut := new(session.Container)
|
||||||
|
sessionTknPut.ForVerb(session.VerbContainerPut)
|
||||||
|
gate.SessionTokens = []*session.Container{sessionTknPut}
|
||||||
|
sessionTkn = gate.SessionToken()
|
||||||
|
require.Equal(t, sessionTkn, sessionTknPut)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetBox(t *testing.T) {
|
||||||
|
cred, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var tkn bearer.Token
|
||||||
|
gate := NewGateData(cred.PublicKey(), &tkn)
|
||||||
|
|
||||||
|
secret := []byte("secret")
|
||||||
|
accessBox, _, err := PackTokens([]*GateData{gate}, secret)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
box, err := accessBox.GetBox(cred)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, hex.EncodeToString(secret), box.Gate.SecretKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccessBox(t *testing.T) {
|
||||||
|
cred, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var tkn bearer.Token
|
||||||
|
gate := NewGateData(cred.PublicKey(), &tkn)
|
||||||
|
|
||||||
|
accessBox, _, err := PackTokens([]*GateData{gate}, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
t.Run("invalid owner", func(t *testing.T) {
|
||||||
|
randomKey, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = accessBox.GetTokens(randomKey)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = accessBox.GetBox(randomKey)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty placement policy", func(t *testing.T) {
|
||||||
|
policy, err := accessBox.GetPlacementPolicy()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Nil(t, policy)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("get correct placement policy", func(t *testing.T) {
|
||||||
|
policy := &AccessBox_ContainerPolicy{LocationConstraint: "locationConstraint"}
|
||||||
|
accessBox.ContainerPolicy = []*AccessBox_ContainerPolicy{policy}
|
||||||
|
|
||||||
|
policies, err := accessBox.GetPlacementPolicy()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Len(t, policies, 1)
|
||||||
|
require.Equal(t, policy.LocationConstraint, policies[0].LocationConstraint)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("get incorrect placement policy", func(t *testing.T) {
|
||||||
|
policy := &AccessBox_ContainerPolicy{
|
||||||
|
LocationConstraint: "locationConstraint",
|
||||||
|
Policy: []byte("policy"),
|
||||||
|
}
|
||||||
|
accessBox.ContainerPolicy = []*AccessBox_ContainerPolicy{policy}
|
||||||
|
|
||||||
|
_, err = accessBox.GetPlacementPolicy()
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = accessBox.GetBox(cred)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty seed key", func(t *testing.T) {
|
||||||
|
accessBox.SeedKey = nil
|
||||||
|
|
||||||
|
_, err = accessBox.GetTokens(cred)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
_, err = accessBox.GetBox(cred)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid gate key", func(t *testing.T) {
|
||||||
|
gate = &GateData{
|
||||||
|
BearerToken: &tkn,
|
||||||
|
GateKey: &keys.PublicKey{},
|
||||||
|
}
|
||||||
|
_, _, err = PackTokens([]*GateData{gate}, nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||||
|
cidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
|
||||||
|
@ -20,12 +21,55 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type frostfsMock struct {
|
type frostfsMock struct {
|
||||||
objects map[oid.Address][]byte
|
objects map[oid.Address][]*object.Object
|
||||||
errors map[oid.Address]error
|
errors map[oid.Address]error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *frostfsMock) CreateObject(context.Context, PrmObjectCreate) (oid.ID, error) {
|
func newFrostfsMock() *frostfsMock {
|
||||||
panic("implement me for test")
|
return &frostfsMock{
|
||||||
|
objects: map[oid.Address][]*object.Object{},
|
||||||
|
errors: map[oid.Address]error{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *frostfsMock) CreateObject(_ context.Context, prm PrmObjectCreate) (oid.ID, error) {
|
||||||
|
var obj object.Object
|
||||||
|
obj.SetPayload(prm.Payload)
|
||||||
|
obj.SetOwnerID(prm.Creator)
|
||||||
|
obj.SetContainerID(prm.Container)
|
||||||
|
|
||||||
|
a := object.NewAttribute()
|
||||||
|
a.SetKey(object.AttributeFilePath)
|
||||||
|
a.SetValue(prm.Filepath)
|
||||||
|
prm.CustomAttributes = append(prm.CustomAttributes, *a)
|
||||||
|
obj.SetAttributes(prm.CustomAttributes...)
|
||||||
|
|
||||||
|
if prm.NewVersionFor != nil {
|
||||||
|
var addr oid.Address
|
||||||
|
addr.SetObject(*prm.NewVersionFor)
|
||||||
|
addr.SetContainer(prm.Container)
|
||||||
|
|
||||||
|
_, ok := f.objects[addr]
|
||||||
|
if !ok {
|
||||||
|
return oid.ID{}, errors.New("not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
objID := oidtest.ID()
|
||||||
|
obj.SetID(objID)
|
||||||
|
f.objects[addr] = append(f.objects[addr], &obj)
|
||||||
|
|
||||||
|
return objID, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
objID := oidtest.ID()
|
||||||
|
obj.SetID(objID)
|
||||||
|
|
||||||
|
var addr oid.Address
|
||||||
|
addr.SetObject(objID)
|
||||||
|
addr.SetContainer(prm.Container)
|
||||||
|
f.objects[addr] = []*object.Object{&obj}
|
||||||
|
|
||||||
|
return objID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *frostfsMock) GetCredsObject(_ context.Context, address oid.Address) (*object.Object, error) {
|
func (f *frostfsMock) GetCredsObject(_ context.Context, address oid.Address) (*object.Object, error) {
|
||||||
|
@ -33,14 +77,12 @@ func (f *frostfsMock) GetCredsObject(_ context.Context, address oid.Address) (*o
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data, ok := f.objects[address]
|
objects, ok := f.objects[address]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("not found")
|
return nil, errors.New("not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
var obj object.Object
|
return objects[len(objects)-1], nil
|
||||||
obj.SetPayload(data)
|
|
||||||
return &obj, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRemovingAccessBox(t *testing.T) {
|
func TestRemovingAccessBox(t *testing.T) {
|
||||||
|
@ -63,9 +105,14 @@ func TestRemovingAccessBox(t *testing.T) {
|
||||||
data, err := accessBox.Marshal()
|
data, err := accessBox.Marshal()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var obj object.Object
|
||||||
|
obj.SetPayload(data)
|
||||||
addr := oidtest.Address()
|
addr := oidtest.Address()
|
||||||
|
obj.SetID(addr.Object())
|
||||||
|
obj.SetContainerID(addr.Container())
|
||||||
|
|
||||||
frostfs := &frostfsMock{
|
frostfs := &frostfsMock{
|
||||||
objects: map[oid.Address][]byte{addr: data},
|
objects: map[oid.Address][]*object.Object{addr: {&obj}},
|
||||||
errors: map[oid.Address]error{},
|
errors: map[oid.Address]error{},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,3 +140,190 @@ func TestRemovingAccessBox(t *testing.T) {
|
||||||
_, _, err = creds.GetBox(ctx, addr)
|
_, _, err = creds.GetBox(ctx, addr)
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetBox(t *testing.T) {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
key, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
gateData := []*accessbox.GateData{{
|
||||||
|
BearerToken: &bearer.Token{},
|
||||||
|
GateKey: key.PublicKey(),
|
||||||
|
}}
|
||||||
|
|
||||||
|
secret := []byte("secret")
|
||||||
|
accessBox, _, err := accessbox.PackTokens(gateData, secret)
|
||||||
|
require.NoError(t, err)
|
||||||
|
data, err := accessBox.Marshal()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var attr object.Attribute
|
||||||
|
attr.SetKey("key")
|
||||||
|
attr.SetValue("value")
|
||||||
|
attrs := []object.Attribute{attr}
|
||||||
|
|
||||||
|
cfg := Config{
|
||||||
|
CacheConfig: &cache.Config{
|
||||||
|
Size: 10,
|
||||||
|
Lifetime: 24 * time.Hour,
|
||||||
|
Logger: zaptest.NewLogger(t),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("no removing check, accessbox from cache", func(t *testing.T) {
|
||||||
|
frostfs := newFrostfsMock()
|
||||||
|
cfg.FrostFS = frostfs
|
||||||
|
cfg.RemovingCheckAfterDurations = time.Hour
|
||||||
|
cfg.Key = key
|
||||||
|
creds := New(cfg)
|
||||||
|
|
||||||
|
cnrID := cidtest.ID()
|
||||||
|
addr, err := creds.Put(ctx, cnrID, CredentialsParam{Keys: keys.PublicKeys{key.PublicKey()}, AccessBox: accessBox})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, _, err = creds.GetBox(ctx, addr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
frostfs.errors[addr] = &apistatus.ObjectAlreadyRemoved{}
|
||||||
|
_, _, err = creds.GetBox(ctx, addr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("error while getting box from frostfs", func(t *testing.T) {
|
||||||
|
frostfs := newFrostfsMock()
|
||||||
|
cfg.FrostFS = frostfs
|
||||||
|
cfg.RemovingCheckAfterDurations = 0
|
||||||
|
cfg.Key = key
|
||||||
|
creds := New(cfg)
|
||||||
|
|
||||||
|
cnrID := cidtest.ID()
|
||||||
|
addr, err := creds.Put(ctx, cnrID, CredentialsParam{Keys: keys.PublicKeys{key.PublicKey()}, AccessBox: accessBox})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
frostfs.errors[addr] = errors.New("network error")
|
||||||
|
_, _, err = creds.GetBox(ctx, addr)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid key", func(t *testing.T) {
|
||||||
|
frostfs := newFrostfsMock()
|
||||||
|
|
||||||
|
var obj object.Object
|
||||||
|
obj.SetPayload(data)
|
||||||
|
addr := oidtest.Address()
|
||||||
|
frostfs.objects[addr] = []*object.Object{&obj}
|
||||||
|
|
||||||
|
cfg.FrostFS = frostfs
|
||||||
|
cfg.RemovingCheckAfterDurations = 0
|
||||||
|
cfg.Key = &keys.PrivateKey{}
|
||||||
|
creds := New(cfg)
|
||||||
|
|
||||||
|
_, _, err = creds.GetBox(ctx, addr)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid payload", func(t *testing.T) {
|
||||||
|
frostfs := newFrostfsMock()
|
||||||
|
|
||||||
|
var obj object.Object
|
||||||
|
obj.SetPayload([]byte("invalid"))
|
||||||
|
addr := oidtest.Address()
|
||||||
|
frostfs.objects[addr] = []*object.Object{&obj}
|
||||||
|
|
||||||
|
cfg.FrostFS = frostfs
|
||||||
|
cfg.RemovingCheckAfterDurations = 0
|
||||||
|
cfg.Key = key
|
||||||
|
creds := New(cfg)
|
||||||
|
|
||||||
|
_, _, err = creds.GetBox(ctx, addr)
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("check attributes update", func(t *testing.T) {
|
||||||
|
frostfs := newFrostfsMock()
|
||||||
|
cfg.FrostFS = frostfs
|
||||||
|
cfg.RemovingCheckAfterDurations = 0
|
||||||
|
cfg.Key = key
|
||||||
|
creds := New(cfg)
|
||||||
|
|
||||||
|
cnrID := cidtest.ID()
|
||||||
|
addr, err := creds.Put(ctx, cnrID, CredentialsParam{Keys: keys.PublicKeys{key.PublicKey()}, AccessBox: accessBox})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, boxAttrs, err := creds.GetBox(ctx, addr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = creds.Update(ctx, addr, CredentialsParam{Keys: keys.PublicKeys{key.PublicKey()}, AccessBox: accessBox, CustomAttributes: attrs})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, newBoxAttrs, err := creds.GetBox(ctx, addr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, len(boxAttrs)+1, len(newBoxAttrs))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("check accessbox update", func(t *testing.T) {
|
||||||
|
frostfs := newFrostfsMock()
|
||||||
|
cfg.FrostFS = frostfs
|
||||||
|
cfg.RemovingCheckAfterDurations = 0
|
||||||
|
cfg.Key = key
|
||||||
|
creds := New(cfg)
|
||||||
|
|
||||||
|
cnrID := cidtest.ID()
|
||||||
|
addr, err := creds.Put(ctx, cnrID, CredentialsParam{Keys: keys.PublicKeys{key.PublicKey()}, AccessBox: accessBox})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
box, _, err := creds.GetBox(ctx, addr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, hex.EncodeToString(secret), box.Gate.SecretKey)
|
||||||
|
|
||||||
|
newKey, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
newGateData := []*accessbox.GateData{{
|
||||||
|
BearerToken: &bearer.Token{},
|
||||||
|
GateKey: newKey.PublicKey(),
|
||||||
|
}}
|
||||||
|
|
||||||
|
newSecret := []byte("new-secret")
|
||||||
|
newAccessBox, _, err := accessbox.PackTokens(newGateData, newSecret)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = creds.Update(ctx, addr, CredentialsParam{Keys: keys.PublicKeys{newKey.PublicKey()}, AccessBox: newAccessBox})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, _, err = creds.GetBox(ctx, addr)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
cfg.Key = newKey
|
||||||
|
newCreds := New(cfg)
|
||||||
|
|
||||||
|
box, _, err = newCreds.GetBox(ctx, addr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, hex.EncodeToString(newSecret), box.Gate.SecretKey)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty keys", func(t *testing.T) {
|
||||||
|
frostfs := newFrostfsMock()
|
||||||
|
cfg.FrostFS = frostfs
|
||||||
|
cfg.RemovingCheckAfterDurations = 0
|
||||||
|
cfg.Key = key
|
||||||
|
creds := New(cfg)
|
||||||
|
|
||||||
|
cnrID := cidtest.ID()
|
||||||
|
_, err = creds.Put(ctx, cnrID, CredentialsParam{AccessBox: accessBox})
|
||||||
|
require.ErrorIs(t, err, ErrEmptyPublicKeys)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("empty accessbox", func(t *testing.T) {
|
||||||
|
frostfs := newFrostfsMock()
|
||||||
|
cfg.FrostFS = frostfs
|
||||||
|
cfg.RemovingCheckAfterDurations = 0
|
||||||
|
cfg.Key = key
|
||||||
|
creds := New(cfg)
|
||||||
|
|
||||||
|
cnrID := cidtest.ID()
|
||||||
|
_, err = creds.Put(ctx, cnrID, CredentialsParam{Keys: keys.PublicKeys{key.PublicKey()}})
|
||||||
|
require.ErrorIs(t, err, ErrEmptyBearerToken)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -16,8 +16,6 @@ import (
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||||
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
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"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -26,12 +24,12 @@ const (
|
||||||
|
|
||||||
// AuthmateFrostFS is a mediator which implements authmate.FrostFS through pool.Pool.
|
// AuthmateFrostFS is a mediator which implements authmate.FrostFS through pool.Pool.
|
||||||
type AuthmateFrostFS struct {
|
type AuthmateFrostFS struct {
|
||||||
frostFS *FrostFS
|
frostFS layer.FrostFS
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAuthmateFrostFS creates new AuthmateFrostFS using provided pool.Pool.
|
// NewAuthmateFrostFS creates new AuthmateFrostFS using provided pool.Pool.
|
||||||
func NewAuthmateFrostFS(p *pool.Pool, key *keys.PrivateKey) *AuthmateFrostFS {
|
func NewAuthmateFrostFS(frostFS layer.FrostFS) *AuthmateFrostFS {
|
||||||
return &AuthmateFrostFS{frostFS: NewFrostFS(p, key)}
|
return &AuthmateFrostFS{frostFS: frostFS}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerExists implements authmate.FrostFS interface method.
|
// ContainerExists implements authmate.FrostFS interface method.
|
||||||
|
|
70
internal/frostfs/authmate_test.go
Normal file
70
internal/frostfs/authmate_test.go
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
package frostfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/layer"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api/middleware"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/authmate"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/tokens"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||||
|
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||||
|
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetCredsObject(t *testing.T) {
|
||||||
|
ctx, bktName, payload, newPayload := context.Background(), "bucket", []byte("payload"), []byte("new-payload")
|
||||||
|
|
||||||
|
key, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var userID user.ID
|
||||||
|
userID.SetScriptHash(key.PublicKey().GetScriptHash())
|
||||||
|
|
||||||
|
var token bearer.Token
|
||||||
|
err = token.Sign(key.PrivateKey)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ctx = middleware.SetBox(ctx, &middleware.Box{AccessBox: &accessbox.Box{
|
||||||
|
Gate: &accessbox.GateData{
|
||||||
|
BearerToken: &token,
|
||||||
|
},
|
||||||
|
}})
|
||||||
|
|
||||||
|
frostfs := NewAuthmateFrostFS(layer.NewTestFrostFS(key))
|
||||||
|
|
||||||
|
cid, err := frostfs.CreateContainer(ctx, authmate.PrmContainerCreate{
|
||||||
|
FriendlyName: bktName,
|
||||||
|
Owner: userID,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
objID, err := frostfs.CreateObject(ctx, tokens.PrmObjectCreate{
|
||||||
|
Container: cid,
|
||||||
|
Payload: payload,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var addr oid.Address
|
||||||
|
addr.SetContainer(cid)
|
||||||
|
addr.SetObject(objID)
|
||||||
|
|
||||||
|
obj, err := frostfs.GetCredsObject(ctx, addr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, payload, obj.Payload())
|
||||||
|
|
||||||
|
_, err = frostfs.CreateObject(ctx, tokens.PrmObjectCreate{
|
||||||
|
Container: cid,
|
||||||
|
Payload: newPayload,
|
||||||
|
NewVersionFor: &objID,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
obj, err = frostfs.GetCredsObject(ctx, addr)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, newPayload, obj.Payload())
|
||||||
|
}
|
Loading…
Reference in a new issue