From d1499e65b913ae45d30e21d8184679af000ec9d9 Mon Sep 17 00:00:00 2001 From: Alex Vanin Date: Mon, 14 Sep 2020 18:21:11 +0300 Subject: [PATCH] [#139] sdk/acl: Add test coverage for EACL structures Signed-off-by: Alex Vanin --- pkg/acl/eacl/enums_test.go | 117 ++++++++++++++++++++++++++++++++++++ pkg/acl/eacl/filter_test.go | 31 ++++++++++ pkg/acl/eacl/record_test.go | 83 +++++++++++++++++++++++++ pkg/acl/eacl/table_test.go | 67 ++++++++++++++++++++- pkg/acl/eacl/target_test.go | 38 ++++++++++++ 5 files changed, 334 insertions(+), 2 deletions(-) create mode 100644 pkg/acl/eacl/enums_test.go create mode 100644 pkg/acl/eacl/filter_test.go create mode 100644 pkg/acl/eacl/record_test.go create mode 100644 pkg/acl/eacl/target_test.go diff --git a/pkg/acl/eacl/enums_test.go b/pkg/acl/eacl/enums_test.go new file mode 100644 index 0000000..11f2224 --- /dev/null +++ b/pkg/acl/eacl/enums_test.go @@ -0,0 +1,117 @@ +package eacl_test + +import ( + "testing" + + "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl" + v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" + "github.com/stretchr/testify/require" +) + +var ( + eqV2Actions = map[eacl.Action]v2acl.Action{ + eacl.ActionUnknown: v2acl.ActionUnknown, + eacl.ActionAllow: v2acl.ActionAllow, + eacl.ActionDeny: v2acl.ActionDeny, + } + + eqV2Operations = map[eacl.Operation]v2acl.Operation{ + eacl.OperationUnknown: v2acl.OperationUnknown, + eacl.OperationGet: v2acl.OperationGet, + eacl.OperationHead: v2acl.OperationHead, + eacl.OperationPut: v2acl.OperationPut, + eacl.OperationDelete: v2acl.OperationDelete, + eacl.OperationSearch: v2acl.OperationSearch, + eacl.OperationRange: v2acl.OperationRange, + eacl.OperationRangeHash: v2acl.OperationRangeHash, + } + + eqV2Roles = map[eacl.Role]v2acl.Role{ + eacl.RoleUnknown: v2acl.RoleUnknown, + eacl.RoleUser: v2acl.RoleUser, + eacl.RoleSystem: v2acl.RoleSystem, + eacl.RoleOthers: v2acl.RoleOthers, + } + + eqV2Matches = map[eacl.Match]v2acl.MatchType{ + eacl.MatchUnknown: v2acl.MatchTypeUnknown, + eacl.MatchStringEqual: v2acl.MatchTypeStringEqual, + eacl.MatchStringNotEqual: v2acl.MatchTypeStringNotEqual, + } + + eqV2HeaderTypes = map[eacl.FilterHeaderType]v2acl.HeaderType{ + eacl.HeaderTypeUnknown: v2acl.HeaderTypeUnknown, + eacl.HeaderFromRequest: v2acl.HeaderTypeRequest, + eacl.HeaderFromObject: v2acl.HeaderTypeObject, + } +) + +func TestAction(t *testing.T) { + t.Run("known actions", func(t *testing.T) { + for i := eacl.ActionUnknown; i <= eacl.ActionDeny; i++ { + require.Equal(t, eqV2Actions[i], i.ToV2()) + require.Equal(t, eacl.ActionFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown actions", func(t *testing.T) { + require.Equal(t, (eacl.ActionDeny + 1).ToV2(), v2acl.ActionUnknown) + require.Equal(t, eacl.ActionFromV2(v2acl.ActionDeny+1), eacl.ActionUnknown) + }) +} + +func TestOperation(t *testing.T) { + t.Run("known operations", func(t *testing.T) { + for i := eacl.OperationUnknown; i <= eacl.OperationRangeHash; i++ { + require.Equal(t, eqV2Operations[i], i.ToV2()) + require.Equal(t, eacl.OperationFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown operations", func(t *testing.T) { + require.Equal(t, (eacl.OperationRangeHash + 1).ToV2(), v2acl.OperationUnknown) + require.Equal(t, eacl.OperationFromV2(v2acl.OperationRangeHash+1), eacl.OperationUnknown) + }) +} + +func TestRole(t *testing.T) { + t.Run("known roles", func(t *testing.T) { + for i := eacl.RoleUnknown; i <= eacl.RoleOthers; i++ { + require.Equal(t, eqV2Roles[i], i.ToV2()) + require.Equal(t, eacl.RoleFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown roles", func(t *testing.T) { + require.Equal(t, (eacl.RoleOthers + 1).ToV2(), v2acl.RoleUnknown) + require.Equal(t, eacl.RoleFromV2(v2acl.RoleOthers+1), eacl.RoleUnknown) + }) +} + +func TestMatch(t *testing.T) { + t.Run("known matches", func(t *testing.T) { + for i := eacl.MatchUnknown; i <= eacl.MatchStringNotEqual; i++ { + require.Equal(t, eqV2Matches[i], i.ToV2()) + require.Equal(t, eacl.MatchFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown matches", func(t *testing.T) { + require.Equal(t, (eacl.MatchStringNotEqual + 1).ToV2(), v2acl.MatchTypeUnknown) + require.Equal(t, eacl.MatchFromV2(v2acl.MatchTypeStringNotEqual+1), eacl.MatchUnknown) + }) +} + +func TestFilterHeaderType(t *testing.T) { + t.Run("known header types", func(t *testing.T) { + for i := eacl.HeaderTypeUnknown; i <= eacl.HeaderFromObject; i++ { + require.Equal(t, eqV2HeaderTypes[i], i.ToV2()) + require.Equal(t, eacl.FilterHeaderTypeFromV2(i.ToV2()), i) + } + }) + + t.Run("unknown header types", func(t *testing.T) { + require.Equal(t, (eacl.HeaderFromObject + 1).ToV2(), v2acl.HeaderTypeUnknown) + require.Equal(t, eacl.FilterHeaderTypeFromV2(v2acl.HeaderTypeObject+1), eacl.HeaderTypeUnknown) + }) +} diff --git a/pkg/acl/eacl/filter_test.go b/pkg/acl/eacl/filter_test.go new file mode 100644 index 0000000..57dcb1d --- /dev/null +++ b/pkg/acl/eacl/filter_test.go @@ -0,0 +1,31 @@ +package eacl + +import ( + "testing" + + v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" + "github.com/stretchr/testify/require" +) + +func TestFilter(t *testing.T) { + filter := &Filter{ + from: HeaderFromObject, + name: HdrObjSysNamePayloadLength, + matcher: MatchStringEqual, + value: "200", + } + + v2 := filter.ToV2() + require.NotNil(t, v2) + require.Equal(t, v2acl.HeaderTypeObject, v2.GetHeaderType()) + require.EqualValues(t, v2acl.MatchTypeStringEqual, v2.GetMatchType()) + require.Equal(t, filter.Name(), v2.GetName()) + require.Equal(t, filter.Value(), v2.GetValue()) + + newFilter := NewFilterFromV2(v2) + require.Equal(t, filter, newFilter) + + t.Run("from nil v2 filter", func(t *testing.T) { + require.Equal(t, new(Filter), NewFilterFromV2(nil)) + }) +} diff --git a/pkg/acl/eacl/record_test.go b/pkg/acl/eacl/record_test.go new file mode 100644 index 0000000..f9b8ffb --- /dev/null +++ b/pkg/acl/eacl/record_test.go @@ -0,0 +1,83 @@ +package eacl + +import ( + "crypto/ecdsa" + "testing" + + v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" + "github.com/nspcc-dev/neofs-crypto/test" + "github.com/stretchr/testify/require" +) + +func TestRecord(t *testing.T) { + record := NewRecord() + record.SetOperation(OperationRange) + record.SetAction(ActionAllow) + record.AddFilter(HeaderFromRequest, MatchStringEqual, "A", "B") + record.AddFilter(HeaderFromRequest, MatchStringNotEqual, "C", "D") + record.AddTarget(RoleSystem) + + v2 := record.ToV2() + require.NotNil(t, v2) + require.Equal(t, v2acl.OperationRange, v2.GetOperation()) + require.Equal(t, v2acl.ActionAllow, v2.GetAction()) + require.Len(t, v2.GetFilters(), len(record.Filters())) + require.Len(t, v2.GetTargets(), len(record.Targets())) + + newRecord := NewRecordFromV2(v2) + require.Equal(t, record, newRecord) + + t.Run("create record", func(t *testing.T) { + record := CreateRecord(ActionAllow, OperationGet) + require.Equal(t, ActionAllow, record.Action()) + require.Equal(t, OperationGet, record.Operation()) + }) + + t.Run("new from nil v2 record", func(t *testing.T) { + require.Equal(t, new(Record), NewRecordFromV2(nil)) + }) +} + +func TestRecord_AddTarget(t *testing.T) { + targets := []Target{ + { + role: RoleUnknown, + keys: []ecdsa.PublicKey{test.DecodeKey(1).PublicKey}, + }, + { + role: RoleSystem, + keys: []ecdsa.PublicKey{}, + }, + } + + r := NewRecord() + for _, target := range targets { + r.AddTarget(target.Role(), target.Keys()...) + } + + require.Equal(t, targets, r.Targets()) +} + +func TestRecord_AddFilter(t *testing.T) { + filters := []Filter{ + { + from: HeaderFromObject, + name: HdrObjSysNameCID, + matcher: MatchStringEqual, + value: "ContainerID", + }, + { + from: HeaderFromRequest, + name: "X-Header-Name", + matcher: MatchStringNotEqual, + value: "X-Header-Value", + }, + } + + r := NewRecord() + for _, filter := range filters { + r.AddFilter(filter.From(), filter.Matcher(), filter.Name(), filter.Value()) + } + + require.Equal(t, filters, r.Filters()) +} diff --git a/pkg/acl/eacl/table_test.go b/pkg/acl/eacl/table_test.go index b4d52b5..e7121fb 100644 --- a/pkg/acl/eacl/table_test.go +++ b/pkg/acl/eacl/table_test.go @@ -1,17 +1,80 @@ package eacl_test import ( + "crypto/sha256" "testing" + "github.com/nspcc-dev/neofs-api-go/pkg" "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl" + "github.com/nspcc-dev/neofs-api-go/pkg/container" "github.com/nspcc-dev/neofs-crypto/test" + "github.com/stretchr/testify/require" ) -func TextExample(t *testing.T) { +// example how to create eACL tables in applications +func example() { record := eacl.CreateRecord(eacl.ActionDeny, eacl.OperationPut) record.AddFilter(eacl.HeaderFromObject, eacl.MatchStringEqual, "filename", "cat.jpg") record.AddTarget(eacl.RoleOthers, test.DecodeKey(1).PublicKey, test.DecodeKey(2).PublicKey) - table := eacl.NewTable() + var cid container.ID + cid.SetSHA256(sha256.Sum256([]byte("container id"))) + + table := eacl.CreateTable(cid) table.AddRecord(record) } + +func TestTable(t *testing.T) { + var ( + v pkg.Version + cid container.ID + ) + + sha := sha256.Sum256([]byte("container id")) + cid.SetSHA256(sha) + + v.SetMajor(3) + v.SetMinor(2) + + table := eacl.NewTable() + table.SetVersion(v) + table.SetCID(&cid) + table.AddRecord(eacl.CreateRecord(eacl.ActionAllow, eacl.OperationPut)) + + v2 := table.ToV2() + require.NotNil(t, v2) + require.Equal(t, uint32(3), v2.GetVersion().GetMajor()) + require.Equal(t, uint32(2), v2.GetVersion().GetMinor()) + require.Equal(t, sha[:], v2.GetContainerID().GetValue()) + require.Len(t, v2.GetRecords(), 1) + + newTable := eacl.NewTableFromV2(v2) + require.Equal(t, table, newTable) + + t.Run("new from nil v2 table", func(t *testing.T) { + require.Equal(t, new(eacl.Table), eacl.NewTableFromV2(nil)) + }) + + t.Run("create table", func(t *testing.T) { + var cid = new(container.ID) + cid.SetSHA256(sha256.Sum256([]byte("container id"))) + + table := eacl.CreateTable(*cid) + require.Equal(t, cid, table.CID()) + require.Equal(t, *pkg.SDKVersion(), table.Version()) + }) +} + +func TestTable_AddRecord(t *testing.T) { + records := []eacl.Record{ + *eacl.CreateRecord(eacl.ActionDeny, eacl.OperationDelete), + *eacl.CreateRecord(eacl.ActionAllow, eacl.OperationPut), + } + + table := eacl.NewTable() + for _, record := range records { + table.AddRecord(&record) + } + + require.Equal(t, records, table.Records()) +} diff --git a/pkg/acl/eacl/target_test.go b/pkg/acl/eacl/target_test.go new file mode 100644 index 0000000..dd26f4b --- /dev/null +++ b/pkg/acl/eacl/target_test.go @@ -0,0 +1,38 @@ +package eacl + +import ( + "crypto/ecdsa" + "testing" + + v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" + crypto "github.com/nspcc-dev/neofs-crypto" + "github.com/nspcc-dev/neofs-crypto/test" + "github.com/stretchr/testify/require" +) + +func TestTarget(t *testing.T) { + keys := []ecdsa.PublicKey{ + test.DecodeKey(1).PublicKey, + test.DecodeKey(2).PublicKey, + } + + target := &Target{ + role: RoleSystem, + keys: keys, + } + + v2 := target.ToV2() + require.NotNil(t, v2) + require.Equal(t, v2acl.RoleSystem, v2.GetRole()) + require.Len(t, v2.GetKeyList(), len(keys)) + for i, key := range v2.GetKeyList() { + require.Equal(t, key, crypto.MarshalPublicKey(&keys[i])) + } + + newTarget := NewTargetFromV2(v2) + require.Equal(t, target, newTarget) + + t.Run("from nil v2 target", func(t *testing.T) { + require.Equal(t, new(Target), NewTargetFromV2(nil)) + }) +}