From fe2d507121fe56f70c2f0b680920e41946d2134a Mon Sep 17 00:00:00 2001 From: Angira Kekteeva Date: Mon, 14 Jun 2021 16:39:25 +0300 Subject: [PATCH] [#48] creds,authmate:Replace old accessbox by new Removed encoder, decoder wraps. Made changes in api, authmate and creds via new accessbox. Updated bearer_token_tests via new accessbox. Signed-off-by: Angira Kekteeva --- api/auth/center.go | 8 +- authmate/authmate.go | 18 ++- creds/accessbox/accessbox.go | 205 +++++++++++++++++++++--- creds/accessbox/bearer_token.go | 43 ----- creds/accessbox/bearer_token_test.go | 176 +++++++++----------- creds/accessbox/decoder.go | 88 ---------- creds/accessbox/encoder.go | 85 ---------- creds/hcs/public.go | 9 +- creds/{bearer => tokens}/credentials.go | 68 +++++--- 9 files changed, 324 insertions(+), 376 deletions(-) delete mode 100644 creds/accessbox/bearer_token.go delete mode 100644 creds/accessbox/decoder.go delete mode 100644 creds/accessbox/encoder.go rename creds/{bearer => tokens}/credentials.go (64%) diff --git a/api/auth/center.go b/api/auth/center.go index 565f11f..eda6481 100644 --- a/api/auth/center.go +++ b/api/auth/center.go @@ -15,8 +15,8 @@ import ( "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/bearer" "github.com/nspcc-dev/neofs-s3-gw/creds/hcs" + "github.com/nspcc-dev/neofs-s3-gw/creds/tokens" "github.com/nspcc-dev/neofs-sdk-go/pkg/pool" "go.uber.org/zap" ) @@ -31,7 +31,7 @@ type ( center struct { reg *regexpSubmatcher - cli bearer.Credentials + cli tokens.Credentials } // Params stores node connection parameters. @@ -57,7 +57,7 @@ var _ io.ReadSeeker = prs(0) // New creates an instance of AuthCenter. func New(conns pool.Pool, key hcs.PrivateKey) Center { return ¢er{ - cli: bearer.New(conns, key), + cli: tokens.New(conns, key), reg: ®expSubmatcher{re: authorizationFieldRegexp}, } } @@ -96,7 +96,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.Get(r.Context(), address) + tkn, err := c.cli.GetBearerToken(r.Context(), address) if err != nil { return nil, err } diff --git a/authmate/authmate.go b/authmate/authmate.go index b994c3f..dd90c31 100644 --- a/authmate/authmate.go +++ b/authmate/authmate.go @@ -20,8 +20,9 @@ import ( "github.com/nspcc-dev/neofs-api-go/pkg/owner" "github.com/nspcc-dev/neofs-api-go/pkg/token" "github.com/nspcc-dev/neofs-node/pkg/policy" - "github.com/nspcc-dev/neofs-s3-gw/creds/bearer" + "github.com/nspcc-dev/neofs-s3-gw/creds/accessbox" "github.com/nspcc-dev/neofs-s3-gw/creds/hcs" + "github.com/nspcc-dev/neofs-s3-gw/creds/tokens" "github.com/nspcc-dev/neofs-sdk-go/pkg/pool" "go.uber.org/zap" ) @@ -129,6 +130,7 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr var ( err error cid *cid.ID + box accessbox.AccessBox ) a.log.Info("check container", zap.Stringer("cid", options.ContainerID)) @@ -148,12 +150,18 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr return fmt.Errorf("failed to build bearer token: %w", err) } + box.SetOwnerPublicKey(options.OwnerPrivateKey.PublicKey()) + err = box.AddBearerToken(tkn, options.OwnerPrivateKey, options.GatesPublicKeys...) + if err != nil { + return fmt.Errorf("failed to add token to accessbox: %w", err) + } + a.log.Info("store bearer token into NeoFS", zap.Stringer("owner_tkn", tkn.Issuer())) - address, err := bearer. + address, err := tokens. New(a.pool, options.OwnerPrivateKey). - Put(ctx, cid, tkn, options.GatesPublicKeys...) + Put(ctx, cid, tkn.Issuer(), &box, options.GatesPublicKeys...) if err != nil { return fmt.Errorf("failed to put bearer token: %w", err) } @@ -179,13 +187,13 @@ func (a *Agent) IssueSecret(ctx context.Context, w io.Writer, options *IssueSecr // ObtainSecret receives an existing secret access key from NeoFS and // writes to io.Writer the secret access key. func (a *Agent) ObtainSecret(ctx context.Context, w io.Writer, options *ObtainSecretOptions) error { - bearerCreds := bearer.New(a.pool, options.GatePrivateKey) + bearerCreds := tokens.New(a.pool, options.GatePrivateKey) address := object.NewAddress() if err := address.Parse(options.SecretAddress); err != nil { return fmt.Errorf("failed to parse secret address: %w", err) } - tkn, err := bearerCreds.Get(ctx, address) + tkn, err := bearerCreds.GetBearerToken(ctx, address) if err != nil { return fmt.Errorf("failed to get bearer token: %w", err) } diff --git a/creds/accessbox/accessbox.go b/creds/accessbox/accessbox.go index 66bcd36..0fc2b7d 100644 --- a/creds/accessbox/accessbox.go +++ b/creds/accessbox/accessbox.go @@ -1,29 +1,184 @@ package accessbox -import "github.com/nspcc-dev/neofs-api-go/pkg/token" +import ( + "bytes" + "crypto/rand" + "fmt" -type ( - // Box provides marshalling/unmarshalling for the token. - Box interface { - Marshal() ([]byte, error) - Unmarshal([]byte) error - } - - // Encoder provides encoding method. - Encoder interface { - Encode(Box) error - } - - // Decoder provides decoding method. - Decoder interface { - Decode(Box) error - } - - // BearerTokenBox is a marshalling/unmarshalling bearer token wrapper. - BearerTokenBox interface { - Box - - Token() *token.BearerToken - SetToken(*token.BearerToken) - } + "github.com/nspcc-dev/neofs-api-go/pkg/session" + "github.com/nspcc-dev/neofs-api-go/pkg/token" + "github.com/nspcc-dev/neofs-s3-gw/creds/hcs" + "golang.org/x/crypto/chacha20poly1305" + "golang.org/x/crypto/curve25519" + "google.golang.org/protobuf/proto" ) + +type tokenInterface interface { + Marshal(bs ...[]byte) ([]byte, error) + Unmarshal([]byte) error +} + +// Marshal returns the wire-format of AccessBox. +func (x *AccessBox) Marshal() ([]byte, error) { + return proto.Marshal(x) +} + +// Unmarshal parses the wire-format message and put data to x. +func (x *AccessBox) Unmarshal(data []byte) error { + return proto.Unmarshal(data, x) +} + +// AddBearerToken adds a bearer token to BearerTokens list. +func (x *AccessBox) AddBearerToken(tkn *token.BearerToken, owner hcs.PrivateKey, keys ...hcs.PublicKey) error { + if x.OwnerPublicKey == nil { + return fmt.Errorf("owner's public key is nil") + } + // restriction to rewrite token for the second time + if len(x.BearerTokens) > 0 { + return fmt.Errorf("bearer token is already set") + } + return x.addToken(tkn, &x.BearerTokens, owner, keys...) +} + +// AddSessionToken adds a session token to SessionTokens list. +func (x *AccessBox) AddSessionToken(tkn *session.Token, owner hcs.PrivateKey, keys ...hcs.PublicKey) error { + if x.OwnerPublicKey == nil { + return fmt.Errorf("owner's public key is nil") + } + //restriction to rewrite token for the second time + if len(x.SessionTokens) > 0 { + return fmt.Errorf("bearer token is already set") + } + return x.addToken(tkn, &x.SessionTokens, owner, keys...) +} + +// SetOwnerPublicKey sets a public key of an issuer. +func (x *AccessBox) SetOwnerPublicKey(key hcs.PublicKey) { + x.OwnerPublicKey = key.Bytes() +} + +// GetBearerToken returns bearer token from AccessBox. +func (x *AccessBox) GetBearerToken(owner hcs.PrivateKey) (*token.BearerToken, error) { + sender, err := hcs.PublicKeyFromBytes(x.OwnerPublicKey) + if err != nil { + return nil, fmt.Errorf("failed to load owner public key from AccessBox: %w", err) + } + for _, data := range x.BearerTokens { + if !bytes.Equal(data.GatePublicKey, owner.PublicKey().Bytes()) { + continue + } + tkn := token.NewBearerToken() + if err := decodeToken(data.Token, tkn, owner, sender); err != nil { + return nil, fmt.Errorf("failed to decode bearer token: %w", err) + } + return tkn, nil + } + + return nil, fmt.Errorf("no bearer token for key %s was found", owner.String()) +} + +// GetSessionToken returns session token from AccessBox. +func (x *AccessBox) GetSessionToken(owner hcs.PrivateKey) (*session.Token, error) { + sender, err := hcs.PublicKeyFromBytes(x.OwnerPublicKey) + if err != nil { + return nil, fmt.Errorf("failed to load owner public key from AccessBox: %w", err) + } + for _, data := range x.SessionTokens { + if !bytes.Equal(data.GatePublicKey, owner.PublicKey().Bytes()) { + continue + } + tkn := session.NewToken() + + if err := decodeToken(data.Token, tkn, owner, sender); err != nil { + return nil, fmt.Errorf("failed to decode session token: %w", err) + } + return tkn, nil + } + + return nil, fmt.Errorf("no session token for key %s was found", owner.String()) +} + +func (x *AccessBox) addToken(tkn tokenInterface, list *[]*AccessBox_Token, owner hcs.PrivateKey, keys ...hcs.PublicKey) error { + for i, sender := range keys { + data, err := encodeToken(tkn, owner, sender) + if err != nil { + return fmt.Errorf("%w, sender = %d", err, i) + } + *list = append(*list, newToken(data, sender.Bytes())) + } + return nil +} + +func newToken(data []byte, key []byte) *AccessBox_Token { + res := new(AccessBox_Token) + res.Token = data + res.GatePublicKey = key + return res +} + +func encodeToken(tkn tokenInterface, owner hcs.PrivateKey, sender hcs.PublicKey) ([]byte, error) { + data, err := tkn.Marshal() + if err != nil { + return nil, err + } + + encrypted, err := encrypt(owner, sender, data) + if err != nil { + return nil, err + } + return encrypted, nil +} + +func decodeToken(data []byte, tkn tokenInterface, owner hcs.PrivateKey, sender hcs.PublicKey) error { + decoded, err := decrypt(owner, sender, data) + if err != nil { + return err + } + + err = tkn.Unmarshal(decoded) + if err != nil { + return err + } + + return nil +} + +func encrypt(owner hcs.PrivateKey, sender hcs.PublicKey, data []byte) ([]byte, error) { + key, err := curve25519.X25519(owner.Bytes(), sender.Bytes()) + if err != nil { + return nil, err + } + + enc, err := chacha20poly1305.NewX(key) + if err != nil { + return nil, err + } + + nonce := make([]byte, enc.NonceSize(), enc.NonceSize()+len(data)+enc.Overhead()) + if _, err := rand.Read(nonce); err != nil { + return nil, err + } + + return enc.Seal(nonce, nonce, data, nil), nil +} + +func decrypt(owner hcs.PrivateKey, sender hcs.PublicKey, data []byte) ([]byte, error) { + sb := sender.Bytes() + + key, err := curve25519.X25519(owner.Bytes(), sb) + if err != nil { + return nil, err + } + + dec, err := chacha20poly1305.NewX(key) + if err != nil { + return nil, err + } + + if ld, ns := len(data), dec.NonceSize(); ld < ns { + return nil, fmt.Errorf("wrong data size (%d), should be greater than %d", ld, ns) + } + + nonce, cypher := data[:dec.NonceSize()], data[dec.NonceSize():] + return dec.Open(nil, nonce, cypher, nil) +} diff --git a/creds/accessbox/bearer_token.go b/creds/accessbox/bearer_token.go deleted file mode 100644 index 8551a52..0000000 --- a/creds/accessbox/bearer_token.go +++ /dev/null @@ -1,43 +0,0 @@ -package accessbox - -import ( - "github.com/nspcc-dev/neofs-api-go/pkg/token" -) - -type bearerBox struct { - tkn *token.BearerToken -} - -// NewBearerBox wraps given bearer token into BearerTokenBox. -func NewBearerBox(token *token.BearerToken) BearerTokenBox { - return &bearerBox{tkn: token} -} - -// Marshal serializes bearer token. -func (b *bearerBox) Marshal() ([]byte, error) { - return b.tkn.Marshal(nil) -} - -// Marshal initializes bearer box from its serialized representation. -func (b *bearerBox) Unmarshal(data []byte) error { - tkn := token.NewBearerToken() - - err := tkn.Unmarshal(data) - if err != nil { - return err - } - - b.SetToken(tkn) - - return nil -} - -// Token unwraps bearer token from the box. -func (b *bearerBox) Token() *token.BearerToken { - return b.tkn -} - -// SetToken sets new token in the box. -func (b *bearerBox) SetToken(tkn *token.BearerToken) { - b.tkn = tkn -} diff --git a/creds/accessbox/bearer_token_test.go b/creds/accessbox/bearer_token_test.go index bcaba33..51f30b8 100644 --- a/creds/accessbox/bearer_token_test.go +++ b/creds/accessbox/bearer_token_test.go @@ -1,12 +1,9 @@ package accessbox import ( - "bytes" "crypto/ecdsa" "crypto/elliptic" "crypto/rand" - "encoding/binary" - "strconv" "testing" "github.com/nspcc-dev/neofs-api-go/pkg/acl/eacl" @@ -15,9 +12,34 @@ import ( "github.com/stretchr/testify/require" ) -func Test_encrypt_decrypt(t *testing.T) { - tkn := token.NewBearerToken() - box := NewBearerBox(tkn) +func Test_tokens_encode_decode(t *testing.T) { + var ( + tkn = token.NewBearerToken() + tkn2 = token.NewBearerToken() + ) + sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + + cred, err := hcs.Generate(rand.Reader) + require.NoError(t, err) + + tkn.SetEACLTable(eacl.NewTable()) + require.NoError(t, tkn.SignToken(sec)) + + data, err := encodeToken(tkn, cred.PrivateKey(), cred.PublicKey()) + require.NoError(t, err) + + err = decodeToken(data, tkn2, cred.PrivateKey(), cred.PublicKey()) + require.NoError(t, err) + + require.Equal(t, tkn, tkn2) +} + +func Test_bearer_token_in_access_box(t *testing.T) { + var ( + box, box2 AccessBox + tkn = token.NewBearerToken() + ) sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) require.NoError(t, err) @@ -28,21 +50,28 @@ func Test_encrypt_decrypt(t *testing.T) { tkn.SetEACLTable(eacl.NewTable()) require.NoError(t, tkn.SignToken(sec)) + box.SetOwnerPublicKey(cred.PublicKey()) + + err = box.AddBearerToken(tkn, cred.PrivateKey(), cred.PublicKey()) + require.NoError(t, err) + data, err := box.Marshal() require.NoError(t, err) - encrypted, err := encrypt(cred.PrivateKey(), cred.PublicKey(), data) + err = box2.Unmarshal(data) require.NoError(t, err) - decrypted, err := decrypt(cred.PrivateKey(), cred.PublicKey(), encrypted) + tkn2, err := box2.GetBearerToken(cred.PrivateKey()) require.NoError(t, err) - require.Equal(t, data, decrypted) + require.Equal(t, tkn, tkn2) } -func Test_encrypt_decrypt_step_by_step(t *testing.T) { - tkn := token.NewBearerToken() - box := NewBearerBox(tkn) +func Test_accessbox_multiple_keys(t *testing.T) { + var ( + box AccessBox + tkn = token.NewBearerToken() + ) sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) require.NoError(t, err) @@ -53,75 +82,6 @@ func Test_encrypt_decrypt_step_by_step(t *testing.T) { tkn.SetEACLTable(eacl.NewTable()) require.NoError(t, tkn.SignToken(sec)) - data, err := box.Marshal() - require.NoError(t, err) - - buf := new(bytes.Buffer) - _, err = cred.PublicKey().WriteTo(buf) - require.NoError(t, err) - - encrypted, err := encrypt(cred.PrivateKey(), cred.PublicKey(), data) - require.NoError(t, err) - - length := len(encrypted) - temp := make([]byte, length+binary.MaxVarintLen64) - size := binary.PutVarint(temp, int64(length)) - copy(temp[size:], encrypted) - buf.Write(temp[:length+size]) - - sender, err := hcs.NewPublicKeyFromReader(buf) - require.NoError(t, err) - - require.Equal(t, cred.PublicKey(), sender) - - ln, err := binary.ReadVarint(buf) - require.NoError(t, err) - require.Equal(t, int64(length), ln) - - enc := make([]byte, ln) - n, err := buf.Read(enc) - require.NoError(t, err) - require.Equal(t, length, n) - require.Equal(t, encrypted, enc) - - decrypted, err := decrypt(cred.PrivateKey(), sender, enc) - require.NoError(t, err) - require.Equal(t, data, decrypted) -} - -func TestSingleKey_AccessBox(t *testing.T) { - tkn := token.NewBearerToken() - expect := NewBearerBox(tkn) - actual := NewBearerBox(nil) - - sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - require.NoError(t, err) - - cred, err := hcs.Generate(rand.Reader) - require.NoError(t, err) - - tkn.SetEACLTable(eacl.NewTable()) - require.NoError(t, tkn.SignToken(sec)) - - data, err := Encode(expect, cred.PrivateKey(), cred.PublicKey()) - require.NoError(t, err) - - require.NoError(t, Decode(data, actual, cred.PrivateKey())) - require.Equal(t, expect, actual) -} - -func TestBearerToken_AccessBox(t *testing.T) { - tkn := token.NewBearerToken() - box := NewBearerBox(tkn) - sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) - require.NoError(t, err) - - cred, err := hcs.Generate(rand.Reader) - require.NoError(t, err) - - tkn.SetEACLTable(eacl.NewTable()) - require.NoError(t, tkn.SignToken(sec)) - count := 10 pubs := make([]hcs.PublicKey, 0, count) keys := make([]hcs.PrivateKey, 0, count) @@ -135,27 +95,41 @@ func TestBearerToken_AccessBox(t *testing.T) { } } - buf := new(bytes.Buffer) - require.NoError(t, NewEncoder(buf, cred.PrivateKey(), pubs...).Encode(box)) + box.SetOwnerPublicKey(cred.PublicKey()) - data := buf.Bytes() + err = box.AddBearerToken(tkn, cred.PrivateKey(), pubs...) + require.NoError(t, err) - for i := range keys { - key := keys[i] - t.Run("try with key "+strconv.Itoa(i), func(t *testing.T) { - r := bytes.NewReader(data) - nbx := NewBearerBox(nil) - require.NoError(t, NewDecoder(r, key).Decode(nbx)) - require.Equal(t, tkn, nbx.Token()) - }) + for i, k := range keys { + tkn2, err := box.GetBearerToken(k) + require.NoError(t, err, "key #%d: %s failed", i, k) + require.Equal(t, tkn2, tkn) } - - t.Run("should fail for unknown key", func(t *testing.T) { - cred, err = hcs.Generate(rand.Reader) - require.NoError(t, err) - - r := bytes.NewReader(data) - nbx := NewBearerBox(nil) - require.EqualError(t, NewDecoder(r, cred.PrivateKey()).Decode(nbx), "chacha20poly1305: message authentication failed") - }) +} + +func Test_unknown_key(t *testing.T) { + var ( + box AccessBox + tkn = token.NewBearerToken() + ) + + sec, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) + require.NoError(t, err) + + cred, err := hcs.Generate(rand.Reader) + require.NoError(t, err) + + wrongCred, err := hcs.Generate(rand.Reader) + require.NoError(t, err) + + tkn.SetEACLTable(eacl.NewTable()) + require.NoError(t, tkn.SignToken(sec)) + + box.SetOwnerPublicKey(cred.PublicKey()) + + err = box.AddBearerToken(tkn, cred.PrivateKey(), cred.PublicKey()) + require.NoError(t, err) + + _, err = box.GetBearerToken(wrongCred.PrivateKey()) + require.Error(t, err) } diff --git a/creds/accessbox/decoder.go b/creds/accessbox/decoder.go deleted file mode 100644 index 059a297..0000000 --- a/creds/accessbox/decoder.go +++ /dev/null @@ -1,88 +0,0 @@ -package accessbox - -import ( - "bufio" - "bytes" - "encoding/binary" - "fmt" - "io" - - "github.com/nspcc-dev/neofs-s3-gw/creds/hcs" - "golang.org/x/crypto/chacha20poly1305" - "golang.org/x/crypto/curve25519" -) - -type decoder struct { - *bufio.Reader - - key hcs.PrivateKey -} - -// NewDecoder returns new private key decoder. -func NewDecoder(r io.Reader, key hcs.PrivateKey) Decoder { - return &decoder{Reader: bufio.NewReader(r), key: key} -} - -func decrypt(owner hcs.PrivateKey, sender hcs.PublicKey, data []byte) ([]byte, error) { - sb := sender.Bytes() - - key, err := curve25519.X25519(owner.Bytes(), sb) - if err != nil { - return nil, err - } - - dec, err := chacha20poly1305.NewX(key) - if err != nil { - return nil, err - } - - if ld, ns := len(data), dec.NonceSize(); ld < ns { - return nil, fmt.Errorf("wrong data size (%d), should be greater than %d", ld, ns) - } - - nonce, cypher := data[:dec.NonceSize()], data[dec.NonceSize():] - return dec.Open(nil, nonce, cypher, nil) -} - -func (d *decoder) Decode(box Box) error { - sender, err := hcs.NewPublicKeyFromReader(d) - if err != nil { - return err - } - - var lastErr error - - for { - size, err := binary.ReadVarint(d) - if err == io.EOF { - break - } else if err != nil { - return err - } - - data := make([]byte, size) - - if ln, err := d.Read(data); err != nil { - lastErr = err - continue - } else if ln != int(size) { - lastErr = fmt.Errorf("expect %d bytes, but read only %d bytes", size, ln) - continue - } else if decoded, err := decrypt(d.key, sender, data); err != nil { - lastErr = err - continue - } else if err = box.Unmarshal(decoded); err != nil { - lastErr = err - continue - } - - return nil - } - - return lastErr -} - -// Decode unwraps serialized bearer token from data into box using owner key. -func Decode(data []byte, box Box, owner hcs.PrivateKey) error { - return NewDecoder(bytes.NewBuffer(data), owner).Decode(box) -} diff --git a/creds/accessbox/encoder.go b/creds/accessbox/encoder.go deleted file mode 100644 index d46b875..0000000 --- a/creds/accessbox/encoder.go +++ /dev/null @@ -1,85 +0,0 @@ -package accessbox - -import ( - "bytes" - "crypto/rand" - "encoding/binary" - "fmt" - "io" - - "github.com/nspcc-dev/neofs-s3-gw/creds/hcs" - "golang.org/x/crypto/chacha20poly1305" - "golang.org/x/crypto/curve25519" -) - -type encoder struct { - io.Writer - - owner hcs.PrivateKey - keys []hcs.PublicKey -} - -// NewEncoder creates encoder. -func NewEncoder(w io.Writer, owner hcs.PrivateKey, keys ...hcs.PublicKey) Encoder { - return &encoder{ - Writer: w, - owner: owner, - keys: keys, - } -} - -func encrypt(owner hcs.PrivateKey, sender hcs.PublicKey, data []byte) ([]byte, error) { - key, err := curve25519.X25519(owner.Bytes(), sender.Bytes()) - if err != nil { - return nil, err - } - - enc, err := chacha20poly1305.NewX(key) - if err != nil { - return nil, err - } - - nonce := make([]byte, enc.NonceSize(), enc.NonceSize()+len(data)+enc.Overhead()) - if _, err := rand.Read(nonce); err != nil { - return nil, err - } - - return enc.Seal(nonce, nonce, data, nil), nil -} - -// Encode and encrypt box through owner private key and public keys. -func (e *encoder) Encode(box Box) error { - data, err := box.Marshal() - if err != nil { - return err - } - - // write owner public key - if _, err = e.owner.PublicKey().WriteTo(e); err != nil { - return err - } - - for i, sender := range e.keys { - encrypted, err := encrypt(e.owner, sender, data) - if err != nil { - return fmt.Errorf("%w, sender = %d", err, i) - } - - ln := len(encrypted) - temp := make([]byte, ln+binary.MaxVarintLen64) - size := binary.PutVarint(temp, int64(ln)) - copy(temp[size:], encrypted) - if _, err := e.Write(temp[:size+ln]); err != nil { - return fmt.Errorf("%w, sender = %d", err, i) - } - } - - return nil -} - -// Encode and encrypt box through owner private key and public keys. -func Encode(box Box, owner hcs.PrivateKey, keys ...hcs.PublicKey) ([]byte, error) { - buf := new(bytes.Buffer) - err := NewEncoder(buf, owner, keys...).Encode(box) - return buf.Bytes(), err -} diff --git a/creds/hcs/public.go b/creds/hcs/public.go index 9a72551..2ef2c4f 100644 --- a/creds/hcs/public.go +++ b/creds/hcs/public.go @@ -26,7 +26,8 @@ func (p *public) WriteTo(w io.Writer) (int64, error) { return int64(pl), err } -func publicKeyFromBytes(v []byte) (PublicKey, error) { +// PublicKeyFromBytes reads a public key from given bytes. +func PublicKeyFromBytes(v []byte) (PublicKey, error) { pub := public(v) return &pub, nil } @@ -37,7 +38,7 @@ func publicKeyFromString(val string) (PublicKey, error) { return nil, err } - return publicKeyFromBytes(v) + return PublicKeyFromBytes(v) } // NewPublicKeyFromReader reads new public key from given reader. @@ -47,7 +48,7 @@ func NewPublicKeyFromReader(r io.Reader) (PublicKey, error) { return nil, err } - return publicKeyFromBytes(data) + return PublicKeyFromBytes(data) } // LoadPublicKey loads public key from given file or (serialized) string. @@ -61,5 +62,5 @@ func LoadPublicKey(val string) (PublicKey, error) { return nil, err } - return publicKeyFromBytes(data) + return PublicKeyFromBytes(data) } diff --git a/creds/bearer/credentials.go b/creds/tokens/credentials.go similarity index 64% rename from creds/bearer/credentials.go rename to creds/tokens/credentials.go index ffaf550..2d39667 100644 --- a/creds/bearer/credentials.go +++ b/creds/tokens/credentials.go @@ -1,4 +1,4 @@ -package bearer +package tokens import ( "bytes" @@ -11,6 +11,8 @@ import ( "github.com/nspcc-dev/neofs-api-go/pkg/client" cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id" "github.com/nspcc-dev/neofs-api-go/pkg/object" + "github.com/nspcc-dev/neofs-api-go/pkg/owner" + "github.com/nspcc-dev/neofs-api-go/pkg/session" "github.com/nspcc-dev/neofs-api-go/pkg/token" "github.com/nspcc-dev/neofs-s3-gw/creds/accessbox" "github.com/nspcc-dev/neofs-s3-gw/creds/hcs" @@ -20,8 +22,9 @@ import ( type ( // Credentials is a bearer token get/put interface. Credentials interface { - Get(context.Context, *object.Address) (*token.BearerToken, error) - Put(context.Context, *cid.ID, *token.BearerToken, ...hcs.PublicKey) (*object.Address, error) + GetBearerToken(context.Context, *object.Address) (*token.BearerToken, error) + GetSessionToken(context.Context, *object.Address) (*session.Token, error) + Put(context.Context, *cid.ID, *owner.ID, *accessbox.AccessBox, ...hcs.PublicKey) (*object.Address, error) } cred struct { @@ -59,11 +62,39 @@ func (c *cred) releaseBuffer(buf *bytes.Buffer) { bufferPool.Put(buf) } -func (c *cred) Get(ctx context.Context, address *object.Address) (*token.BearerToken, error) { - buf := c.acquireBuffer() - defer c.releaseBuffer(buf) +func (c *cred) GetBearerToken(ctx context.Context, address *object.Address) (*token.BearerToken, error) { + box, err := c.getAccessBox(ctx, address) + if err != nil { + return nil, err + } - box := accessbox.NewBearerBox(nil) + tkn, err := box.GetBearerToken(c.key) + if err != nil { + return nil, err + } + return tkn, nil +} + +func (c *cred) GetSessionToken(ctx context.Context, address *object.Address) (*session.Token, error) { + box, err := c.getAccessBox(ctx, address) + if err != nil { + return nil, err + } + + tkn, err := box.GetSessionToken(c.key) + if err != nil { + return nil, err + } + + return tkn, nil +} + +func (c *cred) getAccessBox(ctx context.Context, address *object.Address) (*accessbox.AccessBox, error) { + var ( + box accessbox.AccessBox + buf = c.acquireBuffer() + ) + defer c.releaseBuffer(buf) conn, tok, err := c.pool.Connection() if err != nil { @@ -80,30 +111,25 @@ func (c *cred) Get(ctx context.Context, address *object.Address) (*token.BearerT return nil, err } - err = accessbox.NewDecoder(buf, c.key).Decode(box) - if err != nil { + if err = box.Unmarshal(buf.Bytes()); err != nil { return nil, err } - - return box.Token(), nil + return &box, nil } -func (c *cred) Put(ctx context.Context, cid *cid.ID, tkn *token.BearerToken, keys ...hcs.PublicKey) (*object.Address, error) { +func (c *cred) Put(ctx context.Context, cid *cid.ID, issuer *owner.ID, box *accessbox.AccessBox, keys ...hcs.PublicKey) (*object.Address, error) { var ( err error - buf = c.acquireBuffer() - box = accessbox.NewBearerBox(tkn) - created = strconv.FormatInt(time.Now().Unix(), 10) ) - defer c.releaseBuffer(buf) - if len(keys) == 0 { return nil, ErrEmptyPublicKeys - } else if tkn == nil { + } else if box == nil { return nil, ErrEmptyBearerToken - } else if err = accessbox.NewEncoder(buf, c.key, keys...).Encode(box); err != nil { + } + data, err := box.Marshal() + if err != nil { return nil, err } @@ -121,10 +147,10 @@ func (c *cred) Put(ctx context.Context, cid *cid.ID, tkn *token.BearerToken, key raw := object.NewRaw() raw.SetContainerID(cid) - raw.SetOwnerID(tkn.Issuer()) + raw.SetOwnerID(issuer) raw.SetAttributes(filename, timestamp) - ops := new(client.PutObjectParams).WithObject(raw.Object()).WithPayloadReader(buf) + ops := new(client.PutObjectParams).WithObject(raw.Object()).WithPayloadReader(bytes.NewBuffer(data)) oid, err := conn.PutObject( ctx, ops,