[#83] Added sessionKey to token

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
Denis Kirillov 2021-06-18 18:15:58 +03:00
parent d1594b586e
commit 81408dcc1c
3 changed files with 112 additions and 43 deletions

View file

@ -140,28 +140,17 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
return err return err
} }
oid, err := ownerIDFromNeoFSKey(&options.NeoFSKey.PublicKey) gatesData, err := createTokens(options, cid)
if err != nil {
return err
}
a.log.Info("prepare eACL table")
bearerRules, err := buildEACLTable(cid, options.EACLRules)
if err != nil {
return fmt.Errorf("failed to build eacl table: %w", err)
}
gatesData, err := buildBearerTokens(options.NeoFSKey, bearerRules, options.GatesPublicKeys)
if err != nil { if err != nil {
return fmt.Errorf("failed to build bearer token: %w", err) return fmt.Errorf("failed to build bearer token: %w", err)
} }
sessionTkn, err := createSessionToken(options, oid) box, secrets, err := accessbox.PackTokens(gatesData)
if err != nil { if err != nil {
return fmt.Errorf("failed to create session token: %w", err) return err
} }
box, secrets, err := accessbox.PackTokens(gatesData, sessionTkn) oid, err := ownerIDFromNeoFSKey(&options.NeoFSKey.PublicKey)
if err != nil { if err != nil {
return err return err
} }
@ -291,8 +280,8 @@ func buildContext(rules []byte) (*session.ContainerContext, error) {
return sessionCtx, nil return sessionCtx, nil
} }
func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, ownerKey *ecdsa.PublicKey) (*token.BearerToken, error) { func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, gateKey *ecdsa.PublicKey) (*token.BearerToken, error) {
oid, err := ownerIDFromNeoFSKey(ownerKey) oid, err := ownerIDFromNeoFSKey(gateKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -305,19 +294,19 @@ func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, ownerKey *ecdsa.
return bearerToken, bearerToken.SignToken(key) return bearerToken, bearerToken.SignToken(key)
} }
func buildBearerTokens(key *ecdsa.PrivateKey, table *eacl.Table, ownerKeys []*ecdsa.PublicKey) ([]*accessbox.GateData, error) { func buildBearerTokens(key *ecdsa.PrivateKey, table *eacl.Table, gatesKeys []*ecdsa.PublicKey) ([]*token.BearerToken, error) {
gatesData := make([]*accessbox.GateData, 0, len(ownerKeys)) bearerTokens := make([]*token.BearerToken, 0, len(gatesKeys))
for _, ownerKey := range ownerKeys { for _, gateKey := range gatesKeys {
tkn, err := buildBearerToken(key, table, ownerKey) tkn, err := buildBearerToken(key, table, gateKey)
if err != nil { if err != nil {
return nil, err return nil, err
} }
gatesData = append(gatesData, accessbox.NewGateData(tkn, ownerKey)) bearerTokens = append(bearerTokens, tkn)
} }
return gatesData, nil return bearerTokens, nil
} }
func buildSessionToken(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.ContainerContext) (*session.Token, error) { func buildSessionToken(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.ContainerContext, gateKey *ecdsa.PublicKey) (*session.Token, error) {
tok := session.NewToken() tok := session.NewToken()
tok.SetContext(ctx) tok.SetContext(ctx)
uid, err := uuid.New().MarshalBinary() uid, err := uuid.New().MarshalBinary()
@ -326,19 +315,58 @@ func buildSessionToken(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.Contai
} }
tok.SetID(uid) tok.SetID(uid)
tok.SetOwnerID(oid) tok.SetOwnerID(oid)
tok.SetSessionKey(crypto.MarshalPublicKey(gateKey))
return tok, tok.Sign(key) return tok, tok.Sign(key)
} }
func createSessionToken(options *IssueSecretOptions, oid *owner.ID) (*session.Token, error) { func buildSessionTokens(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.ContainerContext, gatesKeys []*ecdsa.PublicKey) ([]*session.Token, error) {
sessionTokens := make([]*session.Token, 0, len(gatesKeys))
for _, gateKey := range gatesKeys {
tkn, err := buildSessionToken(key, oid, ctx, gateKey)
if err != nil {
return nil, err
}
sessionTokens = append(sessionTokens, tkn)
}
return sessionTokens, nil
}
func createTokens(options *IssueSecretOptions, cid *cid.ID) ([]*accessbox.GateData, error) {
gates := make([]*accessbox.GateData, len(options.GatesPublicKeys))
table, err := buildEACLTable(cid, options.EACLRules)
if err != nil {
return nil, fmt.Errorf("failed to build eacl table: %w", err)
}
bearerTokens, err := buildBearerTokens(options.NeoFSKey, table, options.GatesPublicKeys)
if err != nil {
return nil, fmt.Errorf("failed to build bearer tokens: %w", err)
}
for i, gateKey := range options.GatesPublicKeys {
gates[i] = accessbox.NewGateData(gateKey, bearerTokens[i])
}
if options.SessionTkn { if options.SessionTkn {
sessionRules, err := buildContext(options.ContextRules) sessionRules, err := buildContext(options.ContextRules)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to build context for session token: %w", err) return nil, fmt.Errorf("failed to build context for session token: %w", err)
} }
return buildSessionToken(options.NeoFSKey, oid, sessionRules) oid, err := ownerIDFromNeoFSKey(&options.NeoFSKey.PublicKey)
if err != nil {
return nil, err
}
sessionTokens, err := buildSessionTokens(options.NeoFSKey, oid, sessionRules, options.GatesPublicKeys)
if err != nil {
return nil, err
}
for i, sessionToken := range sessionTokens {
gates[i].SessionToken = sessionToken
}
} }
return nil, nil
return gates, nil
} }
func ownerIDFromNeoFSKey(key *ecdsa.PublicKey) (*owner.ID, error) { func ownerIDFromNeoFSKey(key *ecdsa.PublicKey) (*owner.ID, error) {

View file

@ -24,12 +24,12 @@ type GateData struct {
AccessKey string AccessKey string
BearerToken *token.BearerToken BearerToken *token.BearerToken
SessionToken *session.Token SessionToken *session.Token
OwnerKey *ecdsa.PublicKey GateKey *ecdsa.PublicKey
} }
// NewGateData returns GateData from provided bearer token and public key. // NewGateData returns GateData from provided bearer token and public gate key.
func NewGateData(bearerTkn *token.BearerToken, ownerKey *ecdsa.PublicKey) *GateData { func NewGateData(gateKey *ecdsa.PublicKey, bearerTkn *token.BearerToken) *GateData {
return &GateData{BearerToken: bearerTkn, OwnerKey: ownerKey} return &GateData{GateKey: gateKey, BearerToken: bearerTkn}
} }
// Secrets represents AccessKey and key to encrypt gate tokens. // Secrets represents AccessKey and key to encrypt gate tokens.
@ -50,7 +50,7 @@ func (x *AccessBox) Unmarshal(data []byte) error {
// PackTokens adds a bearer and session tokens to BearerTokens and SessionToken lists respectively. // PackTokens adds a bearer and session tokens to BearerTokens and SessionToken lists respectively.
// Session token can be nil. // Session token can be nil.
func PackTokens(gatesData []*GateData, sess *session.Token) (*AccessBox, *Secrets, error) { func PackTokens(gatesData []*GateData) (*AccessBox, *Secrets, error) {
box := &AccessBox{} box := &AccessBox{}
ephemeralKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ephemeralKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
if err != nil { if err != nil {
@ -63,7 +63,7 @@ func PackTokens(gatesData []*GateData, sess *session.Token) (*AccessBox, *Secret
return nil, nil, fmt.Errorf("failed to generate accessKey as hex: %w", err) return nil, nil, fmt.Errorf("failed to generate accessKey as hex: %w", err)
} }
if err := box.addTokens(gatesData, ephemeralKey, sess, secret); err != nil { if err := box.addTokens(gatesData, ephemeralKey, secret); err != nil {
return nil, nil, fmt.Errorf("failed to add tokens to accessbox: %w", err) return nil, nil, fmt.Errorf("failed to add tokens to accessbox: %w", err)
} }
@ -89,14 +89,14 @@ func (x *AccessBox) GetTokens(owner *ecdsa.PrivateKey) (*GateData, error) {
return nil, fmt.Errorf("no gate data for key %x was found", ownerKey) return nil, fmt.Errorf("no gate data for key %x was found", ownerKey)
} }
func (x *AccessBox) addTokens(gatesData []*GateData, ephemeralKey *ecdsa.PrivateKey, sess *session.Token, secret []byte) error { func (x *AccessBox) addTokens(gatesData []*GateData, ephemeralKey *ecdsa.PrivateKey, secret []byte) error {
for i, gate := range gatesData { for i, gate := range gatesData {
encBearer, err := gate.BearerToken.Marshal() encBearer, err := gate.BearerToken.Marshal()
if err != nil { if err != nil {
return fmt.Errorf("%w, sender = %d", err, i) return fmt.Errorf("%w, sender = %d", err, i)
} }
var encSession []byte var encSession []byte
if sess != nil { if gate.SessionToken != nil {
encSession, err = gate.SessionToken.Marshal() encSession, err = gate.SessionToken.Marshal()
if err != nil { if err != nil {
return fmt.Errorf("%w, sender = %d", err, i) return fmt.Errorf("%w, sender = %d", err, i)
@ -108,7 +108,7 @@ func (x *AccessBox) addTokens(gatesData []*GateData, ephemeralKey *ecdsa.Private
tokens.BearerToken = encBearer tokens.BearerToken = encBearer
tokens.SessionToken = encSession tokens.SessionToken = encSession
boxGate, err := encodeGate(ephemeralKey, gate.OwnerKey, tokens) boxGate, err := encodeGate(ephemeralKey, gate.GateKey, tokens)
if err != nil { if err != nil {
return err return err
} }
@ -153,7 +153,7 @@ func decodeGate(gate *AccessBox_Gate, owner *ecdsa.PrivateKey, sender *ecdsa.Pub
return nil, err return nil, err
} }
gateData := NewGateData(bearerTkn, &owner.PublicKey) gateData := NewGateData(&owner.PublicKey, bearerTkn)
gateData.SessionToken = sessionTkn gateData.SessionToken = sessionTkn
gateData.AccessKey = hex.EncodeToString(tokens.AccessKey) gateData.AccessKey = hex.EncodeToString(tokens.AccessKey)
return gateData, nil return gateData, nil

View file

@ -6,8 +6,11 @@ import (
"crypto/rand" "crypto/rand"
"testing" "testing"
"github.com/google/uuid"
"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-api-go/pkg/token" "github.com/nspcc-dev/neofs-api-go/pkg/token"
crypto "github.com/nspcc-dev/neofs-crypto"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -56,8 +59,8 @@ func Test_bearer_token_in_access_box(t *testing.T) {
tkn.SetEACLTable(eacl.NewTable()) tkn.SetEACLTable(eacl.NewTable())
require.NoError(t, tkn.SignToken(sec)) require.NoError(t, tkn.SignToken(sec))
gate := NewGateData(tkn, &cred.PublicKey) gate := NewGateData(&cred.PublicKey, tkn)
box, _, err = PackTokens([]*GateData{gate}, nil) box, _, err = PackTokens([]*GateData{gate})
require.NoError(t, err) require.NoError(t, err)
data, err := box.Marshal() data, err := box.Marshal()
@ -72,6 +75,44 @@ func Test_bearer_token_in_access_box(t *testing.T) {
require.Equal(t, tkn, tkns.BearerToken) require.Equal(t, tkn, tkns.BearerToken)
} }
func Test_session_token_in_access_box(t *testing.T) {
var (
box *AccessBox
box2 AccessBox
tkn = session.NewToken()
)
sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)
cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)
tok := session.NewToken()
tok.SetContext(session.NewContainerContext())
uid, err := uuid.New().MarshalBinary()
require.NoError(t, err)
tok.SetID(uid)
tok.SetSessionKey(crypto.MarshalPublicKey(&sec.PublicKey))
require.NoError(t, tkn.Sign(sec))
gate := NewGateData(&cred.PublicKey, token.NewBearerToken())
gate.SessionToken = tkn
box, _, err = PackTokens([]*GateData{gate})
require.NoError(t, err)
data, err := box.Marshal()
require.NoError(t, err)
err = box2.Unmarshal(data)
require.NoError(t, err)
tkns, err := box2.GetTokens(cred)
require.NoError(t, err)
require.Equal(t, tkn, tkns.SessionToken)
}
func Test_accessbox_multiple_keys(t *testing.T) { func Test_accessbox_multiple_keys(t *testing.T) {
var ( var (
box *AccessBox box *AccessBox
@ -92,12 +133,12 @@ func Test_accessbox_multiple_keys(t *testing.T) {
cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err) require.NoError(t, err)
gates = append(gates, NewGateData(tkn, &cred.PublicKey)) gates = append(gates, NewGateData(&cred.PublicKey, tkn))
keys = append(keys, cred) keys = append(keys, cred)
} }
} }
box, _, err = PackTokens(gates, nil) box, _, err = PackTokens(gates)
require.NoError(t, err) require.NoError(t, err)
for i, k := range keys { for i, k := range keys {
@ -125,8 +166,8 @@ func Test_unknown_key(t *testing.T) {
tkn.SetEACLTable(eacl.NewTable()) tkn.SetEACLTable(eacl.NewTable())
require.NoError(t, tkn.SignToken(sec)) require.NoError(t, tkn.SignToken(sec))
gate := NewGateData(tkn, &cred.PublicKey) gate := NewGateData(&cred.PublicKey, tkn)
box, _, err = PackTokens([]*GateData{gate}, nil) box, _, err = PackTokens([]*GateData{gate})
require.NoError(t, err) require.NoError(t, err)
_, err = box.GetTokens(wrongCred) _, err = box.GetTokens(wrongCred)