forked from TrueCloudLab/frostfs-node
[#1219] Remove Container.SetEACL method
Signed-off-by: Evgenii Stratonikov <e.stratonikov@yadro.com>
This commit is contained in:
parent
74842e7f43
commit
91bed3b0ba
8 changed files with 8 additions and 338 deletions
|
@ -254,17 +254,3 @@ func (m morphContainerWriter) Put(cnr containerCore.Container) (*cid.ID, error)
|
||||||
func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error {
|
func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error {
|
||||||
return cntClient.Delete(m.neoClient, witness)
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ const (
|
||||||
InterruptPlacementIterationByContext = "interrupt placement iteration by context"
|
InterruptPlacementIterationByContext = "interrupt placement iteration by context"
|
||||||
|
|
||||||
Notification = "notification"
|
Notification = "notification"
|
||||||
|
|
||||||
|
SkipDeprecatedNotification = "skip deprecated notification"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -49,21 +49,6 @@ func (cp *Processor) handleDelete(ev event.Event) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cp *Processor) handleSetEACL(ev event.Event) {
|
func (cp *Processor) handleSetEACL(_ event.Event) {
|
||||||
e := ev.(containerEvent.SetEACL)
|
cp.log.Warn(logs.SkipDeprecatedNotification, zap.String("type", "set EACL"))
|
||||||
|
|
||||||
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()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,8 @@ import (
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||||
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
frostfscrypto "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto"
|
||||||
frostfsecdsa "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/crypto/ecdsa"
|
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/netmap"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"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/core/transaction"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/network/payload"
|
"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")
|
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 {
|
type testAlphabetState struct {
|
||||||
isAlphabet bool
|
isAlphabet bool
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
|
@ -11,9 +11,10 @@ import (
|
||||||
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
containercore "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
|
||||||
containerSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container"
|
containerSvc "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/container"
|
||||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
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/session"
|
||||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
"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")
|
var errMissingUserID = errors.New("missing user ID")
|
||||||
|
@ -40,8 +41,6 @@ type Writer interface {
|
||||||
Put(containercore.Container) (*cid.ID, error)
|
Put(containercore.Container) (*cid.ID, error)
|
||||||
// Delete removes specified container from the side chain.
|
// Delete removes specified container from the side chain.
|
||||||
Delete(containercore.RemovalWitness) error
|
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 {
|
func NewExecutor(rdr Reader, wrt Writer) containerSvc.ServiceExecutor {
|
||||||
|
@ -205,37 +204,8 @@ func (s *morphExecutor) List(_ context.Context, body *container.ListRequestBody)
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *morphExecutor) SetExtendedACL(_ context.Context, tokV2 *sessionV2.Token, body *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) {
|
func (s *morphExecutor) SetExtendedACL(_ context.Context, _ *sessionV2.Token, _ *container.SetExtendedACLRequestBody) (*container.SetExtendedACLResponseBody, error) {
|
||||||
sigV2 := body.GetSignature()
|
return nil, status.Errorf(codes.Unimplemented, "method SetExtendedACL not implemented")
|
||||||
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) GetExtendedACL(_ context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) {
|
func (s *morphExecutor) GetExtendedACL(_ context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) {
|
||||||
|
|
|
@ -96,17 +96,6 @@ func TestInvalidToken(t *testing.T) {
|
||||||
return
|
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 {
|
for _, test := range tests {
|
||||||
|
|
Loading…
Reference in a new issue