From 7cc402344a24620b22d8e7a8ae894eb03758a27d Mon Sep 17 00:00:00 2001 From: Marina Biryukova Date: Fri, 26 Apr 2024 17:32:58 +0300 Subject: [PATCH] [#380] Add test for credentials versioning Signed-off-by: Marina Biryukova --- api/layer/frostfs_mock.go | 47 +++++++++++++++++++++ cmd/s3-authmate/modules/utils.go | 4 +- cmd/s3-gw/app.go | 2 +- internal/frostfs/authmate.go | 8 ++-- internal/frostfs/authmate_test.go | 70 +++++++++++++++++++++++++++++++ 5 files changed, 123 insertions(+), 8 deletions(-) create mode 100644 internal/frostfs/authmate_test.go diff --git a/api/layer/frostfs_mock.go b/api/layer/frostfs_mock.go index d30d304..ff7f3f9 100644 --- a/api/layer/frostfs_mock.go +++ b/api/layer/frostfs_mock.go @@ -8,6 +8,7 @@ import ( "errors" "fmt" "io" + "strings" "time" "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 } +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 { cnr, ok := t.containers[cnrID.EncodeToString()] if !ok { @@ -448,3 +486,12 @@ func getBearerOwner(ctx context.Context) 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 +} diff --git a/cmd/s3-authmate/modules/utils.go b/cmd/s3-authmate/modules/utils.go index 4c1c28a..335f995 100644 --- a/cmd/s3-authmate/modules/utils.go +++ b/cmd/s3-authmate/modules/utils.go @@ -30,7 +30,7 @@ type PoolConfig struct { 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) 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 frostfs.NewAuthmateFrostFS(p, cfg.Key), nil + return frostfs.NewAuthmateFrostFS(frostfs.NewFrostFS(p, cfg.Key)), nil } func parsePolicies(val string) (authmate.ContainerPolicies, error) { diff --git a/cmd/s3-gw/app.go b/cmd/s3-gw/app.go index 32cddd4..317d8a0 100644 --- a/cmd/s3-gw/app.go +++ b/cmd/s3-gw/app.go @@ -127,7 +127,7 @@ func newApp(ctx context.Context, log *Logger, v *viper.Viper) *App { objPool, treePool, key := getPools(ctx, log.logger, v) cfg := tokens.Config{ - FrostFS: frostfs.NewAuthmateFrostFS(objPool, key), + FrostFS: frostfs.NewAuthmateFrostFS(frostfs.NewFrostFS(objPool, key)), Key: key, CacheConfig: getAccessBoxCacheConfig(v, log.logger), RemovingCheckAfterDurations: fetchRemovingCheckInterval(v, log.logger), diff --git a/internal/frostfs/authmate.go b/internal/frostfs/authmate.go index 9de2263..37d9d31 100644 --- a/internal/frostfs/authmate.go +++ b/internal/frostfs/authmate.go @@ -16,8 +16,6 @@ import ( 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" ) const ( @@ -26,12 +24,12 @@ const ( // AuthmateFrostFS is a mediator which implements authmate.FrostFS through pool.Pool. type AuthmateFrostFS struct { - frostFS *FrostFS + frostFS layer.FrostFS } // NewAuthmateFrostFS creates new AuthmateFrostFS using provided pool.Pool. -func NewAuthmateFrostFS(p *pool.Pool, key *keys.PrivateKey) *AuthmateFrostFS { - return &AuthmateFrostFS{frostFS: NewFrostFS(p, key)} +func NewAuthmateFrostFS(frostFS layer.FrostFS) *AuthmateFrostFS { + return &AuthmateFrostFS{frostFS: frostFS} } // ContainerExists implements authmate.FrostFS interface method. diff --git a/internal/frostfs/authmate_test.go b/internal/frostfs/authmate_test.go new file mode 100644 index 0000000..3af15fc --- /dev/null +++ b/internal/frostfs/authmate_test.go @@ -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()) +}