Skip to content

Commit

Permalink
Merge pull request #90 from KirillovDenis/feature/83-use_multiple_bea…
Browse files Browse the repository at this point in the history
…rer_tokens

[#83] Use multiple bearer tokens
  • Loading branch information
roman-khimov authored Jun 18, 2021
2 parents c89304d + d6bbc18 commit cba22aa
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 223 deletions.
12 changes: 3 additions & 9 deletions api/auth/center.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/nspcc-dev/neofs-api-go/pkg/object"
"github.com/nspcc-dev/neofs-api-go/pkg/token"
"github.com/nspcc-dev/neofs-s3-gw/authmate"
"github.com/nspcc-dev/neofs-s3-gw/creds/tokens"
"github.com/nspcc-dev/neofs-sdk-go/pkg/pool"
"go.uber.org/zap"
Expand Down Expand Up @@ -98,12 +97,7 @@ func (c *center) Authenticate(r *http.Request) (*token.BearerToken, error) {
return nil, fmt.Errorf("could not parse AccessBox address: %s : %w", accessKeyID, err)
}

tkn, err := c.cli.GetBearerToken(r.Context(), address)
if err != nil {
return nil, err
}

secret, err := authmate.BearerToAccessKey(tkn)
tkns, err := c.cli.GetTokens(r.Context(), address)
if err != nil {
return nil, err
}
Expand All @@ -119,7 +113,7 @@ func (c *center) Authenticate(r *http.Request) (*token.BearerToken, error) {
}
}

awsCreds := credentials.NewStaticCredentials(accessKeyID, secret, "")
awsCreds := credentials.NewStaticCredentials(accessKeyID, tkns.AccessKey, "")
signer := v4.NewSigner(awsCreds)
signer.DisableURIPathEscaping = true

Expand All @@ -133,5 +127,5 @@ func (c *center) Authenticate(r *http.Request) (*token.BearerToken, error) {
return nil, errors.New("failed to pass authentication procedure")
}

return tkn, nil
return tkns.BearerToken, nil
}
116 changes: 67 additions & 49 deletions authmate/authmate.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package authmate
import (
"context"
"crypto/ecdsa"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -141,34 +140,23 @@ 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)
}

bearerTkn, err := buildBearerToken(options.NeoFSKey, bearerRules, options.GatesPublicKeys[0])
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, ownerKey, err := accessbox.PackTokens(bearerTkn, sessionTkn, options.GatesPublicKeys...)
oid, err := ownerIDFromNeoFSKey(&options.NeoFSKey.PublicKey)
if err != nil {
return err
}

a.log.Info("store bearer token into NeoFS",
zap.Stringer("owner_tkn", bearerTkn.Issuer()))
zap.Stringer("owner_tkn", oid))

if !options.SessionTkn && len(options.ContextRules) > 0 {
_, err := w.Write([]byte("Warning: rules for session token were set but --create-session flag wasn't, " +
Expand All @@ -179,23 +167,18 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr
}

address, err := tokens.
New(a.pool, ownerKey).
New(a.pool, secrets.EphemeralKey).
Put(ctx, cid, oid, box, options.GatesPublicKeys...)
if err != nil {
return fmt.Errorf("failed to put bearer token: %w", err)
}

secret, err := BearerToAccessKey(bearerTkn)
if err != nil {
return fmt.Errorf("failed to get bearer token secret key: %w", err)
}

accessKeyID := address.ContainerID().String() + "_" + address.ObjectID().String()

ir := &issuingResult{
AccessKeyID: accessKeyID,
SecretAccessKey: secret,
OwnerPrivateKey: hex.EncodeToString(crypto.MarshalPrivateKey(ownerKey)),
SecretAccessKey: secrets.AccessKey,
OwnerPrivateKey: hex.EncodeToString(crypto.MarshalPrivateKey(secrets.EphemeralKey)),
}

enc := json.NewEncoder(w)
Expand All @@ -212,19 +195,14 @@ func (a *Agent) ObtainSecret(ctx context.Context, w io.Writer, options *ObtainSe
return fmt.Errorf("failed to parse secret address: %w", err)
}

tkn, err := bearerCreds.GetBearerToken(ctx, address)
if err != nil {
return fmt.Errorf("failed to get bearer token: %w", err)
}

secret, err := BearerToAccessKey(tkn)
tkns, err := bearerCreds.GetTokens(ctx, address)
if err != nil {
return fmt.Errorf("failed to get bearer token secret key: %w", err)
return fmt.Errorf("failed to get tokens: %w", err)
}

or := &obtainingResult{
BearerToken: tkn,
SecretAccessKey: secret,
BearerToken: tkns.BearerToken,
SecretAccessKey: tkns.AccessKey,
}

enc := json.NewEncoder(w)
Expand Down Expand Up @@ -302,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
}
Expand All @@ -316,7 +294,19 @@ func buildBearerToken(key *ecdsa.PrivateKey, table *eacl.Table, ownerKey *ecdsa.
return bearerToken, bearerToken.SignToken(key)
}

func buildSessionToken(key *ecdsa.PrivateKey, oid *owner.ID, ctx *session.ContainerContext) (*session.Token, error) {
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
}
bearerTokens = append(bearerTokens, tkn)
}
return bearerTokens, nil
}

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()
Expand All @@ -325,30 +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) {
if options.SessionTkn {
sessionRules, err := buildContext(options.ContextRules)
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, fmt.Errorf("failed to build context for session token: %w", err)
return nil, err
}
return buildSessionToken(options.NeoFSKey, oid, sessionRules)
sessionTokens = append(sessionTokens, tkn)
}
return nil, nil
return sessionTokens, nil
}

// BearerToAccessKey returns secret access key generated from given BearerToken.
func BearerToAccessKey(tkn *token.BearerToken) (string, error) {
data, err := tkn.Marshal()
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 "", err
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)
}
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
}
}

hash := sha256.Sum256(data)
return hex.EncodeToString(hash[:]), nil
return gates, nil
}

func ownerIDFromNeoFSKey(key *ecdsa.PublicKey) (*owner.ID, error) {
Expand Down
Loading

0 comments on commit cba22aa

Please sign in to comment.