[#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
}
oid, err := ownerIDFromNeoFSKey(&options.NeoFSKey.PublicKey)
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)
gatesData, err := createTokens(options, cid)
if err != nil {
return fmt.Errorf("failed to build bearer token: %w", err)
}
sessionTkn, err := createSessionToken(options, oid)
box, secrets, err := accessbox.PackTokens(gatesData)
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 {
return err
}
@ -291,8 +280,8 @@ func buildContext(rules []byte) (*session.ContainerContext, error) {
return sessionCtx, nil
}
func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, ownerKey *ecdsa.PublicKey) (*token.BearerToken, error) {
oid, err := ownerIDFromNeoFSKey(ownerKey)
func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, gateKey *ecdsa.PublicKey) (*token.BearerToken, error) {
oid, err := ownerIDFromNeoFSKey(gateKey)
if err != nil {
return nil, err
}
@ -305,19 +294,19 @@ func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, ownerKey *ecdsa.
return bearerToken, bearerToken.SignToken(key)
}
func buildBearerTokens(key *ecdsa.PrivateKey, table *eacl.Table, ownerKeys []*ecdsa.PublicKey) ([]*accessbox.GateData, error) {
gatesData := make([]*accessbox.GateData, 0, len(ownerKeys))
for _, ownerKey := range ownerKeys {
tkn, err := buildBearerToken(key, table, ownerKey)
func buildBearerTokens(key *ecdsa.PrivateKey, table *eacl.Table, gatesKeys []*ecdsa.PublicKey) ([]*token.BearerToken, error) {
bearerTokens := make([]*token.BearerToken, 0, len(gatesKeys))
for _, gateKey := range gatesKeys {
tkn, err := buildBearerToken(key, table, gateKey)
if err != nil {
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.SetContext(ctx)
uid, err := uuid.New().MarshalBinary()
@ -326,19 +315,58 @@ func buildSessionToken(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.Contai
}
tok.SetID(uid)
tok.SetOwnerID(oid)
tok.SetSessionKey(crypto.MarshalPublicKey(gateKey))
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 {
sessionRules, err := buildContext(options.ContextRules)
if err != nil {
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) {

View file

@ -24,12 +24,12 @@ type GateData struct {
AccessKey string
BearerToken *token.BearerToken
SessionToken *session.Token
OwnerKey *ecdsa.PublicKey
GateKey *ecdsa.PublicKey
}
// NewGateData returns GateData from provided bearer token and public key.
func NewGateData(bearerTkn *token.BearerToken, ownerKey *ecdsa.PublicKey) *GateData {
return &GateData{BearerToken: bearerTkn, OwnerKey: ownerKey}
// NewGateData returns GateData from provided bearer token and public gate key.
func NewGateData(gateKey *ecdsa.PublicKey, bearerTkn *token.BearerToken) *GateData {
return &GateData{GateKey: gateKey, BearerToken: bearerTkn}
}
// 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.
// Session token can be nil.
func PackTokens(gatesData []*GateData, sess *session.Token) (*AccessBox, *Secrets, error) {
func PackTokens(gatesData []*GateData) (*AccessBox, *Secrets, error) {
box := &AccessBox{}
ephemeralKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
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)
}
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)
}
@ -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)
}
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 {
encBearer, err := gate.BearerToken.Marshal()
if err != nil {
return fmt.Errorf("%w, sender = %d", err, i)
}
var encSession []byte
if sess != nil {
if gate.SessionToken != nil {
encSession, err = gate.SessionToken.Marshal()
if err != nil {
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.SessionToken = encSession
boxGate, err := encodeGate(ephemeralKey, gate.OwnerKey, tokens)
boxGate, err := encodeGate(ephemeralKey, gate.GateKey, tokens)
if err != nil {
return err
}
@ -153,7 +153,7 @@ func decodeGate(gate *AccessBox_Gate, owner *ecdsa.PrivateKey, sender *ecdsa.Pub
return nil, err
}
gateData := NewGateData(bearerTkn, &owner.PublicKey)
gateData := NewGateData(&owner.PublicKey, bearerTkn)
gateData.SessionToken = sessionTkn
gateData.AccessKey = hex.EncodeToString(tokens.AccessKey)
return gateData, nil

View file

@ -6,8 +6,11 @@ import (
"crypto/rand"
"testing"
"github.com/google/uuid"
"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"
crypto "github.com/nspcc-dev/neofs-crypto"
"github.com/stretchr/testify/require"
)
@ -56,8 +59,8 @@ func Test_bearer_token_in_access_box(t *testing.T) {
tkn.SetEACLTable(eacl.NewTable())
require.NoError(t, tkn.SignToken(sec))
gate := NewGateData(tkn, &cred.PublicKey)
box, _, err = PackTokens([]*GateData{gate}, nil)
gate := NewGateData(&cred.PublicKey, tkn)
box, _, err = PackTokens([]*GateData{gate})
require.NoError(t, err)
data, err := box.Marshal()
@ -72,6 +75,44 @@ func Test_bearer_token_in_access_box(t *testing.T) {
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) {
var (
box *AccessBox
@ -92,12 +133,12 @@ func Test_accessbox_multiple_keys(t *testing.T) {
cred, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
require.NoError(t, err)
gates = append(gates, NewGateData(tkn, &cred.PublicKey))
gates = append(gates, NewGateData(&cred.PublicKey, tkn))
keys = append(keys, cred)
}
}
box, _, err = PackTokens(gates, nil)
box, _, err = PackTokens(gates)
require.NoError(t, err)
for i, k := range keys {
@ -125,8 +166,8 @@ func Test_unknown_key(t *testing.T) {
tkn.SetEACLTable(eacl.NewTable())
require.NoError(t, tkn.SignToken(sec))
gate := NewGateData(tkn, &cred.PublicKey)
box, _, err = PackTokens([]*GateData{gate}, nil)
gate := NewGateData(&cred.PublicKey, tkn)
box, _, err = PackTokens([]*GateData{gate})
require.NoError(t, err)
_, err = box.GetTokens(wrongCred)