forked from TrueCloudLab/frostfs-s3-gw
[#83] Added sessionKey to token
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
d1594b586e
commit
81408dcc1c
3 changed files with 112 additions and 43 deletions
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue