[#1451] writer: Sign EC parts with node's private key

As EC put request may be processed only by container node, so sign requests
with current node private to not to perform APE checks.

Signed-off-by: Dmitrii Stepanov <d.stepanov@yadro.com>
This commit is contained in:
Dmitrii Stepanov 2024-10-28 15:44:47 +03:00
parent 17ec84151b
commit 0befda5f4f
Signed by: dstepanov-yadro
GPG key ID: 237AF1A763293BC0
3 changed files with 36 additions and 11 deletions

View file

@ -37,10 +37,12 @@ type ECWriter struct {
ObjectMeta object.ContentMeta ObjectMeta object.ContentMeta
ObjectMetaValid bool ObjectMetaValid bool
remoteRequestSignKey *ecdsa.PrivateKey
} }
func (e *ECWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error { func (e *ECWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error {
relayed, err := e.relayIfNotContainerNode(ctx, obj) relayed, isContainerNode, err := e.relayIfNotContainerNode(ctx, obj)
if err != nil { if err != nil {
return err return err
} }
@ -60,23 +62,35 @@ func (e *ECWriter) WriteObject(ctx context.Context, obj *objectSDK.Object) error
e.ObjectMetaValid = true e.ObjectMetaValid = true
} }
if isContainerNode {
restoreTokens := e.CommonPrm.ForgetTokens()
defer restoreTokens()
// As request executed on container node, so sign request with container key.
e.remoteRequestSignKey, err = e.Config.KeyStorage.GetKey(nil)
if err != nil {
return err
}
} else {
e.remoteRequestSignKey = e.Key
}
if obj.ECHeader() != nil { if obj.ECHeader() != nil {
return e.writeECPart(ctx, obj) return e.writeECPart(ctx, obj)
} }
return e.writeRawObject(ctx, obj) return e.writeRawObject(ctx, obj)
} }
func (e *ECWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.Object) (bool, error) { func (e *ECWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.Object) (bool, bool, error) {
if e.Relay == nil {
return false, nil
}
currentNodeIsContainerNode, err := e.currentNodeIsContainerNode() currentNodeIsContainerNode, err := e.currentNodeIsContainerNode()
if err != nil { if err != nil {
return false, err return false, false, err
} }
if currentNodeIsContainerNode { if currentNodeIsContainerNode {
// object can be splitted or saved local // object can be splitted or saved local
return false, nil return false, true, nil
}
if e.Relay == nil {
return false, currentNodeIsContainerNode, nil
} }
objID := object.AddressOf(obj).Object() objID := object.AddressOf(obj).Object()
var index uint32 var index uint32
@ -85,9 +99,9 @@ func (e *ECWriter) relayIfNotContainerNode(ctx context.Context, obj *objectSDK.O
index = obj.ECHeader().Index() index = obj.ECHeader().Index()
} }
if err := e.relayToContainerNode(ctx, objID, index); err != nil { if err := e.relayToContainerNode(ctx, objID, index); err != nil {
return false, err return false, false, err
} }
return true, nil return true, currentNodeIsContainerNode, nil
} }
func (e *ECWriter) currentNodeIsContainerNode() (bool, error) { func (e *ECWriter) currentNodeIsContainerNode() (bool, error) {
@ -338,7 +352,7 @@ func (e *ECWriter) writePartRemote(ctx context.Context, obj *objectSDK.Object, n
client.NodeInfoFromNetmapElement(&clientNodeInfo, node) client.NodeInfoFromNetmapElement(&clientNodeInfo, node)
remoteTaget := remoteWriter{ remoteTaget := remoteWriter{
privateKey: e.Key, privateKey: e.remoteRequestSignKey,
clientConstructor: e.Config.ClientConstructor, clientConstructor: e.Config.ClientConstructor,
commonPrm: e.CommonPrm, commonPrm: e.CommonPrm,
nodeInfo: clientNodeInfo, nodeInfo: clientNodeInfo,

View file

@ -14,6 +14,7 @@ import (
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/client"
netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap" netmapcore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/network"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object/util"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/object_manager/placement"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger" "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/logger"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum" "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
@ -127,6 +128,8 @@ func TestECWriter(t *testing.T) {
ownerKey, err := keys.NewPrivateKey() ownerKey, err := keys.NewPrivateKey()
require.NoError(t, err) require.NoError(t, err)
nodeKey, err := keys.NewPrivateKey()
require.NoError(t, err)
pool, err := ants.NewPool(4, ants.WithNonblocking(true)) pool, err := ants.NewPool(4, ants.WithNonblocking(true))
require.NoError(t, err) require.NoError(t, err)
@ -141,6 +144,7 @@ func TestECWriter(t *testing.T) {
RemotePool: pool, RemotePool: pool,
Logger: log, Logger: log,
ClientConstructor: clientConstructor{vectors: ns}, ClientConstructor: clientConstructor{vectors: ns},
KeyStorage: util.NewKeyStorage(&nodeKey.PrivateKey, nil, nil),
}, },
PlacementOpts: append( PlacementOpts: append(
[]placement.Option{placement.UseBuilder(builder), placement.ForContainer(cnr)}, []placement.Option{placement.UseBuilder(builder), placement.ForContainer(cnr)},

View file

@ -100,11 +100,18 @@ func (p *CommonPrm) SetNetmapLookupDepth(v uint64) {
// ForgetTokens forgets all the tokens read from the request's // ForgetTokens forgets all the tokens read from the request's
// meta information before. // meta information before.
func (p *CommonPrm) ForgetTokens() { func (p *CommonPrm) ForgetTokens() func() {
if p != nil { if p != nil {
tk := p.token
br := p.bearer
p.token = nil p.token = nil
p.bearer = nil p.bearer = nil
return func() {
p.token = tk
p.bearer = br
}
} }
return func() {}
} }
func CommonPrmFromV2(req interface { func CommonPrmFromV2(req interface {