[#170] bearer: Add docs, refactor
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
96892d7bc4
commit
27cd721422
14 changed files with 463 additions and 368 deletions
316
bearer/bearer.go
Normal file
316
bearer/bearer.go
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
package bearer
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||||
|
v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/signature"
|
||||||
|
sigutil "github.com/nspcc-dev/neofs-sdk-go/util/signature"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
errNilBearerTokenBody = errors.New("bearer token body is not set")
|
||||||
|
errNilBearerTokenEACL = errors.New("bearer token ContainerEACL table is not set")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Token represents bearer token for object service operations.
|
||||||
|
//
|
||||||
|
// Token is mutually compatible with github.com/nspcc-dev/neofs-api-go/v2/acl.BearerToken
|
||||||
|
// message. See ReadFromV2 / WriteToV2 methods.
|
||||||
|
//
|
||||||
|
// Instances can be created using built-in var declaration.
|
||||||
|
//
|
||||||
|
// Note that direct typecast is not safe and may result in loss of compatibility:
|
||||||
|
// _ = Token(acl.BearerToken{}) // not recommended
|
||||||
|
type Token acl.BearerToken
|
||||||
|
|
||||||
|
// ReadFromV2 reads Token from the acl.BearerToken message.
|
||||||
|
//
|
||||||
|
// See also WriteToV2.
|
||||||
|
func (b *Token) ReadFromV2(m acl.BearerToken) {
|
||||||
|
*b = Token(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteToV2 writes Token to the acl.BearerToken message.
|
||||||
|
// The message must not be nil.
|
||||||
|
//
|
||||||
|
// See also ReadFromV2.
|
||||||
|
func (b Token) WriteToV2(m *acl.BearerToken) {
|
||||||
|
*m = (acl.BearerToken)(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns true if bearer token has no fields set.
|
||||||
|
func (b Token) IsEmpty() bool {
|
||||||
|
v2token := (acl.BearerToken)(b)
|
||||||
|
return v2token.GetBody() == nil && v2token.GetSignature() == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetExpiration sets "exp" (expiration time) claim which identifies the
|
||||||
|
// expiration time (in NeoFS epochs) on or after which the Token MUST NOT be
|
||||||
|
// accepted for processing. The processing of the "exp" claim requires that the
|
||||||
|
// current epoch MUST be before the expiration epoch listed in the "exp" claim.
|
||||||
|
//
|
||||||
|
// Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.4.
|
||||||
|
//
|
||||||
|
// See also Expiration.
|
||||||
|
func (b *Token) SetExpiration(exp uint64) {
|
||||||
|
v2token := (*acl.BearerToken)(b)
|
||||||
|
|
||||||
|
body := v2token.GetBody()
|
||||||
|
if body == nil {
|
||||||
|
body = new(acl.BearerTokenBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
lt := new(acl.TokenLifetime)
|
||||||
|
lt.SetExp(exp)
|
||||||
|
lt.SetNbf(body.GetLifetime().GetNbf())
|
||||||
|
lt.SetIat(body.GetLifetime().GetIat())
|
||||||
|
|
||||||
|
body.SetLifetime(lt)
|
||||||
|
v2token.SetBody(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expiration returns "exp" claim.
|
||||||
|
//
|
||||||
|
// Empty Token has zero "exp".
|
||||||
|
//
|
||||||
|
// See also SetExpiration.
|
||||||
|
func (b Token) Expiration() uint64 {
|
||||||
|
v2token := (acl.BearerToken)(b)
|
||||||
|
return v2token.GetBody().GetLifetime().GetExp()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetNotBefore sets "nbf" (not before) claim which identifies the time (in
|
||||||
|
// NeoFS epochs) before which the Token MUST NOT be accepted for processing. The
|
||||||
|
// processing of the "nbf" claim requires that the current epoch MUST be
|
||||||
|
// after or equal to the not-before epoch listed in the "nbf" claim.
|
||||||
|
//
|
||||||
|
// Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.5.
|
||||||
|
//
|
||||||
|
// See also NotBefore.
|
||||||
|
func (b *Token) SetNotBefore(nbf uint64) {
|
||||||
|
v2token := (*acl.BearerToken)(b)
|
||||||
|
|
||||||
|
body := v2token.GetBody()
|
||||||
|
if body == nil {
|
||||||
|
body = new(acl.BearerTokenBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
lt := new(acl.TokenLifetime)
|
||||||
|
lt.SetExp(body.GetLifetime().GetExp())
|
||||||
|
lt.SetNbf(nbf)
|
||||||
|
lt.SetIat(body.GetLifetime().GetIat())
|
||||||
|
|
||||||
|
body.SetLifetime(lt)
|
||||||
|
v2token.SetBody(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NotBefore returns "nbf" claim.
|
||||||
|
//
|
||||||
|
// Empty Token has zero "nbf".
|
||||||
|
//
|
||||||
|
// See also SetNotBefore.
|
||||||
|
func (b Token) NotBefore() uint64 {
|
||||||
|
v2token := (acl.BearerToken)(b)
|
||||||
|
return v2token.GetBody().GetLifetime().GetNbf()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetIssuedAt sets "iat" (issued at) claim which identifies the time (in NeoFS
|
||||||
|
// epochs) at which the Token was issued. This claim can be used to determine
|
||||||
|
// the age of the Token.
|
||||||
|
//
|
||||||
|
// Naming is inspired by https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6.
|
||||||
|
//
|
||||||
|
// See also IssuedAt.
|
||||||
|
func (b *Token) SetIssuedAt(iat uint64) {
|
||||||
|
v2token := (*acl.BearerToken)(b)
|
||||||
|
|
||||||
|
body := v2token.GetBody()
|
||||||
|
if body == nil {
|
||||||
|
body = new(acl.BearerTokenBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
lt := new(acl.TokenLifetime)
|
||||||
|
lt.SetExp(body.GetLifetime().GetExp())
|
||||||
|
lt.SetNbf(body.GetLifetime().GetNbf())
|
||||||
|
lt.SetIat(iat)
|
||||||
|
|
||||||
|
body.SetLifetime(lt)
|
||||||
|
v2token.SetBody(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IssuedAt returns "iat" claim.
|
||||||
|
//
|
||||||
|
// Empty Token has zero "iat".
|
||||||
|
//
|
||||||
|
// See also SetIssuedAt.
|
||||||
|
func (b Token) IssuedAt() uint64 {
|
||||||
|
v2token := (acl.BearerToken)(b)
|
||||||
|
return v2token.GetBody().GetLifetime().GetIat()
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetEACLTable sets extended ACL table that should be used during object
|
||||||
|
// service request processing with bearer token.
|
||||||
|
//
|
||||||
|
// See also EACLTable.
|
||||||
|
func (b *Token) SetEACLTable(table eacl.Table) {
|
||||||
|
v2 := (*acl.BearerToken)(b)
|
||||||
|
|
||||||
|
body := v2.GetBody()
|
||||||
|
if body == nil {
|
||||||
|
body = new(acl.BearerTokenBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
body.SetEACL(table.ToV2())
|
||||||
|
v2.SetBody(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EACLTable returns extended ACL table that should be used during object
|
||||||
|
// service request processing with bearer token.
|
||||||
|
//
|
||||||
|
// See also SetEACLTable.
|
||||||
|
func (b Token) EACLTable() eacl.Table {
|
||||||
|
v2 := (acl.BearerToken)(b)
|
||||||
|
return *eacl.NewTableFromV2(v2.GetBody().GetEACL())
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOwnerID sets owner.ID value of the user who can attach bearer token to
|
||||||
|
// its requests.
|
||||||
|
//
|
||||||
|
// See also OwnerID.
|
||||||
|
func (b *Token) SetOwnerID(id owner.ID) {
|
||||||
|
v2 := (*acl.BearerToken)(b)
|
||||||
|
|
||||||
|
body := v2.GetBody()
|
||||||
|
if body == nil {
|
||||||
|
body = new(acl.BearerTokenBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
body.SetOwnerID(id.ToV2())
|
||||||
|
v2.SetBody(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OwnerID returns owner.ID value of the user who can attach bearer token to
|
||||||
|
// its requests.
|
||||||
|
//
|
||||||
|
// See also SetOwnerID.
|
||||||
|
func (b Token) OwnerID() owner.ID {
|
||||||
|
v2 := (acl.BearerToken)(b)
|
||||||
|
return *owner.NewIDFromV2(v2.GetBody().GetOwnerID())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign signs bearer token. This method should be invoked with the private
|
||||||
|
// key of container owner to allow overriding extended ACL table of the container
|
||||||
|
// included in this token.
|
||||||
|
//
|
||||||
|
// See also Signature.
|
||||||
|
func (b *Token) Sign(key ecdsa.PrivateKey) error {
|
||||||
|
err := sanityCheck(b)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
v2 := (*acl.BearerToken)(b)
|
||||||
|
signWrapper := v2signature.StableMarshalerWrapper{SM: v2.GetBody()}
|
||||||
|
|
||||||
|
sig, err := sigutil.SignData(&key, signWrapper)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
v2.SetSignature(sig.ToV2())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// VerifySignature returns nil if bearer token contains correct signature.
|
||||||
|
func (b Token) VerifySignature() error {
|
||||||
|
if b.IsEmpty() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
v2 := (acl.BearerToken)(b)
|
||||||
|
|
||||||
|
return sigutil.VerifyData(
|
||||||
|
v2signature.StableMarshalerWrapper{SM: v2.GetBody()},
|
||||||
|
signature.NewFromV2(v2.GetSignature()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Issuer returns owner.ID associated with the key that signed bearer token.
|
||||||
|
// To pass node validation it should be owner of requested container.
|
||||||
|
//
|
||||||
|
// If token is not signed, issuer returns empty owner ID.
|
||||||
|
//
|
||||||
|
// See also Sign.
|
||||||
|
func (b Token) Issuer() (id owner.ID) {
|
||||||
|
v2 := (acl.BearerToken)(b)
|
||||||
|
|
||||||
|
pub, _ := keys.NewPublicKeyFromBytes(v2.GetSignature().GetKey(), elliptic.P256())
|
||||||
|
if pub == nil {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
return *owner.NewIDFromPublicKey((*ecdsa.PublicKey)(pub))
|
||||||
|
}
|
||||||
|
|
||||||
|
// sanityCheck if bearer token is ready to be issued.
|
||||||
|
func sanityCheck(b *Token) error {
|
||||||
|
v2 := (*acl.BearerToken)(b)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case v2.GetBody() == nil:
|
||||||
|
return errNilBearerTokenBody
|
||||||
|
case v2.GetBody().GetEACL() == nil:
|
||||||
|
return errNilBearerTokenEACL
|
||||||
|
}
|
||||||
|
|
||||||
|
// consider checking ContainerEACL sanity there, lifetime correctness, etc.
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Marshal marshals Token into a canonical NeoFS binary format (proto3
|
||||||
|
// with direct field order).
|
||||||
|
//
|
||||||
|
// See also Unmarshal.
|
||||||
|
func (b Token) Marshal() []byte {
|
||||||
|
v2 := (acl.BearerToken)(b)
|
||||||
|
|
||||||
|
data, err := v2.StableMarshal(nil)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal unmarshals Token from canonical NeoFS binary format (proto3
|
||||||
|
// with direct field order).
|
||||||
|
//
|
||||||
|
// See also Marshal.
|
||||||
|
func (b *Token) Unmarshal(data []byte) error {
|
||||||
|
v2 := (*acl.BearerToken)(b)
|
||||||
|
return v2.Unmarshal(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON encodes Token to protobuf JSON format.
|
||||||
|
//
|
||||||
|
// See also UnmarshalJSON.
|
||||||
|
func (b Token) MarshalJSON() ([]byte, error) {
|
||||||
|
v2 := (acl.BearerToken)(b)
|
||||||
|
return v2.MarshalJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON decodes Token from protobuf JSON format.
|
||||||
|
//
|
||||||
|
// See also MarshalJSON.
|
||||||
|
func (b *Token) UnmarshalJSON(data []byte) error {
|
||||||
|
v2 := (*acl.BearerToken)(b)
|
||||||
|
return v2.UnmarshalJSON(data)
|
||||||
|
}
|
57
bearer/bearer_test.go
Normal file
57
bearer/bearer_test.go
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
package bearer_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
|
tokentest "github.com/nspcc-dev/neofs-sdk-go/bearer/test"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBearerToken_Issuer(t *testing.T) {
|
||||||
|
var bearerToken bearer.Token
|
||||||
|
|
||||||
|
t.Run("non signed token", func(t *testing.T) {
|
||||||
|
id := bearerToken.Issuer()
|
||||||
|
require.Equal(t, owner.ID{}, id)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("signed token", func(t *testing.T) {
|
||||||
|
p, err := keys.NewPrivateKey()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
ownerID := owner.NewIDFromPublicKey((*ecdsa.PublicKey)(p.PublicKey()))
|
||||||
|
|
||||||
|
bearerToken.SetEACLTable(*eacl.NewTable())
|
||||||
|
require.NoError(t, bearerToken.Sign(p.PrivateKey))
|
||||||
|
issuer := bearerToken.Issuer()
|
||||||
|
require.True(t, ownerID.Equal(&issuer))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFilterEncoding(t *testing.T) {
|
||||||
|
f := tokentest.Token()
|
||||||
|
|
||||||
|
t.Run("binary", func(t *testing.T) {
|
||||||
|
data := f.Marshal()
|
||||||
|
|
||||||
|
var f2 bearer.Token
|
||||||
|
require.NoError(t, f2.Unmarshal(data))
|
||||||
|
|
||||||
|
require.Equal(t, f, f2)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("json", func(t *testing.T) {
|
||||||
|
data, err := f.MarshalJSON()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var d2 bearer.Token
|
||||||
|
require.NoError(t, d2.UnmarshalJSON(data))
|
||||||
|
|
||||||
|
require.Equal(t, f, d2)
|
||||||
|
})
|
||||||
|
}
|
28
bearer/doc.go
Normal file
28
bearer/doc.go
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
Package bearer provides bearer token definition.
|
||||||
|
|
||||||
|
Bearer token is attached to the object service requests, and it overwrites
|
||||||
|
extended ACL of the container. Mainly it is used to provide access of private
|
||||||
|
data for specific user. Therefore, it must be signed by owner of the container.
|
||||||
|
|
||||||
|
Define bearer token by setting correct lifetime, extended ACL and owner ID of
|
||||||
|
the user that will attach token to its requests.
|
||||||
|
var bearerToken bearer.Token
|
||||||
|
bearerToken.SetExpiration(500)
|
||||||
|
bearerToken.SetIssuedAt(10)
|
||||||
|
bearerToken.SetNotBefore(10)
|
||||||
|
bearerToken.SetEACL(eaclTable)
|
||||||
|
bearerToken.SetOwner(ownerID)
|
||||||
|
|
||||||
|
Bearer token must be signed by owner of the container.
|
||||||
|
err := bearerToken.Sign(privateKey)
|
||||||
|
|
||||||
|
Provide signed token in JSON or binary format to the request sender. Request
|
||||||
|
sender can attach this bearer token to the object service requests:
|
||||||
|
import sdkClient "github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
|
|
||||||
|
var headParams sdkClient.PrmObjectHead
|
||||||
|
headParams.WithBearerToken(bearerToken)
|
||||||
|
response, err := client.ObjectHead(ctx, headParams)
|
||||||
|
*/
|
||||||
|
package bearer
|
6
bearer/test/doc.go
Normal file
6
bearer/test/doc.go
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
/*
|
||||||
|
Package bearertest provides functions for testing bearer package.
|
||||||
|
|
||||||
|
Note that this package intended only for tests.
|
||||||
|
*/
|
||||||
|
package bearertest
|
20
bearer/test/generate.go
Normal file
20
bearer/test/generate.go
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
package bearertest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
|
eacltest "github.com/nspcc-dev/neofs-sdk-go/eacl/test"
|
||||||
|
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Token returns random bearer.Token.
|
||||||
|
//
|
||||||
|
// Resulting token is unsigned.
|
||||||
|
func Token() (t bearer.Token) {
|
||||||
|
t.SetExpiration(3)
|
||||||
|
t.SetNotBefore(2)
|
||||||
|
t.SetIssuedAt(1)
|
||||||
|
t.SetOwnerID(*ownertest.ID())
|
||||||
|
t.SetEACLTable(*eacltest.Table())
|
||||||
|
|
||||||
|
return t
|
||||||
|
}
|
|
@ -4,15 +4,16 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||||
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PrmObjectDelete groups parameters of ObjectDelete operation.
|
// PrmObjectDelete groups parameters of ObjectDelete operation.
|
||||||
|
@ -42,8 +43,10 @@ func (x *PrmObjectDelete) WithinSession(t session.Token) {
|
||||||
// If set, underlying eACL rules will be used in access control.
|
// If set, underlying eACL rules will be used in access control.
|
||||||
//
|
//
|
||||||
// Must be signed.
|
// Must be signed.
|
||||||
func (x *PrmObjectDelete) WithBearerToken(t token.BearerToken) {
|
func (x *PrmObjectDelete) WithBearerToken(t bearer.Token) {
|
||||||
x.meta.SetBearerToken(t.ToV2())
|
var v2token acl.BearerToken
|
||||||
|
t.WriteToV2(&v2token)
|
||||||
|
x.meta.SetBearerToken(&v2token)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromContainer specifies NeoFS container of the object.
|
// FromContainer specifies NeoFS container of the object.
|
||||||
|
|
|
@ -7,17 +7,18 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||||
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// shared parameters of GET/HEAD/RANGE.
|
// shared parameters of GET/HEAD/RANGE.
|
||||||
|
@ -32,7 +33,7 @@ type prmObjectRead struct {
|
||||||
session session.Token
|
session session.Token
|
||||||
|
|
||||||
bearerSet bool
|
bearerSet bool
|
||||||
bearer token.BearerToken
|
bearer bearer.Token
|
||||||
|
|
||||||
cnrSet bool
|
cnrSet bool
|
||||||
cnr cid.ID
|
cnr cid.ID
|
||||||
|
@ -47,7 +48,9 @@ func (x prmObjectRead) writeToMetaHeader(h *v2session.RequestMetaHeader) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if x.bearerSet {
|
if x.bearerSet {
|
||||||
h.SetBearerToken(x.bearer.ToV2())
|
var v2token acl.BearerToken
|
||||||
|
x.bearer.WriteToV2(&v2token)
|
||||||
|
h.SetBearerToken(&v2token)
|
||||||
}
|
}
|
||||||
|
|
||||||
if x.sessionSet {
|
if x.sessionSet {
|
||||||
|
@ -83,7 +86,7 @@ func (x *prmObjectRead) WithinSession(t session.Token) {
|
||||||
// If set, underlying eACL rules will be used in access control.
|
// If set, underlying eACL rules will be used in access control.
|
||||||
//
|
//
|
||||||
// Must be signed.
|
// Must be signed.
|
||||||
func (x *prmObjectRead) WithBearerToken(t token.BearerToken) {
|
func (x *prmObjectRead) WithBearerToken(t bearer.Token) {
|
||||||
x.bearer = t
|
x.bearer = t
|
||||||
x.bearerSet = true
|
x.bearerSet = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,16 @@ package client
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||||
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PrmObjectHash groups parameters of ObjectHash operation.
|
// PrmObjectHash groups parameters of ObjectHash operation.
|
||||||
|
@ -45,8 +46,10 @@ func (x *PrmObjectHash) WithinSession(t session.Token) {
|
||||||
// If set, underlying eACL rules will be used in access control.
|
// If set, underlying eACL rules will be used in access control.
|
||||||
//
|
//
|
||||||
// Must be signed.
|
// Must be signed.
|
||||||
func (x *PrmObjectHash) WithBearerToken(t token.BearerToken) {
|
func (x *PrmObjectHash) WithBearerToken(t bearer.Token) {
|
||||||
x.meta.SetBearerToken(t.ToV2())
|
var v2token acl.BearerToken
|
||||||
|
t.WriteToV2(&v2token)
|
||||||
|
x.meta.SetBearerToken(&v2token)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FromContainer specifies NeoFS container of the object.
|
// FromContainer specifies NeoFS container of the object.
|
||||||
|
|
|
@ -5,14 +5,15 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||||
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PrmObjectPutInit groups parameters of ObjectPutInit operation.
|
// PrmObjectPutInit groups parameters of ObjectPutInit operation.
|
||||||
|
@ -69,8 +70,10 @@ func (x *ObjectWriter) UseKey(key ecdsa.PrivateKey) {
|
||||||
|
|
||||||
// WithBearerToken attaches bearer token to be used for the operation.
|
// WithBearerToken attaches bearer token to be used for the operation.
|
||||||
// Should be called once before any writing steps.
|
// Should be called once before any writing steps.
|
||||||
func (x *ObjectWriter) WithBearerToken(t token.BearerToken) {
|
func (x *ObjectWriter) WithBearerToken(t bearer.Token) {
|
||||||
x.metaHdr.SetBearerToken(t.ToV2())
|
var v2token acl.BearerToken
|
||||||
|
t.WriteToV2(&v2token)
|
||||||
|
x.metaHdr.SetBearerToken(&v2token)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithinSession specifies session within which object should be stored.
|
// WithinSession specifies session within which object should be stored.
|
||||||
|
|
|
@ -7,17 +7,18 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
||||||
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
|
||||||
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
v2refs "github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
|
||||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// PrmObjectSearch groups parameters of ObjectSearch operation.
|
// PrmObjectSearch groups parameters of ObjectSearch operation.
|
||||||
|
@ -30,7 +31,7 @@ type PrmObjectSearch struct {
|
||||||
session session.Token
|
session session.Token
|
||||||
|
|
||||||
bearerSet bool
|
bearerSet bool
|
||||||
bearer token.BearerToken
|
bearer bearer.Token
|
||||||
|
|
||||||
cnrSet bool
|
cnrSet bool
|
||||||
cnr cid.ID
|
cnr cid.ID
|
||||||
|
@ -59,7 +60,7 @@ func (x *PrmObjectSearch) WithinSession(t session.Token) {
|
||||||
// If set, underlying eACL rules will be used in access control.
|
// If set, underlying eACL rules will be used in access control.
|
||||||
//
|
//
|
||||||
// Must be signed.
|
// Must be signed.
|
||||||
func (x *PrmObjectSearch) WithBearerToken(t token.BearerToken) {
|
func (x *PrmObjectSearch) WithBearerToken(t bearer.Token) {
|
||||||
x.bearer = t
|
x.bearer = t
|
||||||
x.bearerSet = true
|
x.bearerSet = true
|
||||||
}
|
}
|
||||||
|
@ -257,7 +258,9 @@ func (c *Client) ObjectSearchInit(ctx context.Context, prm PrmObjectSearch) (*Ob
|
||||||
}
|
}
|
||||||
|
|
||||||
if prm.bearerSet {
|
if prm.bearerSet {
|
||||||
meta.SetBearerToken(prm.bearer.ToV2())
|
var v2token acl.BearerToken
|
||||||
|
prm.bearer.WriteToV2(&v2token)
|
||||||
|
meta.SetBearerToken(&v2token)
|
||||||
}
|
}
|
||||||
|
|
||||||
if prm.sessionSet {
|
if prm.sessionSet {
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||||
sessionv2 "github.com/nspcc-dev/neofs-api-go/v2/session"
|
sessionv2 "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/accounting"
|
"github.com/nspcc-dev/neofs-sdk-go/accounting"
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/bearer"
|
||||||
sdkClient "github.com/nspcc-dev/neofs-sdk-go/client"
|
sdkClient "github.com/nspcc-dev/neofs-sdk-go/client"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/container"
|
"github.com/nspcc-dev/neofs-sdk-go/container"
|
||||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||||
|
@ -27,7 +28,6 @@ import (
|
||||||
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -620,7 +620,7 @@ func (x *prmContext) useVerb(verb sessionv2.ObjectSessionVerb) {
|
||||||
|
|
||||||
type prmCommon struct {
|
type prmCommon struct {
|
||||||
key *ecdsa.PrivateKey
|
key *ecdsa.PrivateKey
|
||||||
btoken *token.BearerToken
|
btoken *bearer.Token
|
||||||
stoken *session.Token
|
stoken *session.Token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -631,8 +631,8 @@ func (x *prmCommon) UseKey(key *ecdsa.PrivateKey) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseBearer attaches bearer token to be used for the operation.
|
// UseBearer attaches bearer token to be used for the operation.
|
||||||
func (x *prmCommon) UseBearer(token *token.BearerToken) {
|
func (x *prmCommon) UseBearer(token bearer.Token) {
|
||||||
x.btoken = token
|
x.btoken = &token
|
||||||
}
|
}
|
||||||
|
|
||||||
// UseSession specifies session within which operation should be performed.
|
// UseSession specifies session within which operation should be performed.
|
||||||
|
|
226
token/bearer.go
226
token/bearer.go
|
@ -1,226 +0,0 @@
|
||||||
package token
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/elliptic"
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/acl"
|
|
||||||
v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/signature"
|
|
||||||
sigutil "github.com/nspcc-dev/neofs-sdk-go/util/signature"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
errNilBearerToken = errors.New("bearer token is not set")
|
|
||||||
errNilBearerTokenBody = errors.New("bearer token body is not set")
|
|
||||||
errNilBearerTokenEACL = errors.New("bearer token ContainerEACL table is not set")
|
|
||||||
)
|
|
||||||
|
|
||||||
type BearerToken struct {
|
|
||||||
token acl.BearerToken
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToV2 converts BearerToken to v2 BearerToken message.
|
|
||||||
//
|
|
||||||
// Nil BearerToken converts to nil.
|
|
||||||
func (b *BearerToken) ToV2() *acl.BearerToken {
|
|
||||||
if b == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &b.token
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BearerToken) Empty() bool {
|
|
||||||
return b == nil || b.token.GetBody() == nil && b.token.GetSignature() == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BearerToken) SetLifetime(exp, nbf, iat uint64) {
|
|
||||||
body := b.token.GetBody()
|
|
||||||
if body == nil {
|
|
||||||
body = new(acl.BearerTokenBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
lt := new(acl.TokenLifetime)
|
|
||||||
lt.SetExp(exp)
|
|
||||||
lt.SetNbf(nbf)
|
|
||||||
lt.SetIat(iat)
|
|
||||||
|
|
||||||
body.SetLifetime(lt)
|
|
||||||
b.token.SetBody(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b BearerToken) Expiration() uint64 {
|
|
||||||
return b.token.GetBody().GetLifetime().GetExp()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b BearerToken) NotBeforeTime() uint64 {
|
|
||||||
return b.token.GetBody().GetLifetime().GetNbf()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b BearerToken) IssuedAt() uint64 {
|
|
||||||
return b.token.GetBody().GetLifetime().GetIat()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BearerToken) SetEACLTable(table *eacl.Table) {
|
|
||||||
body := b.token.GetBody()
|
|
||||||
if body == nil {
|
|
||||||
body = new(acl.BearerTokenBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
body.SetEACL(table.ToV2())
|
|
||||||
b.token.SetBody(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b BearerToken) EACLTable() *eacl.Table {
|
|
||||||
return eacl.NewTableFromV2(b.token.GetBody().GetEACL())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BearerToken) SetOwner(id *owner.ID) {
|
|
||||||
body := b.token.GetBody()
|
|
||||||
if body == nil {
|
|
||||||
body = new(acl.BearerTokenBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
body.SetOwnerID(id.ToV2())
|
|
||||||
b.token.SetBody(body)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b BearerToken) OwnerID() *owner.ID {
|
|
||||||
return owner.NewIDFromV2(b.token.GetBody().GetOwnerID())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BearerToken) SignToken(key *ecdsa.PrivateKey) error {
|
|
||||||
err := sanityCheck(b)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
signWrapper := v2signature.StableMarshalerWrapper{SM: b.token.GetBody()}
|
|
||||||
|
|
||||||
sig, err := sigutil.SignData(key, signWrapper)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
b.token.SetSignature(sig.ToV2())
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b BearerToken) Signature() *signature.Signature {
|
|
||||||
return signature.NewFromV2(b.token.GetSignature())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b BearerToken) VerifySignature() error {
|
|
||||||
if b.Empty() {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sigV2 := b.token.GetSignature()
|
|
||||||
return sigutil.VerifyData(
|
|
||||||
v2signature.StableMarshalerWrapper{SM: b.token.GetBody()},
|
|
||||||
signature.NewFromV2(sigV2))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Issuer returns owner.ID associated with the key that signed bearer token.
|
|
||||||
// To pass node validation it should be owner of requested container. Returns
|
|
||||||
// nil if token is not signed.
|
|
||||||
func (b *BearerToken) Issuer() *owner.ID {
|
|
||||||
pub, _ := keys.NewPublicKeyFromBytes(b.token.GetSignature().GetKey(), elliptic.P256())
|
|
||||||
if pub == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return owner.NewIDFromPublicKey((*ecdsa.PublicKey)(pub))
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewBearerToken creates and initializes blank BearerToken.
|
|
||||||
//
|
|
||||||
// Defaults:
|
|
||||||
// - signature: nil;
|
|
||||||
// - eacl: nil;
|
|
||||||
// - ownerID: nil;
|
|
||||||
// - exp: 0;
|
|
||||||
// - nbf: 0;
|
|
||||||
// - iat: 0.
|
|
||||||
func NewBearerToken() *BearerToken {
|
|
||||||
b := new(BearerToken)
|
|
||||||
b.token = acl.BearerToken{}
|
|
||||||
b.token.SetBody(new(acl.BearerTokenBody))
|
|
||||||
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToV2 converts BearerToken to v2 BearerToken message.
|
|
||||||
func NewBearerTokenFromV2(v2 *acl.BearerToken) *BearerToken {
|
|
||||||
if v2 == nil {
|
|
||||||
v2 = new(acl.BearerToken)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &BearerToken{
|
|
||||||
token: *v2,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// sanityCheck if bearer token is ready to be issued.
|
|
||||||
func sanityCheck(b *BearerToken) error {
|
|
||||||
switch {
|
|
||||||
case b == nil:
|
|
||||||
return errNilBearerToken
|
|
||||||
case b.token.GetBody() == nil:
|
|
||||||
return errNilBearerTokenBody
|
|
||||||
case b.token.GetBody().GetEACL() == nil:
|
|
||||||
return errNilBearerTokenEACL
|
|
||||||
}
|
|
||||||
|
|
||||||
// consider checking ContainerEACL sanity there, lifetime correctness, etc.
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Marshal marshals BearerToken into a protobuf binary form.
|
|
||||||
//
|
|
||||||
// Buffer is allocated when the argument is empty.
|
|
||||||
// Otherwise, the first buffer is used.
|
|
||||||
func (b *BearerToken) Marshal(bs ...[]byte) ([]byte, error) {
|
|
||||||
var buf []byte
|
|
||||||
if len(bs) > 0 {
|
|
||||||
buf = bs[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.ToV2().
|
|
||||||
StableMarshal(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unmarshal unmarshals protobuf binary representation of BearerToken.
|
|
||||||
func (b *BearerToken) Unmarshal(data []byte) error {
|
|
||||||
fV2 := new(acl.BearerToken)
|
|
||||||
if err := fV2.Unmarshal(data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*b = *NewBearerTokenFromV2(fV2)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MarshalJSON encodes BearerToken to protobuf JSON format.
|
|
||||||
func (b *BearerToken) MarshalJSON() ([]byte, error) {
|
|
||||||
return b.ToV2().
|
|
||||||
MarshalJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON decodes BearerToken from protobuf JSON format.
|
|
||||||
func (b *BearerToken) UnmarshalJSON(data []byte) error {
|
|
||||||
fV2 := new(acl.BearerToken)
|
|
||||||
if err := fV2.UnmarshalJSON(data); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
*b = *NewBearerTokenFromV2(fV2)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,81 +0,0 @@
|
||||||
package token_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"crypto/ecdsa"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
|
||||||
tokentest "github.com/nspcc-dev/neofs-sdk-go/token/test"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestBearerToken_Issuer(t *testing.T) {
|
|
||||||
bearerToken := token.NewBearerToken()
|
|
||||||
|
|
||||||
t.Run("non signed token", func(t *testing.T) {
|
|
||||||
require.Nil(t, bearerToken.Issuer())
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("signed token", func(t *testing.T) {
|
|
||||||
p, err := keys.NewPrivateKey()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
ownerID := owner.NewIDFromPublicKey((*ecdsa.PublicKey)(p.PublicKey()))
|
|
||||||
|
|
||||||
bearerToken.SetEACLTable(eacl.NewTable())
|
|
||||||
require.NoError(t, bearerToken.SignToken(&p.PrivateKey))
|
|
||||||
require.True(t, ownerID.Equal(bearerToken.Issuer()))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFilterEncoding(t *testing.T) {
|
|
||||||
f := tokentest.BearerToken()
|
|
||||||
|
|
||||||
t.Run("binary", func(t *testing.T) {
|
|
||||||
data, err := f.Marshal()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
f2 := token.NewBearerToken()
|
|
||||||
require.NoError(t, f2.Unmarshal(data))
|
|
||||||
|
|
||||||
require.Equal(t, f, f2)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("json", func(t *testing.T) {
|
|
||||||
data, err := f.MarshalJSON()
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
d2 := token.NewBearerToken()
|
|
||||||
require.NoError(t, d2.UnmarshalJSON(data))
|
|
||||||
|
|
||||||
require.Equal(t, f, d2)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBearerToken_ToV2(t *testing.T) {
|
|
||||||
t.Run("nil", func(t *testing.T) {
|
|
||||||
var x *token.BearerToken
|
|
||||||
|
|
||||||
require.Nil(t, x.ToV2())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewBearerToken(t *testing.T) {
|
|
||||||
t.Run("default values", func(t *testing.T) {
|
|
||||||
tkn := token.NewBearerToken()
|
|
||||||
|
|
||||||
// convert to v2 message
|
|
||||||
tknV2 := tkn.ToV2()
|
|
||||||
|
|
||||||
require.NotNil(t, tknV2.GetBody())
|
|
||||||
require.Zero(t, tknV2.GetBody().GetLifetime().GetExp())
|
|
||||||
require.Zero(t, tknV2.GetBody().GetLifetime().GetNbf())
|
|
||||||
require.Zero(t, tknV2.GetBody().GetLifetime().GetIat())
|
|
||||||
require.Nil(t, tknV2.GetBody().GetEACL())
|
|
||||||
require.Nil(t, tknV2.GetBody().GetOwnerID())
|
|
||||||
require.Nil(t, tknV2.GetSignature())
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package tokentest
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
||||||
eacltest "github.com/nspcc-dev/neofs-sdk-go/eacl/test"
|
|
||||||
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
|
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/token"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BearerToken returns random token.BearerToken.
|
|
||||||
//
|
|
||||||
// Resulting token is unsigned.
|
|
||||||
func BearerToken() *token.BearerToken {
|
|
||||||
x := token.NewBearerToken()
|
|
||||||
|
|
||||||
x.SetLifetime(3, 2, 1)
|
|
||||||
x.SetOwner(ownertest.ID())
|
|
||||||
x.SetEACLTable(eacltest.Table())
|
|
||||||
|
|
||||||
return x
|
|
||||||
}
|
|
||||||
|
|
||||||
// SignedBearerToken returns signed random token.BearerToken.
|
|
||||||
//
|
|
||||||
// Panics if token could not be signed (actually unexpected).
|
|
||||||
func SignedBearerToken() *token.BearerToken {
|
|
||||||
tok := BearerToken()
|
|
||||||
|
|
||||||
p, err := keys.NewPrivateKey()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tok.SignToken(&p.PrivateKey)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tok
|
|
||||||
}
|
|
Loading…
Reference in a new issue