[#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:
Leonard Lyubich 2021-05-28 15:39:27 +03:00 committed by Leonard Lyubich
parent 25d87809c8
commit 23c5277014
3 changed files with 80 additions and 9 deletions

View file

@ -8,12 +8,19 @@ import (
"fmt" "fmt"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "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/owner"
"github.com/nspcc-dev/neofs-api-go/pkg/session" "github.com/nspcc-dev/neofs-api-go/pkg/session"
"github.com/nspcc-dev/neofs-api-go/util/signature" "github.com/nspcc-dev/neofs-api-go/util/signature"
signature2 "github.com/nspcc-dev/neofs-api-go/v2/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 { type ownerIDSource interface {
OwnerID() *owner.ID OwnerID() *owner.ID
} }
@ -125,3 +132,37 @@ func (cp *Processor) checkSessionToken(token *session.Token) error {
return cp.checkKeyOwnership(token, key) 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
}

View file

@ -8,6 +8,9 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
containerSDK "github.com/nspcc-dev/neofs-api-go/pkg/container" 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" "github.com/nspcc-dev/neofs-node/pkg/core/container"
containerEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/container" containerEvent "github.com/nspcc-dev/neofs-node/pkg/morph/event/container"
"go.uber.org/zap" "go.uber.org/zap"
@ -67,7 +70,15 @@ func (cp *Processor) checkPutContainer(e *containerEvent.Put) error {
return err 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) cnr.SetSessionToken(tok)
@ -104,10 +115,10 @@ func (cp *Processor) processContainerDelete(delete *containerEvent.Delete) {
} }
func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error { func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
cid := e.ContainerID() binCID := e.ContainerID()
// receive owner of the related container // receive owner of the related container
cnr, err := cp.cnrClient.Get(cid) cnr, err := cp.cnrClient.Get(binCID)
if err != nil { if err != nil {
return fmt.Errorf("could not receive the container: %w", err) 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 var checkKeys keys.PublicKeys
if token != nil { 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()) key, err := keys.NewPublicKeyFromBytes(token.SessionKey(), elliptic.P256())
if err != nil { if err != nil {
return fmt.Errorf("invalid session key: %w", err) return fmt.Errorf("invalid session key: %w", err)
} }
// TODO: check verb and container ID
// check token ownership // check token ownership
err = cp.checkKeyOwnershipWithToken(cnr, key, token) err = cp.checkKeyOwnershipWithToken(cnr, key, token)
if err != nil { if err != nil {
@ -143,7 +166,7 @@ func (cp *Processor) checkDeleteContainer(e *containerEvent.Delete) error {
} }
// verify signature // verify signature
cidHash := sha256.Sum256(cid) cidHash := sha256.Sum256(binCID)
sig := e.Signature() sig := e.Signature()
for _, key := range checkKeys { for _, key := range checkKeys {

View file

@ -8,6 +8,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "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/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/client/container/wrapper"
"github.com/nspcc-dev/neofs-node/pkg/morph/event/container" "github.com/nspcc-dev/neofs-node/pkg/morph/event/container"
"go.uber.org/zap" "go.uber.org/zap"
@ -67,9 +68,15 @@ func (cp *Processor) checkSetEACL(e container.SetEACL) error {
return err return err
} }
cnr.SetSessionToken(tok) if tok != nil {
// check token context
// TODO: check verb and container ID err = checkTokenContextWithCID(tok, table.CID(), func(c *session.ContainerContext) bool {
return c.IsForSetEACL()
})
if err != nil {
return err
}
}
// check key ownership // check key ownership
return cp.checkKeyOwnership(cnr, key) return cp.checkKeyOwnership(cnr, key)