Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 25 additions & 6 deletions cmd/neofs-cli/modules/container/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/container/acl"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/netmap"
"github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/nspcc-dev/neofs-sdk-go/waiter"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -113,14 +114,24 @@ It will be stored in FS chain when inner ring will accepts it.`,
return fmt.Errorf("decode basic ACL string: %w", err)
}

tok, err := getSession(cmd)
tokAny, err := getSessionAnyVersion(cmd)
if err != nil {
return err
}

if tok != nil {
issuer := tok.Issuer()
cnr.SetOwner(issuer)
// Set owner based on session token
if tokAny != nil {
switch tok := tokAny.(type) {
case *session.TokenV2:
issuer := tok.Issuer()
if issuer.IsOwnerID() {
cnr.SetOwner(issuer.OwnerID())
} else {
return errors.New("v2 session issuer must be OwnerID for container create")
}
case *session.Container:
cnr.SetOwner(tok.Issuer())
}
} else {
cnr.SetOwner(user.NewFromECDSAPublicKey(key.PublicKey))
}
Expand All @@ -141,8 +152,16 @@ It will be stored in FS chain when inner ring will accepts it.`,
}

var putPrm client.PrmContainerPut
if tok != nil {
putPrm.WithinSession(*tok)
if tokAny != nil {
switch tok := tokAny.(type) {
case *session.TokenV2:
if err := validateSessionV2ForContainer(cmd, tok, key, cid.ID{}, session.VerbV2ContainerPut); err != nil {
return err
}
putPrm.WithinSessionV2(*tok)
case *session.Container:
putPrm.WithinSession(*tok)
}
}

id, err := actor.ContainerPut(ctx, cnr, user.NewAutoIDSignerRFC6979(*key), putPrm)
Expand Down
38 changes: 31 additions & 7 deletions cmd/neofs-cli/modules/container/delete.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package container

import (
"errors"
"fmt"

internalclient "github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/client"
Expand All @@ -10,6 +11,7 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/client"
neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa"
objectSDK "github.com/nspcc-dev/neofs-sdk-go/object"
"github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/nspcc-dev/neofs-sdk-go/waiter"
"github.com/spf13/cobra"
Expand All @@ -27,7 +29,7 @@ Only owner of the container has a permission to remove container.`,
return err
}

tok, err := getSession(cmd)
tokAny, err := getSessionAnyVersion(cmd)
if err != nil {
return err
}
Expand Down Expand Up @@ -56,11 +58,25 @@ Only owner of the container has a permission to remove container.`,

owner := cnr.Owner()

if tok != nil {
if tokAny != nil {
common.PrintVerbose(cmd, "Checking session issuer...")

if tok.Issuer() != owner {
return fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer())
switch tok := tokAny.(type) {
case *session.TokenV2:
issuer := tok.Issuer()
var issuerID user.ID
if issuer.IsOwnerID() {
issuerID = issuer.OwnerID()
} else {
return errors.New("v2 session issuer must be OwnerID")
}
if issuerID != owner {
return fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, issuerID)
}
case *session.Container:
if tok.Issuer() != owner {
return fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer())
}
}
} else {
common.PrintVerbose(cmd, "Checking provided account...")
Expand All @@ -74,7 +90,7 @@ Only owner of the container has a permission to remove container.`,

common.PrintVerbose(cmd, "Account matches the container owner.")

if tok != nil {
if tokAny != nil {
common.PrintVerbose(cmd, "Skip searching for LOCK objects - session provided.")
} else {
fs := objectSDK.NewSearchFilters()
Expand Down Expand Up @@ -108,8 +124,16 @@ Only owner of the container has a permission to remove container.`,
}

var delPrm client.PrmContainerDelete
if tok != nil {
delPrm.WithinSession(*tok)
if tokAny != nil {
switch tok := tokAny.(type) {
case *session.TokenV2:
if err := validateSessionV2ForContainer(cmd, tok, pk, id, session.VerbV2ContainerDelete); err != nil {
return err
}
delPrm.WithinSessionV2(*tok)
case *session.Container:
delPrm.WithinSession(*tok)
}
}

err = actor.ContainerDelete(ctx, id, user.NewAutoIDSignerRFC6979(*pk), delPrm)
Expand Down
35 changes: 29 additions & 6 deletions cmd/neofs-cli/modules/container/set_eacl.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/key"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/modules/util"
"github.com/nspcc-dev/neofs-sdk-go/client"
"github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/nspcc-dev/neofs-sdk-go/waiter"
"github.com/spf13/cobra"
Expand All @@ -35,7 +36,7 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
return err
}

tok, err := getSession(cmd)
tokAny, err := getSessionAnyVersion(cmd)
if err != nil {
return err
}
Expand Down Expand Up @@ -73,11 +74,25 @@ Container ID in EACL table will be substituted with ID from the CLI.`,

owner := cnr.Owner()

if tok != nil {
if tokAny != nil {
common.PrintVerbose(cmd, "Checking session issuer...")

if tok.Issuer() != owner {
return fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer())
switch tok := tokAny.(type) {
case *session.TokenV2:
issuer := tok.Issuer()
var issuerID user.ID
if issuer.IsOwnerID() {
issuerID = issuer.OwnerID()
} else {
return errors.New("v2 session issuer must be OwnerID")
}
if issuerID != owner {
return fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, issuerID)
}
case *session.Container:
if tok.Issuer() != owner {
return fmt.Errorf("session issuer differs with the container owner: expected %s, has %s", owner, tok.Issuer())
}
}
} else {
common.PrintVerbose(cmd, "Checking provided account...")
Expand Down Expand Up @@ -112,8 +127,16 @@ Container ID in EACL table will be substituted with ID from the CLI.`,
}

