[#32] Add route to form full binary bearer token

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
Denis Kirillov 2022-08-18 17:35:53 +03:00 committed by Kirillov Denis
parent ada5bf5f9f
commit 07786dd94b
12 changed files with 703 additions and 5 deletions

View file

@ -25,6 +25,7 @@ import (
"github.com/nspcc-dev/neofs-rest-gw/gen/restapi/operations" "github.com/nspcc-dev/neofs-rest-gw/gen/restapi/operations"
"github.com/nspcc-dev/neofs-rest-gw/handlers" "github.com/nspcc-dev/neofs-rest-gw/handlers"
"github.com/nspcc-dev/neofs-rest-gw/internal/util" "github.com/nspcc-dev/neofs-rest-gw/internal/util"
"github.com/nspcc-dev/neofs-sdk-go/bearer"
"github.com/nspcc-dev/neofs-sdk-go/container" "github.com/nspcc-dev/neofs-sdk-go/container"
"github.com/nspcc-dev/neofs-sdk-go/container/acl" "github.com/nspcc-dev/neofs-sdk-go/container/acl"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
@ -117,6 +118,7 @@ func runTests(ctx context.Context, t *testing.T, key *keys.PrivateKey, version s
t.Run("rest auth several tokens "+version, func(t *testing.T) { authTokens(ctx, t) }) t.Run("rest auth several tokens "+version, func(t *testing.T) { authTokens(ctx, t) })
t.Run("rest check mix tokens up "+version, func(t *testing.T) { mixTokens(ctx, t, cnrID) }) t.Run("rest check mix tokens up "+version, func(t *testing.T) { mixTokens(ctx, t, cnrID) })
t.Run("rest form full binary bearer "+version, func(t *testing.T) { formFullBinaryBearer(ctx, t) })
t.Run("rest put object "+version, func(t *testing.T) { restObjectPut(ctx, t, clientPool, cnrID) }) t.Run("rest put object "+version, func(t *testing.T) { restObjectPut(ctx, t, clientPool, cnrID) })
t.Run("rest get object "+version, func(t *testing.T) { restObjectGet(ctx, t, clientPool, &owner, cnrID) }) t.Run("rest get object "+version, func(t *testing.T) { restObjectGet(ctx, t, clientPool, &owner, cnrID) })
@ -319,6 +321,68 @@ func mixTokens(ctx context.Context, t *testing.T, cnrID cid.ID) {
checkPutObjectWithError(t, httpClient, cnrID, containerSetEACLToken) checkPutObjectWithError(t, httpClient, cnrID, containerSetEACLToken)
} }
func formFullBinaryBearer(ctx context.Context, t *testing.T) {
bearers := []*models.Bearer{
{
Name: "all-object",
Object: []*models.Record{{
Operation: models.NewOperation(models.OperationPUT),
Action: models.NewAction(models.ActionALLOW),
Filters: []*models.Filter{},
Targets: []*models.Target{{
Role: models.NewRole(models.RoleOTHERS),
Keys: []string{},
}},
}},
},
{
Name: "put-container",
Container: &models.Rule{
Verb: models.NewVerb(models.VerbPUT),
},
},
}
httpClient := defaultHTTPClient()
tokens := makeAuthTokenRequest(ctx, t, bearers, httpClient)
objectToken := tokens[0]
containerPutToken := tokens[1]
query := make(url.Values)
query.Add(walletConnectQuery, strconv.FormatBool(useWalletConnect))
// check that container token isn't valid
request, err := http.NewRequest(http.MethodGet, testHost+"/v1/auth/bearer?"+query.Encode(), nil)
require.NoError(t, err)
prepareCommonHeaders(request.Header, containerPutToken)
checkGWErrorResponse(t, httpClient, request)
// check that object bearer token is valid
request, err = http.NewRequest(http.MethodGet, testHost+"/v1/auth/bearer?"+query.Encode(), nil)
require.NoError(t, err)
prepareCommonHeaders(request.Header, objectToken)
resp := &models.BinaryBearer{}
doRequest(t, httpClient, request, http.StatusOK, resp)
actualTokenRaw, err := base64.StdEncoding.DecodeString(*resp.Token)
require.NoError(t, err)
var actualToken bearer.Token
err = actualToken.Unmarshal(actualTokenRaw)
require.NoError(t, err)
require.True(t, actualToken.VerifySignature())
require.Len(t, actualToken.EACLTable().Records(), 1)
actualRecord := actualToken.EACLTable().Records()[0]
require.Equal(t, eacl.OperationPut, actualRecord.Operation())
require.Equal(t, eacl.ActionAllow, actualRecord.Action())
require.Empty(t, actualRecord.Filters())
require.Len(t, actualRecord.Targets(), 1)
actualTarget := actualRecord.Targets()[0]
require.Empty(t, actualTarget.BinaryKeys())
require.Equal(t, eacl.RoleOthers, actualTarget.Role())
}
func checkPutContainerWithError(t *testing.T, httpClient *http.Client, token *handlers.BearerToken) { func checkPutContainerWithError(t *testing.T, httpClient *http.Client, token *handlers.BearerToken) {
reqURL, err := url.Parse(testHost + "/v1/containers") reqURL, err := url.Parse(testHost + "/v1/containers")
require.NoError(t, err) require.NoError(t, err)

View file

@ -0,0 +1,72 @@
// Code generated by go-swagger; DO NOT EDIT.
package models
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"context"
"github.com/go-openapi/errors"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// BinaryBearer Bearer token for object operations that is represented in binary form.
// Example: {"token":"ChIKDAoAGggIARABIgIIAxoCCGQSZgohA+J5jFWFMiOpyvMZBu9wwPTKsWsG0q206kVe63iuWP/wEkEE4SIV0QngnKppDf54QezUKmar7UQby6HzufT5yVIOvj7QEqZnOavrKW0chCeCwP0khda/j9k00ct6NMEDxQFW+g=="}
//
// swagger:model BinaryBearer
type BinaryBearer struct {
// Base64 encoded bearer token.
// Required: true
Token *string `json:"token"`
}
// Validate validates this binary bearer
func (m *BinaryBearer) Validate(formats strfmt.Registry) error {
var res []error
if err := m.validateToken(formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
func (m *BinaryBearer) validateToken(formats strfmt.Registry) error {
if err := validate.Required("token", "body", m.Token); err != nil {
return err
}
return nil
}
// ContextValidate validates this binary bearer based on context it is used
func (m *BinaryBearer) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
return nil
}
// MarshalBinary interface implementation
func (m *BinaryBearer) MarshalBinary() ([]byte, error) {
if m == nil {
return nil, nil
}
return swag.WriteJSON(m)
}
// UnmarshalBinary interface implementation
func (m *BinaryBearer) UnmarshalBinary(b []byte) error {
var res BinaryBearer
if err := swag.ReadJSON(b, &res); err != nil {
return err
}
*m = res
return nil
}

View file

@ -110,7 +110,7 @@ func init() {
], ],
"responses": { "responses": {
"200": { "200": {
"description": "Base64 encoded stable binary marshaled bearer token.", "description": "Base64 encoded stable binary marshaled bearer token bodies.",
"schema": { "schema": {
"type": "array", "type": "array",
"items": { "items": {
@ -149,6 +149,45 @@ func init() {
} }
} }
}, },
"/auth/bearer": {
"get": {
"produces": [
"application/json"
],
"summary": "Form binary bearer token",
"operationId": "formBinaryBearer",
"parameters": [
{
"$ref": "#/parameters/signatureParam"
},
{
"$ref": "#/parameters/signatureKeyParam"
},
{
"$ref": "#/parameters/signatureScheme"
}
],
"responses": {
"200": {
"description": "Base64 encoded stable binary marshaled bearer token.",
"schema": {
"$ref": "#/definitions/BinaryBearer"
},
"headers": {
"Access-Control-Allow-Origin": {
"type": "string"
}
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/containers": { "/containers": {
"get": { "get": {
"security": [], "security": [],
@ -844,6 +883,22 @@ func init() {
} }
] ]
}, },
"BinaryBearer": {
"description": "Bearer token for object operations that is represented in binary form.",
"type": "object",
"required": [
"token"
],
"properties": {
"token": {
"description": "Base64 encoded bearer token.",
"type": "string"
}
},
"example": {
"token": "ChIKDAoAGggIARABIgIIAxoCCGQSZgohA+J5jFWFMiOpyvMZBu9wwPTKsWsG0q206kVe63iuWP/wEkEE4SIV0QngnKppDf54QezUKmar7UQby6HzufT5yVIOvj7QEqZnOavrKW0chCeCwP0khda/j9k00ct6NMEDxQFW+g=="
}
},
"ContainerInfo": { "ContainerInfo": {
"description": "Information about container.", "description": "Information about container.",
"type": "object", "type": "object",
@ -1649,7 +1704,7 @@ func init() {
], ],
"responses": { "responses": {
"200": { "200": {
"description": "Base64 encoded stable binary marshaled bearer token.", "description": "Base64 encoded stable binary marshaled bearer token bodies.",
"schema": { "schema": {
"type": "array", "type": "array",
"items": { "items": {
@ -1688,6 +1743,57 @@ func init() {
} }
} }
}, },
"/auth/bearer": {
"get": {
"produces": [
"application/json"
],
"summary": "Form binary bearer token",
"operationId": "formBinaryBearer",
"parameters": [
{
"type": "string",
"description": "Base64 encoded signature for bearer token.",
"name": "X-Bearer-Signature",
"in": "header",
"required": true
},
{
"type": "string",
"description": "Hex encoded the public part of the key that signed the bearer token.",
"name": "X-Bearer-Signature-Key",
"in": "header",
"required": true
},
{
"type": "boolean",
"default": false,
"description": "Use wallet connect signature scheme or native NeoFS signature.",
"name": "walletConnect",
"in": "query"
}
],
"responses": {
"200": {
"description": "Base64 encoded stable binary marshaled bearer token.",
"schema": {
"$ref": "#/definitions/BinaryBearer"
},
"headers": {
"Access-Control-Allow-Origin": {
"type": "string"
}
}
},
"400": {
"description": "Bad request",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
}
}
},
"/containers": { "/containers": {
"get": { "get": {
"security": [], "security": [],
@ -2491,6 +2597,22 @@ func init() {
} }
] ]
}, },
"BinaryBearer": {
"description": "Bearer token for object operations that is represented in binary form.",
"type": "object",
"required": [
"token"
],
"properties": {
"token": {
"description": "Base64 encoded bearer token.",
"type": "string"
}
},
"example": {
"token": "ChIKDAoAGggIARABIgIIAxoCCGQSZgohA+J5jFWFMiOpyvMZBu9wwPTKsWsG0q206kVe63iuWP/wEkEE4SIV0QngnKppDf54QezUKmar7UQby6HzufT5yVIOvj7QEqZnOavrKW0chCeCwP0khda/j9k00ct6NMEDxQFW+g=="
}
},
"ContainerInfo": { "ContainerInfo": {
"description": "Information about container.", "description": "Information about container.",
"type": "object", "type": "object",

View file

@ -16,7 +16,7 @@ import (
// AuthOKCode is the HTTP code returned for type AuthOK // AuthOKCode is the HTTP code returned for type AuthOK
const AuthOKCode int = 200 const AuthOKCode int = 200
/*AuthOK Base64 encoded stable binary marshaled bearer token. /*AuthOK Base64 encoded stable binary marshaled bearer token bodies.
swagger:response authOK swagger:response authOK
*/ */

View file

@ -0,0 +1,71 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the generate command
import (
"net/http"
"github.com/go-openapi/runtime/middleware"
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
)
// FormBinaryBearerHandlerFunc turns a function with the right signature into a form binary bearer handler
type FormBinaryBearerHandlerFunc func(FormBinaryBearerParams, *models.Principal) middleware.Responder
// Handle executing the request and returning a response
func (fn FormBinaryBearerHandlerFunc) Handle(params FormBinaryBearerParams, principal *models.Principal) middleware.Responder {
return fn(params, principal)
}
// FormBinaryBearerHandler interface for that can handle valid form binary bearer params
type FormBinaryBearerHandler interface {
Handle(FormBinaryBearerParams, *models.Principal) middleware.Responder
}
// NewFormBinaryBearer creates a new http.Handler for the form binary bearer operation
func NewFormBinaryBearer(ctx *middleware.Context, handler FormBinaryBearerHandler) *FormBinaryBearer {
return &FormBinaryBearer{Context: ctx, Handler: handler}
}
/* FormBinaryBearer swagger:route GET /auth/bearer formBinaryBearer
Form binary bearer token
*/
type FormBinaryBearer struct {
Context *middleware.Context
Handler FormBinaryBearerHandler
}
func (o *FormBinaryBearer) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
route, rCtx, _ := o.Context.RouteInfo(r)
if rCtx != nil {
*r = *rCtx
}
var Params = NewFormBinaryBearerParams()
uprinc, aCtx, err := o.Context.Authorize(r, route)
if err != nil {
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
if aCtx != nil {
*r = *aCtx
}
var principal *models.Principal
if uprinc != nil {
principal = uprinc.(*models.Principal) // this is really a models.Principal, I promise
}
if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params
o.Context.Respond(rw, r, route.Produces, route, err)
return
}
res := o.Handler.Handle(Params, principal) // actually handle the request
o.Context.Respond(rw, r, route.Produces, route, res)
}

View file

@ -0,0 +1,151 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/errors"
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/swag"
"github.com/go-openapi/validate"
)
// NewFormBinaryBearerParams creates a new FormBinaryBearerParams object
// with the default values initialized.
func NewFormBinaryBearerParams() FormBinaryBearerParams {
var (
// initialize parameters with default values
walletConnectDefault = bool(false)
)
return FormBinaryBearerParams{
WalletConnect: &walletConnectDefault,
}
}
// FormBinaryBearerParams contains all the bound params for the form binary bearer operation
// typically these are obtained from a http.Request
//
// swagger:parameters formBinaryBearer
type FormBinaryBearerParams struct {
// HTTP Request Object
HTTPRequest *http.Request `json:"-"`
/*Base64 encoded signature for bearer token.
Required: true
In: header
*/
XBearerSignature string
/*Hex encoded the public part of the key that signed the bearer token.
Required: true
In: header
*/
XBearerSignatureKey string
/*Use wallet connect signature scheme or native NeoFS signature.
In: query
Default: false
*/
WalletConnect *bool
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
// for simple values it will use straight method calls.
//
// To ensure default values, the struct must have been initialized with NewFormBinaryBearerParams() beforehand.
func (o *FormBinaryBearerParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error {
var res []error
o.HTTPRequest = r
qs := runtime.Values(r.URL.Query())
if err := o.bindXBearerSignature(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature")], true, route.Formats); err != nil {
res = append(res, err)
}
if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil {
res = append(res, err)
}
qWalletConnect, qhkWalletConnect, _ := qs.GetOK("walletConnect")
if err := o.bindWalletConnect(qWalletConnect, qhkWalletConnect, route.Formats); err != nil {
res = append(res, err)
}
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
return nil
}
// bindXBearerSignature binds and validates parameter XBearerSignature from header.
func (o *FormBinaryBearerParams) bindXBearerSignature(rawData []string, hasKey bool, formats strfmt.Registry) error {
if !hasKey {
return errors.Required("X-Bearer-Signature", "header", rawData)
}
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: true
if err := validate.RequiredString("X-Bearer-Signature", "header", raw); err != nil {
return err
}
o.XBearerSignature = raw
return nil
}
// bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header.
func (o *FormBinaryBearerParams) bindXBearerSignatureKey(rawData []string, hasKey bool, formats strfmt.Registry) error {
if !hasKey {
return errors.Required("X-Bearer-Signature-Key", "header", rawData)
}
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: true
if err := validate.RequiredString("X-Bearer-Signature-Key", "header", raw); err != nil {
return err
}
o.XBearerSignatureKey = raw
return nil
}
// bindWalletConnect binds and validates parameter WalletConnect from query.
func (o *FormBinaryBearerParams) bindWalletConnect(rawData []string, hasKey bool, formats strfmt.Registry) error {
var raw string
if len(rawData) > 0 {
raw = rawData[len(rawData)-1]
}
// Required: false
// AllowEmptyValue: false
if raw == "" { // empty values pass all other validations
// Default values have been previously initialized by NewFormBinaryBearerParams()
return nil
}
value, err := swag.ConvertBool(raw)
if err != nil {
return errors.InvalidType("walletConnect", "query", "bool", raw)
}
o.WalletConnect = &value
return nil
}

View file

@ -0,0 +1,124 @@
// Code generated by go-swagger; DO NOT EDIT.
package operations
// This file was generated by the swagger tool.
// Editing this file might prove futile when you re-run the swagger generate command
import (
"net/http"
"github.com/go-openapi/runtime"
"github.com/nspcc-dev/neofs-rest-gw/gen/models"
)
// FormBinaryBearerOKCode is the HTTP code returned for type FormBinaryBearerOK
const FormBinaryBearerOKCode int = 200
/*FormBinaryBearerOK Base64 encoded stable binary marshaled bearer token.
swagger:response formBinaryBearerOK
*/
type FormBinaryBearerOK struct {
/*
*/
AccessControlAllowOrigin string `json:"Access-Control-Allow-Origin"`
/*
In: Body
*/
Payload *models.BinaryBearer `json:"body,omitempty"`
}
// NewFormBinaryBearerOK creates FormBinaryBearerOK with default headers values
func NewFormBinaryBearerOK() *FormBinaryBearerOK {
return &FormBinaryBearerOK{}
}
// WithAccessControlAllowOrigin adds the accessControlAllowOrigin to the form binary bearer o k response
func (o *FormBinaryBearerOK) WithAccessControlAllowOrigin(accessControlAllowOrigin string) *FormBinaryBearerOK {
o.AccessControlAllowOrigin = accessControlAllowOrigin
return o
}
// SetAccessControlAllowOrigin sets the accessControlAllowOrigin to the form binary bearer o k response
func (o *FormBinaryBearerOK) SetAccessControlAllowOrigin(accessControlAllowOrigin string) {
o.AccessControlAllowOrigin = accessControlAllowOrigin
}
// WithPayload adds the payload to the form binary bearer o k response
func (o *FormBinaryBearerOK) WithPayload(payload *models.BinaryBearer) *FormBinaryBearerOK {
o.Payload = payload
return o
}
// SetPayload sets the payload to the form binary bearer o k response
func (o *FormBinaryBearerOK) SetPayload(payload *models.BinaryBearer) {
o.Payload = payload
}
// WriteResponse to the client
func (o *FormBinaryBearerOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
// response header Access-Control-Allow-Origin
accessControlAllowOrigin := o.AccessControlAllowOrigin
if accessControlAllowOrigin != "" {
rw.Header().Set("Access-Control-Allow-Origin", accessControlAllowOrigin)
}
rw.WriteHeader(200)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}
// FormBinaryBearerBadRequestCode is the HTTP code returned for type FormBinaryBearerBadRequest
const FormBinaryBearerBadRequestCode int = 400
/*FormBinaryBearerBadRequest Bad request
swagger:response formBinaryBearerBadRequest
*/
type FormBinaryBearerBadRequest struct {
/*
In: Body
*/
Payload *models.ErrorResponse `json:"body,omitempty"`
}
// NewFormBinaryBearerBadRequest creates FormBinaryBearerBadRequest with default headers values
func NewFormBinaryBearerBadRequest() *FormBinaryBearerBadRequest {
return &FormBinaryBearerBadRequest{}
}
// WithPayload adds the payload to the form binary bearer bad request response
func (o *FormBinaryBearerBadRequest) WithPayload(payload *models.ErrorResponse) *FormBinaryBearerBadRequest {
o.Payload = payload
return o
}
// SetPayload sets the payload to the form binary bearer bad request response
func (o *FormBinaryBearerBadRequest) SetPayload(payload *models.ErrorResponse) {
o.Payload = payload
}
// WriteResponse to the client
func (o *FormBinaryBearerBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) {
rw.WriteHeader(400)
if o.Payload != nil {
payload := o.Payload
if err := producer.Produce(rw, payload); err != nil {
panic(err) // let the recovery middleware deal with this
}
}
}

View file

@ -53,6 +53,9 @@ func NewNeofsRestGwAPI(spec *loads.Document) *NeofsRestGwAPI {
DeleteObjectHandler: DeleteObjectHandlerFunc(func(params DeleteObjectParams, principal *models.Principal) middleware.Responder { DeleteObjectHandler: DeleteObjectHandlerFunc(func(params DeleteObjectParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation DeleteObject has not yet been implemented") return middleware.NotImplemented("operation DeleteObject has not yet been implemented")
}), }),
FormBinaryBearerHandler: FormBinaryBearerHandlerFunc(func(params FormBinaryBearerParams, principal *models.Principal) middleware.Responder {
return middleware.NotImplemented("operation FormBinaryBearer has not yet been implemented")
}),
GetBalanceHandler: GetBalanceHandlerFunc(func(params GetBalanceParams) middleware.Responder { GetBalanceHandler: GetBalanceHandlerFunc(func(params GetBalanceParams) middleware.Responder {
return middleware.NotImplemented("operation GetBalance has not yet been implemented") return middleware.NotImplemented("operation GetBalance has not yet been implemented")
}), }),
@ -157,6 +160,8 @@ type NeofsRestGwAPI struct {
DeleteContainerHandler DeleteContainerHandler DeleteContainerHandler DeleteContainerHandler
// DeleteObjectHandler sets the operation handler for the delete object operation // DeleteObjectHandler sets the operation handler for the delete object operation
DeleteObjectHandler DeleteObjectHandler DeleteObjectHandler DeleteObjectHandler
// FormBinaryBearerHandler sets the operation handler for the form binary bearer operation
FormBinaryBearerHandler FormBinaryBearerHandler
// GetBalanceHandler sets the operation handler for the get balance operation // GetBalanceHandler sets the operation handler for the get balance operation
GetBalanceHandler GetBalanceHandler GetBalanceHandler GetBalanceHandler
// GetContainerHandler sets the operation handler for the get container operation // GetContainerHandler sets the operation handler for the get container operation
@ -279,6 +284,9 @@ func (o *NeofsRestGwAPI) Validate() error {
if o.DeleteObjectHandler == nil { if o.DeleteObjectHandler == nil {
unregistered = append(unregistered, "DeleteObjectHandler") unregistered = append(unregistered, "DeleteObjectHandler")
} }
if o.FormBinaryBearerHandler == nil {
unregistered = append(unregistered, "FormBinaryBearerHandler")
}
if o.GetBalanceHandler == nil { if o.GetBalanceHandler == nil {
unregistered = append(unregistered, "GetBalanceHandler") unregistered = append(unregistered, "GetBalanceHandler")
} }
@ -441,6 +449,10 @@ func (o *NeofsRestGwAPI) initHandlerCache() {
if o.handlers["GET"] == nil { if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler) o.handlers["GET"] = make(map[string]http.Handler)
} }
o.handlers["GET"]["/auth/bearer"] = NewFormBinaryBearer(o.context, o.FormBinaryBearerHandler)
if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler)
}
o.handlers["GET"]["/accounting/balance/{address}"] = NewGetBalance(o.context, o.GetBalanceHandler) o.handlers["GET"]["/accounting/balance/{address}"] = NewGetBalance(o.context, o.GetBalanceHandler)
if o.handlers["GET"] == nil { if o.handlers["GET"] == nil {
o.handlers["GET"] = make(map[string]http.Handler) o.handlers["GET"] = make(map[string]http.Handler)

View file

@ -98,6 +98,8 @@ func (a *API) Configure(api *operations.NeofsRestGwAPI) http.Handler {
api.OptionsAuthHandler = operations.OptionsAuthHandlerFunc(a.OptionsAuth) api.OptionsAuthHandler = operations.OptionsAuthHandlerFunc(a.OptionsAuth)
api.AuthHandler = operations.AuthHandlerFunc(a.PostAuth) api.AuthHandler = operations.AuthHandlerFunc(a.PostAuth)
api.FormBinaryBearerHandler = operations.FormBinaryBearerHandlerFunc(a.FormBinaryBearer)
api.GetBalanceHandler = operations.GetBalanceHandlerFunc(a.Balance) api.GetBalanceHandler = operations.GetBalanceHandlerFunc(a.Balance)
api.OptionsObjectsPutHandler = operations.OptionsObjectsPutHandlerFunc(a.OptionsObjectsPut) api.OptionsObjectsPutHandler = operations.OptionsObjectsPutHandlerFunc(a.OptionsObjectsPut)

View file

@ -102,6 +102,21 @@ func (a *API) PostAuth(params operations.AuthParams) middleware.Responder {
WithAccessControlAllowOrigin("*") WithAccessControlAllowOrigin("*")
} }
// FormBinaryBearer handler that forms binary bearer token using headers with body and signature.
func (a *API) FormBinaryBearer(params operations.FormBinaryBearerParams, principal *models.Principal) middleware.Responder {
btoken, err := getBearerToken(principal, params.XBearerSignature, params.XBearerSignatureKey, *params.WalletConnect)
if err != nil {
resp := a.logAndGetErrorResponse("invalid bearer token", err)
return operations.NewFormBinaryBearerBadRequest().WithPayload(resp)
}
resp := &models.BinaryBearer{
Token: util.NewString(base64.StdEncoding.EncodeToString(btoken.Marshal())),
}
return operations.NewFormBinaryBearerOK().WithPayload(resp)
}
func prepareObjectToken(ctx context.Context, params objectTokenParams, pool *pool.Pool, owner user.ID) (*models.TokenResponse, error) { func prepareObjectToken(ctx context.Context, params objectTokenParams, pool *pool.Pool, owner user.ID) (*models.TokenResponse, error) {
btoken, err := util.ToNativeObjectToken(params.Records) btoken, err := util.ToNativeObjectToken(params.Records)
if err != nil { if err != nil {

View file

@ -7,6 +7,7 @@ import (
"crypto/sha512" "crypto/sha512"
"encoding/base64" "encoding/base64"
"encoding/hex" "encoding/hex"
"fmt"
"math" "math"
"testing" "testing"
@ -14,6 +15,8 @@ import (
"github.com/nspcc-dev/neofs-api-go/v2/acl" "github.com/nspcc-dev/neofs-api-go/v2/acl"
"github.com/nspcc-dev/neofs-rest-gw/gen/models" "github.com/nspcc-dev/neofs-rest-gw/gen/models"
"github.com/nspcc-dev/neofs-rest-gw/internal/util" "github.com/nspcc-dev/neofs-rest-gw/internal/util"
"github.com/nspcc-dev/neofs-sdk-go/bearer"
"github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/user" "github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -70,3 +73,31 @@ func TestSign(t *testing.T) {
_, err = prepareBearerToken(bt, false) _, err = prepareBearerToken(bt, false)
require.NoError(t, err) require.NoError(t, err)
} }
func TestName(t *testing.T) {
//bt := "Cq4BCokBCgASIgog1WV5EUB4P+vBDntpIRfpfqU9vFbfqYCLVQxeGiN4We4aVwgDEAEaTQgCEAEaBUVtYWlsIkA2NGJhM2FkNDdjYmVlNWY1Mjg4ZTZjOTZiNWUwNjg1NjZmMzM2MGMyOGIyODNiN2M2NmM0MmFiZTczNTFjNDQ5IgIIAxoICAMQAiICCAMSGwoZNaq5pfYuroaGE7h9o5iQsPR/1aRe5gmWrhoDCLcGEmYKIQMabG+73wLKNRdF+oa5ulqUUteFrE9/wrdUjKKkbE/PShJBBEGKRnVy4jfvBuNMspDwI6/fynIkqql4p+wKe/BgOKgDFkX83h6Q13J8eakV4RzZR+31JLgyM37GVp57ndZk9w4="
//
//btRaw, err := base64.StdEncoding.DecodeString(bt)
//require.NoError(t, err)
key, err := keys.NewPrivateKey()
require.NoError(t, err)
var btoken bearer.Token
var table eacl.Table
var r eacl.Record
r.SetAction(eacl.ActionAllow)
r.SetOperation(eacl.OperationGet)
eacl.AddFormedTarget(&r, eacl.RoleOthers)
table.AddRecord(&r)
btoken.SetExp(100)
btoken.SetEACLTable(table)
err = btoken.Sign(key.PrivateKey)
require.NoError(t, err)
bytes := btoken.Marshal()
fmt.Println(base64.StdEncoding.EncodeToString(bytes))
}

View file

@ -93,7 +93,7 @@ paths:
- application/json - application/json
responses: responses:
200: 200:
description: Base64 encoded stable binary marshaled bearer token. description: Base64 encoded stable binary marshaled bearer token bodies.
headers: headers:
Access-Control-Allow-Origin: Access-Control-Allow-Origin:
type: string type: string
@ -106,6 +106,29 @@ paths:
schema: schema:
$ref: '#/definitions/ErrorResponse' $ref: '#/definitions/ErrorResponse'
/auth/bearer:
get:
operationId: formBinaryBearer
summary: Form binary bearer token
parameters:
- $ref: '#/parameters/signatureParam'
- $ref: '#/parameters/signatureKeyParam'
- $ref: '#/parameters/signatureScheme'
produces:
- application/json
responses:
200:
description: Base64 encoded stable binary marshaled bearer token.
headers:
Access-Control-Allow-Origin:
type: string
schema:
$ref: '#/definitions/BinaryBearer'
400:
description: Bad request
schema:
$ref: '#/definitions/ErrorResponse'
/accounting/balance/{address}: /accounting/balance/{address}:
get: get:
operationId: getBalance operationId: getBalance
@ -503,6 +526,17 @@ paths:
$ref: '#/definitions/ErrorResponse' $ref: '#/definitions/ErrorResponse'
definitions: definitions:
BinaryBearer:
description: Bearer token for object operations that is represented in binary form.
type: object
properties:
token:
description: Base64 encoded bearer token.
type: string
required:
- token
example:
token: ChIKDAoAGggIARABIgIIAxoCCGQSZgohA+J5jFWFMiOpyvMZBu9wwPTKsWsG0q206kVe63iuWP/wEkEE4SIV0QngnKppDf54QezUKmar7UQby6HzufT5yVIOvj7QEqZnOavrKW0chCeCwP0khda/j9k00ct6NMEDxQFW+g==
Bearer: Bearer:
description: Bearer token that is expected to be formed. description: Bearer token that is expected to be formed.
type: object type: object