forked from TrueCloudLab/frostfs-node
[#525] ir/container: Check session verb and container ID
Token of the container session should be written out with container context. The context should have the verb corresponding to the operation. If an operation is performed on a fixed container, the session should be propagated to it or to all user containers Implement all described checks in validation of `Put` / `Delete` / `SetEACL` events. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
25d87809c8
commit
23c5277014
3 changed files with 80 additions and 9 deletions
|
@ -8,12 +8,19 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/owner"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/session"
|
||||
"github.com/nspcc-dev/neofs-api-go/util/signature"
|
||||
signature2 "github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||
)
|
||||
|
||||
var (
|
||||
errWrongSessionContext = errors.New("wrong session context")
|
||||
errWrongSessionVerb = errors.New("wrong token verb")
|
||||
errWrongCID = errors.New("wrong container ID")
|
||||
)
|
||||
|
||||
type ownerIDSource interface {
|
||||
OwnerID() *owner.ID
|
||||
}
|
||||
|
@ -125,3 +132,37 @@ func (cp *Processor) checkSessionToken(token *session.Token) error {
|
|||
|
||||
return cp.checkKeyOwnership(token, key)
|
||||
}
|
||||
|
||||
type verbAssert func(*session.ContainerContext) bool
|
||||
|
||||
func contextWithVerifiedVerb(tok *session.Token, verbAssert verbAssert) (*session.ContainerContext, error) {
|
||||
c := session.GetContainerContext(tok)
|
||||
if c == nil {
|
||||
return nil, errWrongSessionContext
|
||||
}
|
||||
|
||||
if !verbAssert(c) {
|
||||
return nil, errWrongSessionVerb
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func checkTokenContext(tok *session.Token, verbAssert verbAssert) error {
|
||||
_, err := contextWithVerifiedVerb(tok, verbAssert)
|
||||
return err
|
||||
}
|
||||
|
||||
func checkTokenContextWithCID(tok *session.Token, id *cid.ID, verbAssert verbAssert) error {
|
||||
c, err := contextWithVerifiedVerb(tok, verbAssert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
tokCID := c.Container()
|
||||
if tokCID != nil && !tokCID.Equal(id) {
|
||||
return errWrongCID
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
containerSDK "github.com/nspcc-dev/neofs-api-go/pkg/container"
|
||||
cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/session"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/core/container"
|
||||
containerEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/container"
|
||||
"go.uber.org/zap"
|
||||
|
@ -67,7 +70,15 @@ func (cp *Processor) checkPutContainer(e *containerEvent.Put) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// TODO: check verb and CID
|
||||
if tok != nil {
|
||||
// check token context
|
||||
err = checkTokenContext(tok, func(c *session.ContainerContext) bool {
|
||||
return c.IsForPut()
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cnr.SetSessionToken(tok)
|
||||
|
||||
|
@ -104,10 +115,10 @@ func (cp *Processor) processContainerDelete(delete *containerEvent.Delete) {
|
|||
}
|
||||
|
||||
func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
|
||||
cid := e.ContainerID()
|
||||
binCID := e.ContainerID()
|
||||
|
||||
// receive owner of the related container
|
||||
cnr, err := cp.cnrClient.Get(cid)
|
||||
cnr, err := cp.cnrClient.Get(binCID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not receive the container: %w", err)
|
||||
}
|
||||
|
@ -120,13 +131,25 @@ func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
|
|||
var checkKeys keys.PublicKeys
|
||||
|
||||
if token != nil {
|
||||
// check token context
|
||||
// TODO: think how to avoid version casts
|
||||
idV2 := new(refs.ContainerID)
|
||||
idV2.SetValue(binCID)
|
||||
|
||||
id := cid.NewFromV2(idV2)
|
||||
|
||||
err = checkTokenContextWithCID(token, id, func(c *session.ContainerContext) bool {
|
||||
return c.IsForDelete()
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
key, err := keys.NewPublicKeyFromBytes(token.SessionKey(), elliptic.P256())
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid session key: %w", err)
|
||||
}
|
||||
|
||||
// TODO: check verb and container ID
|
||||
|
||||
// check token ownership
|
||||
err = cp.checkKeyOwnershipWithToken(cnr, key, token)
|
||||
if err != nil {
|
||||
|
@ -143,7 +166,7 @@ func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
|
|||
}
|
||||
|
||||
// verify signature
|
||||
cidHash := sha256.Sum256(cid)
|
||||
cidHash := sha256.Sum256(binCID)
|
||||
sig := e.Signature()
|
||||
|
||||
for _, key := range checkKeys {
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl"
|
||||
"github.com/nspcc-dev/neofs-api-go/pkg/session"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
|
||||
"github.com/nspcc-dev/neofs-node/pkg/morph/event/container"
|
||||
"go.uber.org/zap"
|
||||
|
@ -67,9 +68,15 @@ func (cp *Processor) checkSetEACL(e container.SetEACL) error {
|
|||
return err
|
||||
}
|
||||
|
||||
cnr.SetSessionToken(tok)
|
||||
|
||||
// TODO: check verb and container ID
|
||||
if tok != nil {
|
||||
// check token context
|
||||
err = checkTokenContextWithCID(tok, table.CID(), func(c *session.ContainerContext) bool {
|
||||
return c.IsForSetEACL()
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// check key ownership
|
||||
return cp.checkKeyOwnership(cnr, key)
|
||||
|
|
Loading…
Reference in a new issue