var setEACLPrm client.PrmContainerSetEACL
if tok != nil {
setEACLPrm.WithinSession(*tok)
if tokAny != nil {
switch tok := tokAny.(type) {
case *session.TokenV2:
if err := validateSessionV2ForContainer(cmd, tok, pk, id, session.VerbV2ContainerSetEACL); err != nil {
return err
}
setEACLPrm.WithinSessionV2(*tok)
case *session.Container:
setEACLPrm.WithinSession(*tok)
}
}
err = actor.ContainerSetEACL(ctx, eaclTable, user.NewAutoIDSignerRFC6979(*pk), setEACLPrm)
if err != nil {
Expand Down
81 changes: 81 additions & 0 deletions cmd/neofs-cli/modules/container/util_session_v2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package container

import (
"crypto/ecdsa"
"errors"
"fmt"

"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/common"
"github.com/nspcc-dev/neofs-node/cmd/neofs-cli/internal/commonflags"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/spf13/cobra"
)

func getSessionV2(cmd *cobra.Command) (*session.TokenV2, error) {
common.PrintVerbose(cmd, "Trying to read V2 container session from the file...")

path, _ := cmd.Flags().GetString(commonflags.SessionToken)
if path == "" {
common.PrintVerbose(cmd, "Session not provided.")
return nil, nil
}

common.PrintVerbose(cmd, "Reading V2 container session from the file [%s]...", path)

var tok session.TokenV2

err := common.ReadBinaryOrJSON(cmd, &tok, path)
if err != nil {
return nil, fmt.Errorf("read V2 container session: %w", err)
}

common.PrintVerbose(cmd, "V2 session successfully read.")
return &tok, nil
}

// getSessionAnyVersion tries V2 token first, then V1.
func getSessionAnyVersion(cmd *cobra.Command) (any, error) {
tokV2, err := getSessionV2(cmd)
if err == nil && tokV2 != nil {
return tokV2, nil
}

tok, err := getSession(cmd)
if err != nil {
return nil, err
}
if tok != nil {
return tok, nil
}

return nil, nil
}

// validateSessionV2ForContainer validates V2 token for container operations.
func validateSessionV2ForContainer(cmd *cobra.Command, tok *session.TokenV2, key *ecdsa.PrivateKey, cnrID cid.ID, verb session.VerbV2) error {
common.PrintVerbose(cmd, "Validating V2 session token...")

if err := tok.Validate(); err != nil {
return fmt.Errorf("invalid V2 session token: %w", err)
}

if !tok.VerifySignature() {
return errors.New("v2 session token signature verification failed")
}

signer := user.NewAutoIDSigner(*key)
target := session.NewTarget(signer.UserID())

if !tok.AssertAuthority(target) {
return fmt.Errorf("user %s is not authorized by V2 session token", signer.UserID().String())
}

if !tok.AssertContainer(verb, cnrID) {
return fmt.Errorf("v2 session token does not authorize %v for container %s", verb, cnrID.String())
}

common.PrintVerbose(cmd, "V2 session token validated successfully")
return nil
}
Loading
Loading