From e252f93dbf0dffcfe68aa1489b52c1b19667e4dd Mon Sep 17 00:00:00 2001
From: Alex Vanin <alexey@nspcc.ru>
Date: Wed, 27 Jan 2021 11:47:40 +0300
Subject: [PATCH] [#350] object/acl: Make best effort to classify request

Classifier looks at list of inner ring nodes and container
nodes from current and previous epoch to classify request.
Sometimes these checks might return error.

Consider there is a request from unknown key and container's
placement policy valid for current epoch and invalid for past
epoch. Classifier tries to find if key belongs to container
node from current epoch -- it is not. Then it tries to find if
key belongs to container node from past epoch and it throws
error, because placement policy is invalid for past epoch.

This is a legit case and classifier should ignore such errors
to provide best effort in matching. The only error classifier
should return is an error when request does not contain
public key to classify it.

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
---
 cmd/neofs-node/object.go              |  1 +
 pkg/services/object/acl/classifier.go | 15 ++++++++++++---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/cmd/neofs-node/object.go b/cmd/neofs-node/object.go
index 715cc83a6..c095275b1 100644
--- a/cmd/neofs-node/object.go
+++ b/cmd/neofs-node/object.go
@@ -287,6 +287,7 @@ func initObjectService(c *cfg) {
 			acl.New(
 				acl.WithSenderClassifier(
 					acl.NewSenderClassifier(
+						c.log,
 						c.cfgNetmap.wrapper,
 						c.cfgNetmap.wrapper,
 					),
diff --git a/pkg/services/object/acl/classifier.go b/pkg/services/object/acl/classifier.go
index 81c8b78f1..b50045bb6 100644
--- a/pkg/services/object/acl/classifier.go
+++ b/pkg/services/object/acl/classifier.go
@@ -16,6 +16,7 @@ import (
 	crypto "github.com/nspcc-dev/neofs-crypto"
 	core "github.com/nspcc-dev/neofs-node/pkg/core/netmap"
 	"github.com/pkg/errors"
+	"go.uber.org/zap"
 )
 
 type (
@@ -31,14 +32,16 @@ type (
 	}
 
 	SenderClassifier struct {
+		log       *zap.Logger
 		innerRing InnerRingFetcher
 		netmap    core.Source
 	}
 )
 
 // fixme: update classifier constructor
-func NewSenderClassifier(ir InnerRingFetcher, nm core.Source) SenderClassifier {
+func NewSenderClassifier(l *zap.Logger, ir InnerRingFetcher, nm core.Source) SenderClassifier {
 	return SenderClassifier{
+		log:       l,
 		innerRing: ir,
 		netmap:    nm,
 	}
@@ -68,14 +71,20 @@ func (c SenderClassifier) Classify(
 
 	isInnerRingNode, err := c.isInnerRingKey(ownerKeyInBytes)
 	if err != nil {
-		return 0, false, nil, errors.Wrap(err, "can't check if request from inner ring")
+		// do not throw error, try best case matching
+		c.log.Debug("can't check if request from inner ring",
+			zap.String("error", err.Error()))
 	} else if isInnerRingNode {
 		return acl.RoleSystem, true, ownerKeyInBytes, nil
 	}
 
 	isContainerNode, err := c.isContainerKey(ownerKeyInBytes, cid.ToV2().GetValue(), cnr)
 	if err != nil {
-		return 0, false, nil, errors.Wrap(err, "can't check if request from container node")
+		// error might happen if request has `RoleOther` key and placement
+		// is not possible for previous epoch, so
+		// do not throw error, try best case matching
+		c.log.Debug("can't check if request from container node",
+			zap.String("error", err.Error()))
 	} else if isContainerNode {
 		return acl.RoleSystem, false, ownerKeyInBytes, nil
 	}