From 6c76c9b457b24349d6fc1ff0d262f57006931b03 Mon Sep 17 00:00:00 2001 From: aarifullin Date: Thu, 2 May 2024 20:26:06 +0300 Subject: [PATCH] [#1117] core: Introduce SubjectProvider interface for FrostfsID * Make tree, object and container services use SubjectProvider interface. * Fix unit-tests. Signed-off-by: Airat Arifullin --- pkg/ape/request/request.go | 2 +- pkg/core/frostfsid/subject_provider.go | 16 ++++++++++ pkg/morph/client/frostfsid/client.go | 3 ++ pkg/services/container/ape.go | 19 +++--------- pkg/services/container/ape_test.go | 17 ++++++++-- pkg/services/object/ape/checker.go | 11 ++----- pkg/services/object/ape/checker_test.go | 41 ++++++++++++++++++++++--- pkg/services/object/ape/request.go | 7 ++--- pkg/services/tree/ape.go | 5 ++- pkg/services/tree/options.go | 11 ++----- 10 files changed, 85 insertions(+), 47 deletions(-) create mode 100644 pkg/core/frostfsid/subject_provider.go diff --git a/pkg/ape/request/request.go b/pkg/ape/request/request.go index 6d62ef3d5..de67dea23 100644 --- a/pkg/ape/request/request.go +++ b/pkg/ape/request/request.go @@ -1,4 +1,4 @@ -package ape +package request import ( aperesource "git.frostfs.info/TrueCloudLab/policy-engine/pkg/resource" diff --git a/pkg/core/frostfsid/subject_provider.go b/pkg/core/frostfsid/subject_provider.go new file mode 100644 index 000000000..ecfd0eb15 --- /dev/null +++ b/pkg/core/frostfsid/subject_provider.go @@ -0,0 +1,16 @@ +package frostfsid + +import ( + "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + "github.com/nspcc-dev/neo-go/pkg/util" +) + +const ( + SubjectNotFoundErrorMessage = "subject not found" +) + +// SubjectProvider interface provides methods to get subject from FrostfsID contract. +type SubjectProvider interface { + GetSubject(util.Uint160) (*client.Subject, error) + GetSubjectExtended(util.Uint160) (*client.SubjectExtended, error) +} diff --git a/pkg/morph/client/frostfsid/client.go b/pkg/morph/client/frostfsid/client.go index 3efa522bc..4c31f42de 100644 --- a/pkg/morph/client/frostfsid/client.go +++ b/pkg/morph/client/frostfsid/client.go @@ -3,6 +3,7 @@ package frostfsid import ( "fmt" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/util" @@ -20,6 +21,8 @@ type Client struct { client *client.StaticClient // static FrostFS ID contract client } +var _ frostfsidcore.SubjectProvider = (*Client)(nil) + // NewFromMorph wraps client to work with FrostFS ID contract. func NewFromMorph(cli *client.Client, contract util.Uint160, fee fixedn.Fixed8) (*Client, error) { sc, err := client.NewStatic(cli, contract, fee, client.TryNotary(), client.AsAlphabet()) diff --git a/pkg/services/container/ape.go b/pkg/services/container/ape.go index 2ce427fa3..9c38d1bba 100644 --- a/pkg/services/container/ape.go +++ b/pkg/services/container/ape.go @@ -14,9 +14,9 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container" "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs" session "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session" - "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-observability/tracing" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" @@ -30,11 +30,6 @@ import ( commonschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/common" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/util" -) - -const ( - subjectNotFoundErrorMessage = "subject not found" ) var ( @@ -59,22 +54,18 @@ type containers interface { Get(cid.ID) (*containercore.Container, error) } -type frostfsidSubjectProvider interface { - GetSubject(util.Uint160) (*client.Subject, error) -} - type apeChecker struct { router policyengine.ChainRouter reader containers ir ir nm netmap.Source - frostFSIDClient frostfsidSubjectProvider + frostFSIDClient frostfsidcore.SubjectProvider next Server } -func NewAPEServer(router policyengine.ChainRouter, reader containers, ir ir, nm netmap.Source, frostFSIDClient frostfsidSubjectProvider, srv Server) Server { +func NewAPEServer(router policyengine.ChainRouter, reader containers, ir ir, nm netmap.Source, frostFSIDClient frostfsidcore.SubjectProvider, srv Server) Server { return &apeChecker{ router: router, reader: reader, @@ -574,7 +565,7 @@ func (ac *apeChecker) namespaceByOwner(owner *refs.OwnerID) (string, error) { if err == nil { namespace = subject.Namespace } else { - if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return "", fmt.Errorf("get subject error: %w", err) } } @@ -630,7 +621,7 @@ func (ac *apeChecker) fillWithUserClaimTags(reqProps map[string]string, pk *keys } subj, err := ac.frostFSIDClient.GetSubject(pk.GetScriptHash()) if err != nil { - if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return nil, fmt.Errorf("get subject error: %w", err) } return reqProps, nil diff --git a/pkg/services/container/ape_test.go b/pkg/services/container/ape_test.go index e26e82d43..a2fe79956 100644 --- a/pkg/services/container/ape_test.go +++ b/pkg/services/container/ape_test.go @@ -15,6 +15,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" @@ -922,13 +923,22 @@ func (s *netmapStub) Epoch() (uint64, error) { } type frostfsidStub struct { - subjects map[util.Uint160]*client.Subject + subjects map[util.Uint160]*client.Subject + subjectsExt map[util.Uint160]*client.SubjectExtended } func (f *frostfsidStub) GetSubject(owner util.Uint160) (*client.Subject, error) { s, ok := f.subjects[owner] if !ok { - return nil, fmt.Errorf("%s", subjectNotFoundErrorMessage) + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) + } + return s, nil +} + +func (f *frostfsidStub) GetSubjectExtended(owner util.Uint160) (*client.SubjectExtended, error) { + s, ok := f.subjectsExt[owner] + if !ok { + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) } return s, nil } @@ -965,7 +975,8 @@ func newTestAPEServer() testAPEServer { netmap := &netmapStub{} frostfsIDSubjectReader := &frostfsidStub{ - subjects: map[util.Uint160]*client.Subject{}, + subjects: map[util.Uint160]*client.Subject{}, + subjectsExt: map[util.Uint160]*client.SubjectExtended{}, } apeChecker := &apeChecker{ diff --git a/pkg/services/object/ape/checker.go b/pkg/services/object/ape/checker.go index 170787317..e74b05379 100644 --- a/pkg/services/object/ape/checker.go +++ b/pkg/services/object/ape/checker.go @@ -6,7 +6,7 @@ import ( "fmt" objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" - "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" oid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user" @@ -14,7 +14,6 @@ import ( policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" nativeschema "git.frostfs.info/TrueCloudLab/policy-engine/schema/native" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/util" ) type checkerImpl struct { @@ -22,14 +21,10 @@ type checkerImpl struct { headerProvider HeaderProvider - frostFSIDClient frostfsidSubjectProvider + frostFSIDClient frostfsidcore.SubjectProvider } -type frostfsidSubjectProvider interface { - GetSubject(util.Uint160) (*client.Subject, error) -} - -func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidSubjectProvider) Checker { +func NewChecker(chainRouter policyengine.ChainRouter, headerProvider HeaderProvider, frostFSIDClient frostfsidcore.SubjectProvider) Checker { return &checkerImpl{ chainRouter: chainRouter, diff --git a/pkg/services/object/ape/checker_test.go b/pkg/services/object/ape/checker_test.go index 9510bf039..c591bc494 100644 --- a/pkg/services/object/ape/checker_test.go +++ b/pkg/services/object/ape/checker_test.go @@ -7,6 +7,7 @@ import ( "testing" "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -156,14 +157,15 @@ var ( ) type frostfsIDProviderMock struct { - m map[util.Uint160]*client.Subject + subjects map[util.Uint160]*client.Subject + subjectsExtended map[util.Uint160]*client.SubjectExtended } -var _ frostfsidSubjectProvider = (*frostfsIDProviderMock)(nil) +var _ frostfsidcore.SubjectProvider = (*frostfsIDProviderMock)(nil) func newFrostfsIDProviderMock(t *testing.T) *frostfsIDProviderMock { return &frostfsIDProviderMock{ - m: map[util.Uint160]*client.Subject{ + subjects: map[util.Uint160]*client.Subject{ scriptHashFromSenderKey(t, senderKey): { Namespace: "testnamespace", Name: "test", @@ -173,6 +175,27 @@ func newFrostfsIDProviderMock(t *testing.T) *frostfsIDProviderMock { }, }, }, + subjectsExtended: map[util.Uint160]*client.SubjectExtended{ + scriptHashFromSenderKey(t, senderKey): { + Namespace: "testnamespace", + Name: "test", + KV: map[string]string{ + "tag-attr1": "value1", + "tag-attr2": "value2", + }, + Groups: []*client.Group{ + { + ID: 1, + Name: "test", + Namespace: "testnamespace", + KV: map[string]string{ + "attr1": "value1", + "attr2": "value2", + }, + }, + }, + }, + }, } } @@ -183,9 +206,17 @@ func scriptHashFromSenderKey(t *testing.T, senderKey string) util.Uint160 { } func (f *frostfsIDProviderMock) GetSubject(key util.Uint160) (*client.Subject, error) { - v, ok := f.m[key] + v, ok := f.subjects[key] if !ok { - return nil, fmt.Errorf("%s", subjectNotFoundErrorMessage) + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) + } + return v, nil +} + +func (f *frostfsIDProviderMock) GetSubjectExtended(key util.Uint160) (*client.SubjectExtended, error) { + v, ok := f.subjectsExtended[key] + if !ok { + return nil, fmt.Errorf("%s", frostfsidcore.SubjectNotFoundErrorMessage) } return v, nil } diff --git a/pkg/services/object/ape/request.go b/pkg/services/object/ape/request.go index 5daf8751b..82b6adb1f 100644 --- a/pkg/services/object/ape/request.go +++ b/pkg/services/object/ape/request.go @@ -8,6 +8,7 @@ import ( objectV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/object" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" objectSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object" @@ -18,10 +19,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) -const ( - subjectNotFoundErrorMessage = "subject not found" -) - var defaultRequest = aperequest.Request{} func nativeSchemaRole(role acl.Role) string { @@ -153,7 +150,7 @@ func (c *checkerImpl) fillWithUserClaimTags(reqProps map[string]string, prm Prm) } subj, err := c.frostFSIDClient.GetSubject(pk.GetScriptHash()) if err != nil { - if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return nil, fmt.Errorf("get subject error: %w", err) } return reqProps, nil diff --git a/pkg/services/tree/ape.go b/pkg/services/tree/ape.go index 76ec254f0..47e7cb41d 100644 --- a/pkg/services/tree/ape.go +++ b/pkg/services/tree/ape.go @@ -8,6 +8,7 @@ import ( "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/converter" aperequest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/ape/request" core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status" cnrSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl" @@ -19,8 +20,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/keys" ) -var subjectNotFoundErrorMessage = "subject not found" - func (s *Service) checkAPE(container *core.Container, cid cid.ID, operation acl.Op, role acl.Role, publicKey *keys.PublicKey) error { namespace := "" cntNamespace, hasNamespace := strings.CutSuffix(cnrSDK.ReadDomain(container.Value).Zone(), ".ns") @@ -83,7 +82,7 @@ func (s *Service) fillWithUserClaimTags(reqProps map[string]string, publicKey *k } subj, err := s.frostfsidSubjectProvider.GetSubject(publicKey.GetScriptHash()) if err != nil { - if !strings.Contains(err.Error(), subjectNotFoundErrorMessage) { + if !strings.Contains(err.Error(), frostfsidcore.SubjectNotFoundErrorMessage) { return nil, fmt.Errorf("get subject error: %w", err) } return reqProps, nil diff --git a/pkg/services/tree/options.go b/pkg/services/tree/options.go index c4ef80856..a99ba6046 100644 --- a/pkg/services/tree/options.go +++ b/pkg/services/tree/options.go @@ -4,21 +4,16 @@ import ( "crypto/ecdsa" "time" - "git.frostfs.info/TrueCloudLab/frostfs-contract/frostfsid/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container" + frostfsidcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/frostfsid" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/local_object_storage/pilorama" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id" policyengine "git.frostfs.info/TrueCloudLab/policy-engine/pkg/engine" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/util" ) -type FrostfsidSubjectProvider interface { - GetSubject(util.Uint160) (*client.Subject, error) -} - type ContainerSource interface { container.Source @@ -36,7 +31,7 @@ type cfg struct { rawPub []byte nmSource netmap.Source cnrSource ContainerSource - frostfsidSubjectProvider FrostfsidSubjectProvider + frostfsidSubjectProvider frostfsidcore.SubjectProvider eaclSource container.EACLSource forest pilorama.Forest // replication-related parameters @@ -62,7 +57,7 @@ func WithContainerSource(src ContainerSource) Option { } } -func WithFrostfsidSubjectProvider(provider FrostfsidSubjectProvider) Option { +func WithFrostfsidSubjectProvider(provider frostfsidcore.SubjectProvider) Option { return func(c *cfg) { c.frostfsidSubjectProvider = provider }