forked from TrueCloudLab/frostfs-rest-gw
[#3] Use owner id to auth
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
d5d5ef211f
commit
d48a7b6f66
8 changed files with 55 additions and 44 deletions
|
@ -2,7 +2,7 @@ FROM golang:1.17 as basebuilder
|
||||||
|
|
||||||
RUN set -x \
|
RUN set -x \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install -y make
|
&& apt-get install -y make jq
|
||||||
|
|
||||||
FROM basebuilder as builder
|
FROM basebuilder as builder
|
||||||
ENV GOGC off
|
ENV GOGC off
|
||||||
|
|
|
@ -25,13 +25,14 @@ 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-rest-gw/internal/wallet-connect"
|
walletconnect "github.com/nspcc-dev/neofs-rest-gw/internal/wallet-connect"
|
||||||
"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"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
"github.com/nspcc-dev/neofs-sdk-go/eacl"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object"
|
"github.com/nspcc-dev/neofs-sdk-go/object"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object/address"
|
"github.com/nspcc-dev/neofs-sdk-go/object/address"
|
||||||
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/policy"
|
"github.com/nspcc-dev/neofs-sdk-go/policy"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/pool"
|
"github.com/nspcc-dev/neofs-sdk-go/pool"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
@ -54,11 +55,13 @@ const (
|
||||||
XBearerSignature = "X-Bearer-Signature"
|
XBearerSignature = "X-Bearer-Signature"
|
||||||
// XBearerSignatureKey header contains hex encoded public key that corresponds the signature of the token body.
|
// XBearerSignatureKey header contains hex encoded public key that corresponds the signature of the token body.
|
||||||
XBearerSignatureKey = "X-Bearer-Signature-Key"
|
XBearerSignatureKey = "X-Bearer-Signature-Key"
|
||||||
|
// XBearerOwnerID header contains owner id (wallet address) that corresponds the signature of the token body.
|
||||||
|
XBearerOwnerID = "X-Bearer-Owner-Id"
|
||||||
// XBearerScope header contains operation scope for auth (bearer) token.
|
// XBearerScope header contains operation scope for auth (bearer) token.
|
||||||
// It corresponds to 'object' or 'container' services in neofs.
|
// It corresponds to 'object' or 'container' services in neofs.
|
||||||
XBearerScope = "X-Bearer-Scope"
|
XBearerScope = "X-Bearer-Scope"
|
||||||
|
|
||||||
// configuration tests
|
// tests configuration.
|
||||||
useWalletConnect = false
|
useWalletConnect = false
|
||||||
useLocalEnvironment = false
|
useLocalEnvironment = false
|
||||||
)
|
)
|
||||||
|
@ -86,7 +89,8 @@ func runTestInContainer(rootCtx context.Context, t *testing.T, key *keys.Private
|
||||||
//"0.25.1",
|
//"0.25.1",
|
||||||
//"0.26.1",
|
//"0.26.1",
|
||||||
//"0.27.5",
|
//"0.27.5",
|
||||||
"latest",
|
"0.27.7",
|
||||||
|
//"latest",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, version := range versions {
|
for _, version := range versions {
|
||||||
|
@ -682,7 +686,7 @@ func makeAuthTokenRequest(ctx context.Context, t *testing.T, bearer *models.Bear
|
||||||
key, err := keys.NewPrivateKeyFromHex(devenvPrivateKey)
|
key, err := keys.NewPrivateKeyFromHex(devenvPrivateKey)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
hexPubKey := hex.EncodeToString(key.PublicKey().Bytes())
|
ownerID := owner.NewIDFromPublicKey((*ecdsa.PublicKey)(key.PublicKey()))
|
||||||
|
|
||||||
data, err := json.Marshal(bearer)
|
data, err := json.Marshal(bearer)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -692,7 +696,7 @@ func makeAuthTokenRequest(ctx context.Context, t *testing.T, bearer *models.Bear
|
||||||
request = request.WithContext(ctx)
|
request = request.WithContext(ctx)
|
||||||
request.Header.Add("Content-Type", "application/json")
|
request.Header.Add("Content-Type", "application/json")
|
||||||
request.Header.Add(XBearerScope, string(tokenType))
|
request.Header.Add(XBearerScope, string(tokenType))
|
||||||
request.Header.Add(XBearerSignatureKey, hexPubKey)
|
request.Header.Add(XBearerOwnerID, ownerID.String())
|
||||||
|
|
||||||
resp, err := httpClient.Do(request)
|
resp, err := httpClient.Do(request)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -43,7 +43,11 @@ func init() {
|
||||||
"operationId": "auth",
|
"operationId": "auth",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"$ref": "#/parameters/signatureKeyParam"
|
"type": "string",
|
||||||
|
"description": "Owner Id (wallet address) that will sign the token",
|
||||||
|
"name": "X-Bearer-Owner-Id",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"enum": [
|
"enum": [
|
||||||
|
@ -1094,8 +1098,8 @@ func init() {
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Hex encoded the public part of the key that signed the bearer token",
|
"description": "Owner Id (wallet address) that will sign the token",
|
||||||
"name": "X-Bearer-Signature-Key",
|
"name": "X-Bearer-Owner-Id",
|
||||||
"in": "header",
|
"in": "header",
|
||||||
"required": true
|
"required": true
|
||||||
},
|
},
|
||||||
|
|
|
@ -49,16 +49,16 @@ type AuthParams struct {
|
||||||
Default: 100
|
Default: 100
|
||||||
*/
|
*/
|
||||||
XBearerLifetime *int64
|
XBearerLifetime *int64
|
||||||
|
/*Owner Id (wallet address) that will sign the token
|
||||||
|
Required: true
|
||||||
|
In: header
|
||||||
|
*/
|
||||||
|
XBearerOwnerID string
|
||||||
/*Supported operation scope for token
|
/*Supported operation scope for token
|
||||||
Required: true
|
Required: true
|
||||||
In: header
|
In: header
|
||||||
*/
|
*/
|
||||||
XBearerScope string
|
XBearerScope string
|
||||||
/*Hex encoded the public part of the key that signed the bearer token
|
|
||||||
Required: true
|
|
||||||
In: header
|
|
||||||
*/
|
|
||||||
XBearerSignatureKey string
|
|
||||||
/*Bearer token
|
/*Bearer token
|
||||||
Required: true
|
Required: true
|
||||||
In: body
|
In: body
|
||||||
|
@ -79,11 +79,11 @@ func (o *AuthParams) BindRequest(r *http.Request, route *middleware.MatchedRoute
|
||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := o.bindXBearerScope(r.Header[http.CanonicalHeaderKey("X-Bearer-Scope")], true, route.Formats); err != nil {
|
if err := o.bindXBearerOwnerID(r.Header[http.CanonicalHeaderKey("X-Bearer-Owner-Id")], true, route.Formats); err != nil {
|
||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := o.bindXBearerSignatureKey(r.Header[http.CanonicalHeaderKey("X-Bearer-Signature-Key")], true, route.Formats); err != nil {
|
if err := o.bindXBearerScope(r.Header[http.CanonicalHeaderKey("X-Bearer-Scope")], true, route.Formats); err != nil {
|
||||||
res = append(res, err)
|
res = append(res, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +143,26 @@ func (o *AuthParams) bindXBearerLifetime(rawData []string, hasKey bool, formats
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bindXBearerOwnerID binds and validates parameter XBearerOwnerID from header.
|
||||||
|
func (o *AuthParams) bindXBearerOwnerID(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
|
if !hasKey {
|
||||||
|
return errors.Required("X-Bearer-Owner-Id", "header", rawData)
|
||||||
|
}
|
||||||
|
var raw string
|
||||||
|
if len(rawData) > 0 {
|
||||||
|
raw = rawData[len(rawData)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required: true
|
||||||
|
|
||||||
|
if err := validate.RequiredString("X-Bearer-Owner-Id", "header", raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.XBearerOwnerID = raw
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// bindXBearerScope binds and validates parameter XBearerScope from header.
|
// bindXBearerScope binds and validates parameter XBearerScope from header.
|
||||||
func (o *AuthParams) bindXBearerScope(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
func (o *AuthParams) bindXBearerScope(rawData []string, hasKey bool, formats strfmt.Registry) error {
|
||||||
if !hasKey {
|
if !hasKey {
|
||||||
|
@ -176,23 +196,3 @@ func (o *AuthParams) validateXBearerScope(formats strfmt.Registry) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// bindXBearerSignatureKey binds and validates parameter XBearerSignatureKey from header.
|
|
||||||
func (o *AuthParams) 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
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
@ -72,9 +71,9 @@ func prepareContainerTokens(params operations.AuthParams, pool *pool.Pool, key *
|
||||||
return nil, fmt.Errorf("couldn't get lifetime: %w", err)
|
return nil, fmt.Errorf("couldn't get lifetime: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ownerKey, err := keys.NewPublicKeyFromString(params.XBearerSignatureKey)
|
var ownerID owner.ID
|
||||||
if err != nil {
|
if err = ownerID.Parse(params.XBearerOwnerID); err != nil {
|
||||||
return nil, fmt.Errorf("invalid singature key: %w", err)
|
return nil, fmt.Errorf("invalid bearer owner: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp models.TokenResponse
|
var resp models.TokenResponse
|
||||||
|
@ -91,7 +90,7 @@ func prepareContainerTokens(params operations.AuthParams, pool *pool.Pool, key *
|
||||||
}
|
}
|
||||||
stoken.SetID(uid)
|
stoken.SetID(uid)
|
||||||
|
|
||||||
stoken.SetOwnerID(owner.NewIDFromPublicKey((*ecdsa.PublicKey)(ownerKey)))
|
stoken.SetOwnerID(&ownerID)
|
||||||
|
|
||||||
stoken.SetIat(iat)
|
stoken.SetIat(iat)
|
||||||
stoken.SetExp(exp)
|
stoken.SetExp(exp)
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"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/gen/restapi/operations"
|
"github.com/nspcc-dev/neofs-rest-gw/gen/restapi/operations"
|
||||||
"github.com/nspcc-dev/neofs-rest-gw/internal/util"
|
"github.com/nspcc-dev/neofs-rest-gw/internal/util"
|
||||||
"github.com/nspcc-dev/neofs-rest-gw/internal/wallet-connect"
|
walletconnect "github.com/nspcc-dev/neofs-rest-gw/internal/wallet-connect"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/acl"
|
"github.com/nspcc-dev/neofs-sdk-go/acl"
|
||||||
"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"
|
||||||
|
|
|
@ -15,7 +15,7 @@ import (
|
||||||
"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/gen/restapi/operations"
|
"github.com/nspcc-dev/neofs-rest-gw/gen/restapi/operations"
|
||||||
"github.com/nspcc-dev/neofs-rest-gw/internal/util"
|
"github.com/nspcc-dev/neofs-rest-gw/internal/util"
|
||||||
"github.com/nspcc-dev/neofs-rest-gw/internal/wallet-connect"
|
walletconnect "github.com/nspcc-dev/neofs-rest-gw/internal/wallet-connect"
|
||||||
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"
|
||||||
"github.com/nspcc-dev/neofs-sdk-go/object/address"
|
"github.com/nspcc-dev/neofs-sdk-go/object/address"
|
||||||
|
|
|
@ -59,7 +59,11 @@ paths:
|
||||||
summary: Form bearer token to futher requests
|
summary: Form bearer token to futher requests
|
||||||
security: [ ]
|
security: [ ]
|
||||||
parameters:
|
parameters:
|
||||||
- $ref: '#/parameters/signatureKeyParam'
|
- in: header
|
||||||
|
name: X-Bearer-Owner-Id
|
||||||
|
description: Owner Id (wallet address) that will sign the token
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
- in: header
|
- in: header
|
||||||
description: Supported operation scope for token
|
description: Supported operation scope for token
|
||||||
name: X-Bearer-Scope
|
name: X-Bearer-Scope
|
||||||
|
|
Loading…
Reference in a new issue