[#329] Use suitable tokens for container requests
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
cce79b612a
commit
c383f332d5
6 changed files with 73 additions and 28 deletions
|
@ -549,7 +549,7 @@ func (h *handler) CreateBucketHandler(w http.ResponseWriter, r *http.Request) {
|
|||
boxData, err := layer.GetBoxData(r.Context())
|
||||
if err == nil {
|
||||
policies = boxData.Policies
|
||||
p.SessionToken = boxData.Gate.SessionToken
|
||||
p.SessionToken = boxData.Gate.SessionTokenForPut()
|
||||
}
|
||||
|
||||
if createParams.LocationConstraint != "" {
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/pool"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -170,7 +171,14 @@ func (n *layer) createContainer(ctx context.Context, p *CreateBucketParams) (*ci
|
|||
|
||||
func (n *layer) setContainerEACLTable(ctx context.Context, cid *cid.ID, table *eacl.Table) error {
|
||||
table.SetCID(cid)
|
||||
if err := n.pool.SetEACL(ctx, table, n.SessionOpt(ctx)); err != nil {
|
||||
|
||||
var sessionToken *session.Token
|
||||
boxData, err := GetBoxData(ctx)
|
||||
if err == nil {
|
||||
sessionToken = boxData.Gate.SessionTokenForSetEACL()
|
||||
}
|
||||
|
||||
if err := n.pool.SetEACL(ctx, table, pool.WithSession(sessionToken)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -225,5 +233,10 @@ func (n *layer) waitEACLPresence(ctx context.Context, cid *cid.ID, table *eacl.T
|
|||
}
|
||||
|
||||
func (n *layer) deleteContainer(ctx context.Context, cid *cid.ID) error {
|
||||
return n.pool.DeleteContainer(ctx, cid, n.SessionOpt(ctx))
|
||||
var sessionToken *session.Token
|
||||
boxData, err := GetBoxData(ctx)
|
||||
if err == nil {
|
||||
sessionToken = boxData.Gate.SessionTokenForDelete()
|
||||
}
|
||||
return n.pool.DeleteContainer(ctx, cid, pool.WithSession(sessionToken))
|
||||
}
|
||||
|
|
|
@ -299,15 +299,6 @@ func (n *layer) CallOptions(ctx context.Context) []pool.CallOption {
|
|||
return []pool.CallOption{pool.WithKey(&n.anonKey.Key.PrivateKey)}
|
||||
}
|
||||
|
||||
// SessionOpt returns client.WithSession call option with token from context or with nil token.
|
||||
func (n *layer) SessionOpt(ctx context.Context) pool.CallOption {
|
||||
if data, ok := ctx.Value(api.BoxData).(*accessbox.Box); ok && data != nil && data.Gate != nil {
|
||||
return pool.WithSession(data.Gate.SessionToken)
|
||||
}
|
||||
|
||||
return pool.WithSession(nil)
|
||||
}
|
||||
|
||||
// Get NeoFS Object by refs.Address (should be used by auth.Center).
|
||||
func (n *layer) Get(ctx context.Context, address *object.Address) (*object.Object, error) {
|
||||
ops := new(client.GetObjectParams).WithAddress(address)
|
||||
|
|
|
@ -484,8 +484,8 @@ func createTokens(options *IssueSecretOptions, lifetime lifetimeOptions, cid *ci
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i, sessionToken := range sessionTokens {
|
||||
gates[i].SessionToken = sessionToken[0]
|
||||
for i, sessionTkns := range sessionTokens {
|
||||
gates[i].SessionTokens = sessionTkns
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"io"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
apisession "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/netmap"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
||||
|
@ -35,7 +36,7 @@ type ContainerPolicy struct {
|
|||
type GateData struct {
|
||||
AccessKey string
|
||||
BearerToken *token.BearerToken
|
||||
SessionToken *session.Token
|
||||
SessionTokens []*session.Token
|
||||
GateKey *keys.PublicKey
|
||||
}
|
||||
|
||||
|
@ -44,6 +45,39 @@ func NewGateData(gateKey *keys.PublicKey, bearerTkn *token.BearerToken) *GateDat
|
|||
return &GateData{GateKey: gateKey, BearerToken: bearerTkn}
|
||||
}
|
||||
|
||||
// SessionTokenForPut return the first suitable container session context for PUT operation.
|
||||
func (g *GateData) SessionTokenForPut() *session.Token {
|
||||
return g.containerSessionToken(apisession.ContainerVerbPut)
|
||||
}
|
||||
|
||||
// SessionTokenForDelete return the first suitable container session context for DELETE operation.
|
||||
func (g *GateData) SessionTokenForDelete() *session.Token {
|
||||
return g.containerSessionToken(apisession.ContainerVerbDelete)
|
||||
}
|
||||
|
||||
// SessionTokenForSetEACL return the first suitable container session context for SetEACL operation.
|
||||
func (g *GateData) SessionTokenForSetEACL() *session.Token {
|
||||
return g.containerSessionToken(apisession.ContainerVerbSetEACL)
|
||||
}
|
||||
|
||||
func (g *GateData) containerSessionToken(verb apisession.ContainerSessionVerb) *session.Token {
|
||||
for _, sessionToken := range g.SessionTokens {
|
||||
switch ctx := sessionToken.Context().(type) {
|
||||
case *session.ContainerContext:
|
||||
if isAppropriateContainerContext(ctx, verb) {
|
||||
return sessionToken
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isAppropriateContainerContext(ctx *session.ContainerContext, verb apisession.ContainerSessionVerb) bool {
|
||||
return verb == apisession.ContainerVerbPut && ctx.IsForPut() ||
|
||||
verb == apisession.ContainerVerbDelete && ctx.IsForDelete() ||
|
||||
verb == apisession.ContainerVerbSetEACL && ctx.IsForSetEACL()
|
||||
}
|
||||
|
||||
// Secrets represents AccessKey and key to encrypt gate tokens.
|
||||
type Secrets struct {
|
||||
AccessKey string
|
||||
|
@ -146,18 +180,20 @@ func (x *AccessBox) addTokens(gatesData []*GateData, ephemeralKey *keys.PrivateK
|
|||
if err != nil {
|
||||
return fmt.Errorf("%w, sender = %d", err, i)
|
||||
}
|
||||
var encSession []byte
|
||||
if gate.SessionToken != nil {
|
||||
encSession, err = gate.SessionToken.Marshal()
|
||||
|
||||
encSessions := make([][]byte, len(gate.SessionTokens))
|
||||
for i, sessionToken := range gate.SessionTokens {
|
||||
encSession, err := sessionToken.Marshal()
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w, sender = %d", err, i)
|
||||
}
|
||||
encSessions[i] = encSession
|
||||
}
|
||||
|
||||
tokens := new(Tokens)
|
||||
tokens.AccessKey = secret
|
||||
tokens.BearerToken = encBearer
|
||||
tokens.SessionToken = encSession
|
||||
tokens.SessionTokens = encSessions
|
||||
|
||||
boxGate, err := encodeGate(ephemeralKey, gate.GateKey, tokens)
|
||||
if err != nil {
|
||||
|
@ -199,13 +235,18 @@ func decodeGate(gate *AccessBox_Gate, owner *keys.PrivateKey, sender *keys.Publi
|
|||
if err := bearerTkn.Unmarshal(tokens.BearerToken); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sessionTkns := make([]*session.Token, len(tokens.SessionTokens))
|
||||
for i, encSessionToken := range tokens.SessionTokens {
|
||||
sessionTkn := session.NewToken()
|
||||
if err := sessionTkn.Unmarshal(tokens.SessionToken); err != nil {
|
||||
if err := sessionTkn.Unmarshal(encSessionToken); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sessionTkns[i] = sessionTkn
|
||||
}
|
||||
|
||||
gateData := NewGateData(owner.PublicKey(), bearerTkn)
|
||||
gateData.SessionToken = sessionTkn
|
||||
gateData.SessionTokens = sessionTkns
|
||||
gateData.AccessKey = hex.EncodeToString(tokens.AccessKey)
|
||||
return gateData, nil
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ func Test_session_token_in_access_box(t *testing.T) {
|
|||
require.NoError(t, tkn.Sign(&sec.PrivateKey))
|
||||
|
||||
gate := NewGateData(cred.PublicKey(), token.NewBearerToken())
|
||||
gate.SessionToken = tkn
|
||||
gate.SessionTokens = []*session.Token{tkn}
|
||||
box, _, err = PackTokens([]*GateData{gate})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -107,7 +107,7 @@ func Test_session_token_in_access_box(t *testing.T) {
|
|||
tkns, err := box2.GetTokens(cred)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, tkn, tkns.SessionToken)
|
||||
require.Equal(t, []*session.Token{tkn}, tkns.SessionTokens)
|
||||
}
|
||||
|
||||
func Test_accessbox_multiple_keys(t *testing.T) {
|
||||
|
|
Loading…
Reference in a new issue