[#529] objectcore: Use common sender classifier

Use common sender classifier for ACL service and format validator.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2023-08-07 09:54:47 +03:00
parent ae81d6660a
commit 55b82e744b
5 changed files with 95 additions and 120 deletions

View file

@ -1,10 +1,8 @@
package object
import (
"bytes"
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/sha256"
"errors"
"fmt"
@ -14,18 +12,20 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
netmapSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
objectSDK "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/user"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
)
// FormatValidator represents an object format validator.
type FormatValidator struct {
*cfg
senderClassifier SenderClassifier
}
// FormatValidatorOption represents a FormatValidator constructor option.
@ -37,13 +37,10 @@ type cfg struct {
ir InnerRing
netmap netmap.Source
containers container.Source
log *logger.Logger
verifyTokenIssuer bool
}
type InnerRing interface {
InnerRingKeys() ([][]byte, error)
}
// DeleteHandler is an interface of delete queue processor.
type DeleteHandler interface {
// DeleteObjects places objects to a removal queue.
@ -93,7 +90,8 @@ func NewFormatValidator(opts ...FormatValidatorOption) *FormatValidator {
}
return &FormatValidator{
cfg: cfg,
cfg: cfg,
senderClassifier: NewSenderClassifier(cfg.ir, cfg.netmap, cfg.log),
}
}
@ -193,42 +191,6 @@ func (v *FormatValidator) validateSignatureKey(obj *objectSDK.Object) error {
}
func (v *FormatValidator) isIROrContainerNode(obj *objectSDK.Object, signerKey []byte) (bool, error) {
pKey, err := keys.NewPublicKeyFromBytes(signerKey, elliptic.P256())
if err != nil {
return false, fmt.Errorf("(%T) failed to unmarshal signer public key: %w", v, err)
}
isIR, err := v.isInnerRingKey(pKey.Bytes())
if err != nil {
return false, fmt.Errorf("(%T) failed to check if signer is inner ring node: %w", v, err)
}
if isIR {
return true, nil
}
isContainerNode, err := v.isContainerNode(pKey.Bytes(), obj)
if err != nil {
return false, fmt.Errorf("(%T) failed to check if signer is container node: %w", v, err)
}
return isContainerNode, nil
}
func (v *FormatValidator) isInnerRingKey(key []byte) (bool, error) {
innerRingKeys, err := v.ir.InnerRingKeys()
if err != nil {
return false, err
}
for i := range innerRingKeys {
if bytes.Equal(innerRingKeys[i], key) {
return true, nil
}
}
return false, nil
}
func (v *FormatValidator) isContainerNode(key []byte, obj *objectSDK.Object) (bool, error) {
cnrID, containerIDSet := obj.ContainerID()
if !containerIDSet {
return false, errNilCID
@ -242,46 +204,11 @@ func (v *FormatValidator) isContainerNode(key []byte, obj *objectSDK.Object) (bo
return false, fmt.Errorf("failed to get container (id=%s): %w", cnrID.EncodeToString(), err)
}
lastNetmap, err := netmap.GetLatestNetworkMap(v.netmap)
if err != nil {
return false, fmt.Errorf("failed to get latest netmap: %w", err)
}
isContainerNode, err := v.isContainerNodeKey(lastNetmap, cnr, cnrIDBin, key)
if err != nil {
return false, fmt.Errorf("failed to check latest netmap for container nodes: %w", err)
}
if isContainerNode {
return true, nil
}
previousNetmap, err := netmap.GetPreviousNetworkMap(v.netmap)
if err != nil {
return false, fmt.Errorf("failed to get previous netmap: %w", err)
}
isContainerNode, err = v.isContainerNodeKey(previousNetmap, cnr, cnrIDBin, key)
if err != nil {
return false, fmt.Errorf("failed to check previous netmap for container nodes: %w", err)
}
return isContainerNode, nil
}
func (v *FormatValidator) isContainerNodeKey(nm *netmapSDK.NetMap, cnr *container.Container, cnrIDBin, key []byte) (bool, error) {
cnrVectors, err := nm.ContainerNodes(cnr.Value.PlacementPolicy(), cnrIDBin)
res, err := v.senderClassifier.IsInnerRingOrContainerNode(signerKey, cnrID, cnr.Value)
if err != nil {
return false, err
}
for i := range cnrVectors {
for j := range cnrVectors[i] {
if bytes.Equal(cnrVectors[i][j].PublicKey(), key) {
return true, nil
}
}
}
return false, nil
return res.Role == acl.RoleContainer || res.Role == acl.RoleInnerRing, nil
}
func (v *FormatValidator) checkOwnerKey(id user.ID, key frostfsecdsa.PublicKey) error {
@ -533,3 +460,10 @@ func WithVerifySessionTokenIssuer(verifySessionTokenIssuer bool) FormatValidator
c.verifyTokenIssuer = verifySessionTokenIssuer
}
}
// WithLogger return option to set logger.
func WithLogger(l *logger.Logger) FormatValidatorOption {
return func(c *cfg) {
c.log = l
}
}