Skip to content

Commit

Permalink
node: Support wildcard for container sessions
Browse files Browse the repository at this point in the history
Do not require container ID to be set if wildcard is true. Also, for all
containers case check that a requested operation relates a container that
belongs to the attached token's issuer.

Signed-off-by: Pavel Karpy <[email protected]>
  • Loading branch information
carpawell committed Feb 13, 2024
1 parent d54311b commit 6500422
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 11 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Changelog for NeoFS Node
### Added

### Fixed
- Inability to deploy contract with non-standard zone via neofs-adm
- Inability to deploy contract with non-standard zone via neofs-adm (#2740)
- Container session token's `wildcard` field support (#2741)

### Changed

Expand Down
40 changes: 32 additions & 8 deletions pkg/services/container/morph/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/nspcc-dev/neofs-api-go/v2/refs"
sessionV2 "github.com/nspcc-dev/neofs-api-go/v2/session"
"github.com/nspcc-dev/neofs-api-go/v2/util/signature"
crypto "github.com/nspcc-dev/neofs-crypto"
containercore "github.com/nspcc-dev/neofs-node/pkg/core/container"
containerSvc "github.com/nspcc-dev/neofs-node/pkg/services/container"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
Expand Down Expand Up @@ -335,22 +336,45 @@ func (s *morphExecutor) validateToken(t *sessionV2.Token, cIDV2 *refs.ContainerI
return fmt.Errorf("incorrect token signature: %w", err)
}

if cIDV2 == nil { // can be nil for PUT or wildcard may be true
if cIDV2 == nil { // can be nil for PUT
return nil
}

if sessionCID := cc.ContainerID().GetValue(); !bytes.Equal(sessionCID, cIDV2.GetValue()) {
return fmt.Errorf("wrong container: %s", base58.Encode(sessionCID))
}
var cIDRequested cid.ID

var cID cid.ID

err = cID.ReadFromV2(*cIDV2)
err = cIDRequested.ReadFromV2(*cIDV2)
if err != nil {
return fmt.Errorf("invalid container ID: %w", err)
}

cnr, err := s.rdr.Get(cID)
if cc.Wildcard() {
keyFromToken := crypto.UnmarshalPublicKey(t.GetSignature().GetKey())
if keyFromToken == nil {
return errors.New("error while decoding public key from the token's signer")

Check warning on line 353 in pkg/services/container/morph/executor.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/container/morph/executor.go#L353

Added line #L353 was not covered by tests
}

userFromToken := user.ResolveFromECDSAPublicKey(*keyFromToken)

cIDs, err := s.rdr.List(&userFromToken)
if err != nil {
return fmt.Errorf("reading container list: %w", err)

Check warning on line 360 in pkg/services/container/morph/executor.go

View check run for this annotation

Codecov / codecov/patch

pkg/services/container/morph/executor.go#L360

Added line #L360 was not covered by tests
}

for _, cIDRead := range cIDs {
if cIDRead.Equals(cIDRequested) {
return nil
}
}

return fmt.Errorf("requested container ID does not belong to the token's owner: cID: %s, owner: %s",
cIDRequested, userFromToken)
}

if sessionCID := cc.ContainerID().GetValue(); !bytes.Equal(sessionCID, cIDV2.GetValue()) {
return fmt.Errorf("wrong container: %s", base58.Encode(sessionCID))
}

cnr, err := s.rdr.Get(cIDRequested)
if err != nil {
return fmt.Errorf("reading container from the network: %w", err)
}
Expand Down
48 changes: 46 additions & 2 deletions pkg/services/container/morph/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ package container_test

import (
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/sha256"
"testing"

"github.com/google/uuid"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-api-go/v2/container"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
Expand All @@ -17,6 +21,7 @@ import (
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
containertest "github.com/nspcc-dev/neofs-sdk-go/container/test"
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa"
sessionsdk "github.com/nspcc-dev/neofs-sdk-go/session"
sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test"
"github.com/nspcc-dev/neofs-sdk-go/user"
Expand All @@ -25,7 +30,8 @@ import (
)

type mock struct {
cnr containerSDK.Container
cnr containerSDK.Container
list []cid.ID
}

func (m mock) Get(_ cid.ID) (*containerCore.Container, error) {
Expand All @@ -37,7 +43,7 @@ func (m mock) GetEACL(id cid.ID) (*containerCore.EACL, error) {
}

func (m mock) List(id *user.ID) ([]cid.ID, error) {
return nil, nil
return m.list, nil
}

func (m mock) Put(_ containerCore.Container) (*cid.ID, error) {
Expand Down Expand Up @@ -279,6 +285,44 @@ func TestValidateToken(t *testing.T) {
_, err = e.Delete(context.TODO(), &tokV2, &reqBody)
require.Error(t, err)
})

t.Run("wildcard support", func(t *testing.T) {
var reqBody container.DeleteRequestBody
reqBody.SetContainerID(&cIDV2)

var tok sessionsdk.Container

priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)

tok.SetExp(11)
tok.SetNbf(22)
tok.SetIat(33)
tok.ForVerb(sessionsdk.VerbContainerDelete)
tok.SetID(uuid.New())
tok.SetAuthKey((*neofsecdsa.PublicKey)(&priv.PublicKey))
require.NoError(t, tok.Sign(signer))

var tokV2 session.Token
tok.WriteToV2(&tokV2)

m := &mock{cnr: cnr}
e := containerSvcMorph.NewExecutor(m, m)

t.Run("wrong owner", func(t *testing.T) {
m.list = []cid.ID{cidtest.ID()}

_, err := e.Delete(context.TODO(), &tokV2, &reqBody)
require.Error(t, err)
})

t.Run("correct owner", func(t *testing.T) {
m.list = []cid.ID{cID}

_, err := e.Delete(context.TODO(), &tokV2, &reqBody)
require.NoError(t, err)
})
})
}

func generateToken(t *testing.T, ctx session.TokenContext, signer user.Signer) *session.Token {
Expand Down

0 comments on commit 6500422

Please sign in to comment.