Fixed node pairing
This commit is contained in:
@@ -129,7 +129,7 @@ endpoints:
|
||||
parameters:
|
||||
path: [ { name: nodeID, type: uint64, required: true, title: NodeID } ]
|
||||
post:
|
||||
- name: tokenA
|
||||
- name: authToken
|
||||
type: string
|
||||
required: true
|
||||
title: Node A token
|
||||
|
||||
@@ -2,6 +2,7 @@ package rest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/federation/rest/request"
|
||||
"github.com/cortezaproject/corteza-server/federation/service"
|
||||
"github.com/cortezaproject/corteza-server/federation/types"
|
||||
@@ -103,7 +104,7 @@ func (ctrl Node) HandshakeConfirm(ctx context.Context, r *request.NodeHandshakeC
|
||||
}
|
||||
|
||||
func (ctrl Node) HandshakeComplete(ctx context.Context, r *request.NodeHandshakeComplete) (interface{}, error) {
|
||||
return api.OK(), ctrl.svcNode.HandshakeComplete(ctx, r.NodeID, r.TokenA)
|
||||
return api.OK(), ctrl.svcNode.HandshakeComplete(ctx, r.NodeID, r.AuthToken)
|
||||
}
|
||||
|
||||
func (ctrl Node) makePayload(ctx context.Context, m *types.Node, err error) (*nodePayload, error) {
|
||||
|
||||
@@ -123,10 +123,10 @@ type (
|
||||
// NodeID
|
||||
NodeID uint64 `json:",string"`
|
||||
|
||||
// TokenA POST parameter
|
||||
// AuthToken POST parameter
|
||||
//
|
||||
// Node A token
|
||||
TokenA string
|
||||
AuthToken string
|
||||
}
|
||||
)
|
||||
|
||||
@@ -618,8 +618,8 @@ func NewNodeHandshakeComplete() *NodeHandshakeComplete {
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r NodeHandshakeComplete) Auditable() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"nodeID": r.NodeID,
|
||||
"tokenA": r.TokenA,
|
||||
"nodeID": r.NodeID,
|
||||
"authToken": r.AuthToken,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,8 +629,8 @@ func (r NodeHandshakeComplete) GetNodeID() uint64 {
|
||||
}
|
||||
|
||||
// Auditable returns all auditable/loggable parameters
|
||||
func (r NodeHandshakeComplete) GetTokenA() string {
|
||||
return r.TokenA
|
||||
func (r NodeHandshakeComplete) GetAuthToken() string {
|
||||
return r.AuthToken
|
||||
}
|
||||
|
||||
// Fill processes request and fills internal variables
|
||||
@@ -653,8 +653,8 @@ func (r *NodeHandshakeComplete) Fill(req *http.Request) (err error) {
|
||||
|
||||
// POST params
|
||||
|
||||
if val, ok := req.Form["tokenA"]; ok && len(val) > 0 {
|
||||
r.TokenA, err = val[0], nil
|
||||
if val, ok := req.Form["authToken"]; ok && len(val) > 0 {
|
||||
r.AuthToken, err = val[0], nil
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -53,13 +53,8 @@ func Node(s store.Storer, u service.UserService, al actionlog.Recorder, th auth.
|
||||
sysUser: u,
|
||||
actionlog: al,
|
||||
tokenEncoder: th,
|
||||
|
||||
// name of this node
|
||||
// @todo read this from settings
|
||||
name: "Server A",
|
||||
|
||||
// @todo read this from settings
|
||||
host: options.Host,
|
||||
name: options.Label,
|
||||
host: options.Host,
|
||||
|
||||
// @todo use HTTP_API_BASE_URL (HTTPServerOpt.ApiBaseUrl) to prefix URI path
|
||||
baseURL: "/federation",
|
||||
@@ -267,7 +262,7 @@ func (svc node) Pair(ctx context.Context, nodeID uint64) error {
|
||||
func (svc node) HandshakeInit(ctx context.Context, nodeID uint64, pairToken string, sharedNodeID uint64, authToken string) error {
|
||||
_, err := svc.updater(
|
||||
ctx,
|
||||
nodeID,
|
||||
sharedNodeID,
|
||||
NodeActionHandshakeInit,
|
||||
func(ctx context.Context, n *types.Node) error {
|
||||
// @todo need to check node status before we can proceed with initialization
|
||||
@@ -320,15 +315,25 @@ func (svc node) HandshakeConfirm(ctx context.Context, nodeID uint64) error {
|
||||
}
|
||||
|
||||
// HandshakeComplete is used by server B to handle handshake confirmation
|
||||
func (svc node) HandshakeComplete(ctx context.Context, nodeID uint64, token string) error {
|
||||
_, err := svc.updater(ctx, nodeID, NodeActionHandshakeComplete, func(ctx context.Context, n *types.Node) error {
|
||||
n.Status = types.NodeStatusPaired
|
||||
func (svc node) HandshakeComplete(ctx context.Context, sharedNodeID uint64, token string) error {
|
||||
var (
|
||||
n *types.Node
|
||||
err error
|
||||
)
|
||||
|
||||
if n, err = store.LookupFederationNodeBySharedNodeID(ctx, svc.store, sharedNodeID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = svc.updater(ctx, n.ID, NodeActionHandshakeComplete, func(ctx context.Context, n *types.Node) error {
|
||||
n.AuthToken = token
|
||||
n.Status = types.NodeStatusPaired
|
||||
n.UpdatedBy = auth.GetIdentityFromContext(ctx).Identity()
|
||||
n.UpdatedAt = now()
|
||||
|
||||
return nil
|
||||
}, nil)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -437,7 +442,7 @@ func (node) decodePairingURI(uri string) (*types.Node, error) {
|
||||
}
|
||||
|
||||
n.Name = parsedURI.Query().Get("name")
|
||||
n.BaseURL = fmt.Sprintf("https://%s/%s", parsedURI.Host, strings.Trim(parsedURI.Path, "/"))
|
||||
n.BaseURL = fmt.Sprintf("%s://%s/%s", parsedURI.Scheme, parsedURI.Host, strings.Trim(parsedURI.Path, "/"))
|
||||
return nil
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/cortezaproject/corteza-server/federation/types"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/federation/types"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -40,7 +41,7 @@ func (h httpNodeHandshake) Init(ctx context.Context, n *types.Node, authToken st
|
||||
|
||||
// Share auth token for the federation service user for this node
|
||||
"authToken": authToken,
|
||||
"sharedNodeID": strconv.FormatUint(n.ID, 10),
|
||||
"sharedNodeID": strconv.FormatUint(n.SharedNodeID, 10),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -60,6 +61,9 @@ func (h httpNodeHandshake) Complete(ctx context.Context, n *types.Node, authToke
|
||||
}
|
||||
)
|
||||
|
||||
// use n.AuthToken in context
|
||||
ctx = context.WithValue(ctx, "authToken", n.AuthToken)
|
||||
|
||||
return h.send(ctx, endpoint, payload)
|
||||
}
|
||||
|
||||
@@ -74,6 +78,12 @@ func (h httpNodeHandshake) send(ctx context.Context, endpoint string, payload ma
|
||||
return err
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
if authToken := ctx.Value("authToken"); authToken != nil {
|
||||
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", authToken))
|
||||
}
|
||||
|
||||
rsp, err := h.httpClient.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -3,6 +3,7 @@ package options
|
||||
type (
|
||||
FederationOpt struct {
|
||||
Enabled bool `env:"FEDERATION_ENABLED"`
|
||||
Label string `env:"FEDERATION_LABEL"`
|
||||
Host string `env:"FEDERATION_HOST"`
|
||||
}
|
||||
)
|
||||
@@ -11,6 +12,7 @@ func Federation() (o *FederationOpt) {
|
||||
|
||||
o = &FederationOpt{
|
||||
Enabled: false,
|
||||
Label: `Example host`,
|
||||
Host: `example.tld`,
|
||||
}
|
||||
|
||||
|
||||
@@ -3,10 +3,13 @@ package federation
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/app"
|
||||
"github.com/cortezaproject/corteza-server/federation/rest"
|
||||
"github.com/cortezaproject/corteza-server/federation/service"
|
||||
"github.com/cortezaproject/corteza-server/pkg/api"
|
||||
"github.com/cortezaproject/corteza-server/pkg/api/server"
|
||||
"github.com/cortezaproject/corteza-server/pkg/auth"
|
||||
"github.com/cortezaproject/corteza-server/pkg/cli"
|
||||
"github.com/cortezaproject/corteza-server/pkg/eventbus"
|
||||
@@ -20,8 +23,6 @@ import (
|
||||
"github.com/steinfletcher/apitest"
|
||||
"github.com/stretchr/testify/require"
|
||||
"go.uber.org/zap"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -60,7 +61,7 @@ func InitTestApp() {
|
||||
|
||||
if r == nil {
|
||||
r = chi.NewRouter()
|
||||
r.Use(api.BaseMiddleware(logger.Default())...)
|
||||
r.Use(server.BaseMiddleware(false, logger.Default())...)
|
||||
helpers.BindAuthMiddleware(r)
|
||||
rest.MountRoutes(r)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user