[#380] creds: Increase test coverage #380

Merged
alexvanin merged 2 commits from mbiryukova/frostfs-s3-gw:feature/increase_test_coverage into master 2024-05-03 07:24:16 +00:00
2 changed files with 388 additions and 8 deletions
Showing only changes of commit 98b536c76d - Show all commits

View file

@ -1,6 +1,7 @@
package accessbox
import (
"encoding/hex"
"testing"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
@ -170,3 +171,148 @@ func TestUnknownKey(t *testing.T) {
_, err = box.GetTokens(wrongCred)
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)
})
}

View file

@ -11,6 +11,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/creds/accessbox"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
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"
oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
oidtest "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id/test"
@ -20,12 +21,55 @@ import (
)
type frostfsMock struct {
objects map[oid.Address][]byte
objects map[oid.Address][]*object.Object
errors map[oid.Address]error
}
func (f *frostfsMock) CreateObject(context.Context, PrmObjectCreate) (oid.ID, error) {
panic("implement me for test")
func newFrostfsMock() *frostfsMock {
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) {
@ -33,14 +77,12 @@ func (f *frostfsMock) GetCredsObject(_ context.Context, address oid.Address) (*o
return nil, err
}
data, ok := f.objects[address]
objects, ok := f.objects[address]
if !ok {
return nil, errors.New("not found")
}
var obj object.Object
obj.SetPayload(data)
return &obj, nil
return objects[len(objects)-1], nil
}
func TestRemovingAccessBox(t *testing.T) {
@ -63,9 +105,14 @@ func TestRemovingAccessBox(t *testing.T) {
data, err := accessBox.Marshal()
require.NoError(t, err)
var obj object.Object
obj.SetPayload(data)
addr := oidtest.Address()
obj.SetID(addr.Object())
obj.SetContainerID(addr.Container())
frostfs := &frostfsMock{
objects: map[oid.Address][]byte{addr: data},
objects: map[oid.Address][]*object.Object{addr: {&obj}},
errors: map[oid.Address]error{},
}
@ -93,3 +140,190 @@ func TestRemovingAccessBox(t *testing.T) {
_, _, err = creds.GetBox(ctx, addr)
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)
})
}