Remove Container.SetEACL method #1219

Merged
fyrchik merged 1 commit from fyrchik/frostfs-node:remove-eacl into master 2024-07-02 13:05:48 +00:00
8 changed files with 8 additions and 338 deletions

View file

@ -254,17 +254,3 @@ func (m morphContainerWriter) Put(cnr containerCore.Container) (*cid.ID, error)
func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error {
return cntClient.Delete(m.neoClient, witness)
}
func (m morphContainerWriter) PutEACL(eaclInfo containerCore.EACL) error {
err := cntClient.PutEACL(m.neoClient, eaclInfo)
if err != nil {
return err
}
if m.cacheEnabled {
id, _ := eaclInfo.Value.CID()
m.eacls.InvalidateEACL(id)
}
return nil
}

View file

@ -14,6 +14,8 @@ const (
InterruptPlacementIterationByContext = "interrupt placement iteration by context"
Notification = "notification"
SkipDeprecatedNotification = "skip deprecated notification"
)
const (

View file

@ -49,21 +49,6 @@ func (cp *Processor) handleDelete(ev event.Event) {
}
}
func (cp *Processor) handleSetEACL(ev event.Event) {
e := ev.(containerEvent.SetEACL)
cp.log.Info(logs.Notification,
zap.String("type", "set EACL"),
)
// send an event to the worker pool
err := processors.SubmitEvent(cp.pool, cp.metrics, "container_set_eacl", func() bool {
return cp.processSetEACL(e)
})
if err != nil {
// there system can be moved into controlled degradation stage
cp.log.Warn(logs.ContainerContainerProcessorWorkerPoolDrained,
zap.Int("capacity", cp.pool.Cap()))
}
func (cp *Processor) handleSetEACL(_ event.Event) {
cp.log.Warn(logs.SkipDeprecatedNotification, zap.String("type", "set EACL"))
}

View file

@ -18,10 +18,8 @@ import (
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/version"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/network/payload"
@ -159,91 +157,6 @@ func TestDeleteEvent(t *testing.T) {
require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests")
}
func TestSetEACLEvent(t *testing.T) {
t.Parallel()
nst := &testNetworkState{
homHashDisabled: true,
epoch: 100,
}
cc := &testContainerClient{
get: make(map[string]*containercore.Container),
}
mc := &testMorphClient{}
proc, err := New(&Params{
Log: test.NewLogger(t),
PoolSize: 2,
AlphabetState: &testAlphabetState{isAlphabet: true},
NetworkState: nst,
ContainerClient: cc,
MorphClient: mc,
FrostFSIDClient: &testFrostFSIDClient{},
})
require.NoError(t, err, "failed to create processor")
p, err := keys.NewPrivateKey()
require.NoError(t, err)
var usr user.ID
user.IDFromKey(&usr, (ecdsa.PublicKey)(*p.PublicKey()))
var pp netmap.PlacementPolicy
pp.AddReplicas(netmap.ReplicaDescriptor{})
var cnr containerSDK.Container
cnr.Init()
cnr.SetOwner(usr)
cnr.SetPlacementPolicy(pp)
cnr.SetBasicACL(acl.PrivateExtended)
containerSDK.DisableHomomorphicHashing(&cnr)
var cid cid.ID
containerSDK.CalculateID(&cid, cnr)
cidBytes := make([]byte, 32)
cid.Encode(cidBytes)
var signature frostfscrypto.Signature
signer := frostfsecdsa.Signer(p.PrivateKey)
require.NoError(t, signature.Calculate(signer, cidBytes), "failed to calculate signature")
cc.get[hex.EncodeToString(cidBytes)] = &containercore.Container{
Value: cnr,
Signature: signature,
}
table := eacl.NewTable()
table.SetCID(cid)
table.SetVersion(version.Current())
r := &eacl.Record{}
r.AddObjectContainerIDFilter(eacl.MatchStringEqual, cid)
table.AddRecord(r)
nr := &payload.P2PNotaryRequest{
MainTransaction: &transaction.Transaction{},
}
event := containerEvent.SetEACL{
TableValue: table.ToV2().StableMarshal(nil),
PublicKeyValue: p.PublicKey().Bytes(),
SignatureValue: p.Sign(table.ToV2().StableMarshal(nil)),
NotaryRequestValue: nr,
}
proc.handleSetEACL(event)
for proc.pool.Running() > 0 {
time.Sleep(10 * time.Millisecond)
}
var expectedPutEACL cntClient.PutEACLPrm
expectedPutEACL.SetTable(table.ToV2().StableMarshal(nil))
expectedPutEACL.SetKey(p.PublicKey().Bytes())
expectedPutEACL.SetSignature(p.Sign(table.ToV2().StableMarshal(nil)))
require.EqualValues(t, []*transaction.Transaction{nr.MainTransaction}, mc.transactions, "invalid notary requests")
}
type testAlphabetState struct {
isAlphabet bool
}

View file

@ -1,82 +0,0 @@
package container
import (
"errors"
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-node/internal/logs"
cntClient "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client/container"
containerEvent "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/event/container"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
"go.uber.org/zap"
)
func (cp *Processor) processSetEACL(e containerEvent.SetEACL) bool {
if !cp.alphabetState.IsAlphabet() {
cp.log.Info(logs.ContainerNonAlphabetModeIgnoreSetEACL)
return true
}
err := cp.checkSetEACL(e)
if err != nil {
cp.log.Error(logs.ContainerSetEACLCheckFailed,
zap.String("error", err.Error()),
)
return false
}
if err := cp.morphClient.NotarySignAndInvokeTX(e.NotaryRequest().MainTransaction); err != nil {
cp.log.Error(logs.ContainerCouldNotApproveSetEACL,
zap.String("error", err.Error()),
)
return false
}
return true
}
func (cp *Processor) checkSetEACL(e containerEvent.SetEACL) error {
binTable := e.Table()
// unmarshal table
table := eacl.NewTable()
err := table.Unmarshal(binTable)
if err != nil {
return fmt.Errorf("invalid binary table: %w", err)
}
idCnr, ok := table.CID()
if !ok {
return errors.New("missing container ID in eACL table")
}
// receive owner of the related container
cnr, err := cntClient.Get(cp.cnrClient, idCnr)
if err != nil {
return fmt.Errorf("could not receive the container: %w", err)
}
// ACL extensions can be disabled by basic ACL, check it
if !cnr.Value.BasicACL().Extendable() {
return errors.New("ACL extension disabled by container basic ACL")
}
err = cp.verifySignature(signatureVerificationData{
ownerContainer: cnr.Value.Owner(),
verb: session.VerbContainerSetEACL,
idContainerSet: true,
idContainer: idCnr,
binTokenSession: e.SessionToken(),
binPublicKey: e.PublicKey(),
signature: e.Signature(),
signedData: binTable,
})
if err != nil {
return fmt.Errorf("auth eACL table setting: %w", err)
}
return nil
}

View file

@ -1,93 +0,0 @@
package container
import (
"fmt"
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/refs"
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
)
// PutEACL marshals table, and passes it to Wrapper's PutEACLBinary method
// along with sig.Key() and sig.Sign().
//
// Returns error if table is nil.
//
// If TryNotary is provided, calls notary contract.
func PutEACL(c *Client, eaclInfo containercore.EACL) error {
if eaclInfo.Value == nil {
return errNilArgument
}
data, err := eaclInfo.Value.Marshal()
if err != nil {
return fmt.Errorf("can't marshal eacl table: %w", err)
}
var prm PutEACLPrm
prm.SetTable(data)
if eaclInfo.Session != nil {
prm.SetToken(eaclInfo.Session.Marshal())
}
// TODO(@cthulhu-rider): #468 implement and use another approach to avoid conversion
var sigV2 refs.Signature
eaclInfo.Signature.WriteToV2(&sigV2)
prm.SetKey(sigV2.GetKey())
prm.SetSignature(sigV2.GetSign())
return c.PutEACL(prm)
}
// PutEACLPrm groups parameters of PutEACL operation.
type PutEACLPrm struct {
table []byte
key []byte
sig []byte
token []byte
client.InvokePrmOptional
}
// SetTable sets table.
func (p *PutEACLPrm) SetTable(table []byte) {
p.table = table
}
// SetKey sets key.
func (p *PutEACLPrm) SetKey(key []byte) {
p.key = key
}
// SetSignature sets signature.
func (p *PutEACLPrm) SetSignature(sig []byte) {
p.sig = sig
}
// SetToken sets session token.
func (p *PutEACLPrm) SetToken(token []byte) {
p.token = token
}
// PutEACL saves binary eACL table with its session token, key and signature
// in FrostFS system through Container contract call.
//
// Returns any error encountered that caused the saving to interrupt.
func (c *Client) PutEACL(p PutEACLPrm) error {
if len(p.sig) == 0 || len(p.key) == 0 {
return errNilArgument
}
prm := client.InvokePrm{}
prm.SetMethod(setEACLMethod)
prm.SetArgs(p.table, p.sig, p.key, p.token)
prm.InvokePrmOptional = p.InvokePrmOptional
_, err := c.client.Invoke(prm)
if err != nil {
return fmt.Errorf("could not invoke method (%s): %w", setEACLMethod, err)
}
return nil
}

View file

@ -11,9 +11,10 @@ import (
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
containerSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container"
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
eaclSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/session"
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var errMissingUserID = errors.New("missing user ID")
@ -40,8 +41,6 @@ type Writer interface {
Put(containercore.Container) (*cid.ID, error)
// Delete removes specified container from the side chain.
Delete(containercore.RemovalWitness) error
// PutEACL updates extended ACL table of specified container in the side chain.
PutEACL(containercore.EACL) error
}
func NewExecutor(rdr Reader, wrt Writer) containerSvc.ServiceExecutor {
@ -205,37 +204,8 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody)
return res, nil
}
func (s *morphExecutor) SetExtendedACL(_ context.Context, tokV2 *sessionV2.Token, body *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) {
sigV2 := body.GetSignature()
if sigV2 == nil {
// TODO(@cthulhu-rider): #468 use "const" error
return nil, errors.New("missing signature")
}
eaclInfo := containercore.EACL{
Value: eaclSDK.NewTableFromV2(body.GetEACL()),
}
err := eaclInfo.Signature.ReadFromV2(*sigV2)
if err != nil {
return nil, fmt.Errorf("can't read signature: %w", err)
}
if tokV2 != nil {
eaclInfo.Session = new(session.Container)
err := eaclInfo.Session.ReadFromV2(*tokV2)
if err != nil {
return nil, fmt.Errorf("invalid session token: %w", err)
}
}
err = s.wrt.PutEACL(eaclInfo)
if err != nil {
return nil, err
}
return new(container.SetExtendedACLResponseBody), nil
func (s *morphExecutor) SetExtendedACL(_ context.Context, _ *sessionV2.Token, _ *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) {
return nil, status.Errorf(codes.Unimplemented, "method SetExtendedACL not implemented")
}
func (s *morphExecutor) GetExtendedACL(_ context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) {

View file

@ -96,17 +96,6 @@ func TestInvalidToken(t *testing.T) {
return
},
},
{
name: "setEACL",
op: func(e containerSvc.ServiceExecutor, tokV2 *session.Token) (err error) {
var reqBody container.SetExtendedACLRequestBody
reqBody.SetSignature(new(refs.Signature))
sign(&reqBody)
_, err = e.SetExtendedACL(context.TODO(), tokV2, &reqBody)
return
},
},
}
for _, test := range tests {