mirror of
https://github.com/gravitl/netmaker.git
synced 2024-09-20 15:26:04 +08:00
added host pull model, made API
This commit is contained in:
parent
d3a7e704f2
commit
63eac1e79c
|
@ -1,6 +1,7 @@
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -26,6 +27,7 @@ func hostHandlers(r *mux.Router) {
|
||||||
r.HandleFunc("/api/hosts/{hostid}/relay", logic.SecurityCheck(false, http.HandlerFunc(createHostRelay))).Methods(http.MethodPost)
|
r.HandleFunc("/api/hosts/{hostid}/relay", logic.SecurityCheck(false, http.HandlerFunc(createHostRelay))).Methods(http.MethodPost)
|
||||||
r.HandleFunc("/api/hosts/{hostid}/relay", logic.SecurityCheck(false, http.HandlerFunc(deleteHostRelay))).Methods(http.MethodDelete)
|
r.HandleFunc("/api/hosts/{hostid}/relay", logic.SecurityCheck(false, http.HandlerFunc(deleteHostRelay))).Methods(http.MethodDelete)
|
||||||
r.HandleFunc("/api/hosts/adm/authenticate", authenticateHost).Methods(http.MethodPost)
|
r.HandleFunc("/api/hosts/adm/authenticate", authenticateHost).Methods(http.MethodPost)
|
||||||
|
r.HandleFunc("/api/v1/host", authorize(true, false, "host", http.HandlerFunc(pull))).Methods(http.MethodGet)
|
||||||
}
|
}
|
||||||
|
|
||||||
// swagger:route GET /api/hosts hosts getHosts
|
// swagger:route GET /api/hosts hosts getHosts
|
||||||
|
@ -53,6 +55,53 @@ func getHosts(w http.ResponseWriter, r *http.Request) {
|
||||||
json.NewEncoder(w).Encode(apiHosts)
|
json.NewEncoder(w).Encode(apiHosts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// swagger:route GET /api/v1/host pull pullHost
|
||||||
|
//
|
||||||
|
// Used by clients for "pull" command
|
||||||
|
//
|
||||||
|
// Schemes: https
|
||||||
|
//
|
||||||
|
// Security:
|
||||||
|
// oauth
|
||||||
|
//
|
||||||
|
// Responses:
|
||||||
|
// 200: pull
|
||||||
|
func pull(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
hostID := r.Header.Get(hostIDHeader) // return JSON/API formatted keys
|
||||||
|
if len(hostID) == 0 {
|
||||||
|
logger.Log(0, "no host authorized to pull")
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(fmt.Errorf("no host authorized to pull"), "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
host, err := logic.GetHost(hostID)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(0, "no host found during pull", hostID)
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hPU, err := logic.GetPeerUpdateForHost(context.Background(), "", host, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
logger.Log(0, "could not pull peers for host", hostID)
|
||||||
|
logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
serverConf := servercfg.GetServerInfo()
|
||||||
|
if servercfg.GetBrokerType() == servercfg.EmqxBrokerType {
|
||||||
|
serverConf.MQUserName = hostID
|
||||||
|
}
|
||||||
|
response := models.HostPull{
|
||||||
|
Host: *host,
|
||||||
|
ServerConfig: serverConf,
|
||||||
|
Peers: hPU.Peers,
|
||||||
|
PeerIDs: hPU.PeerIDs,
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Log(1, hostID, "completed a pull")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(&response)
|
||||||
|
}
|
||||||
|
|
||||||
// swagger:route PUT /api/hosts/{hostid} hosts updateHost
|
// swagger:route PUT /api/hosts/{hostid} hosts updateHost
|
||||||
//
|
//
|
||||||
// Updates a Netclient host on Netmaker server.
|
// Updates a Netclient host on Netmaker server.
|
||||||
|
|
|
@ -19,6 +19,8 @@ import (
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var hostIDHeader = "host-id"
|
||||||
|
|
||||||
func nodeHandlers(r *mux.Router) {
|
func nodeHandlers(r *mux.Router) {
|
||||||
|
|
||||||
r.HandleFunc("/api/nodes", authorize(false, false, "user", http.HandlerFunc(getAllNodes))).Methods(http.MethodGet)
|
r.HandleFunc("/api/nodes", authorize(false, false, "user", http.HandlerFunc(getAllNodes))).Methods(http.MethodGet)
|
||||||
|
@ -152,7 +154,7 @@ func authenticate(response http.ResponseWriter, request *http.Request) {
|
||||||
// even if it's technically ok
|
// even if it's technically ok
|
||||||
// This is kind of a poor man's RBAC. There's probably a better/smarter way.
|
// This is kind of a poor man's RBAC. There's probably a better/smarter way.
|
||||||
// TODO: Consider better RBAC implementations
|
// TODO: Consider better RBAC implementations
|
||||||
func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Handler) http.HandlerFunc {
|
func authorize(hostAllowed, networkCheck bool, authNetwork string, next http.Handler) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var errorResponse = models.ErrorResponse{
|
var errorResponse = models.ErrorResponse{
|
||||||
Code: http.StatusUnauthorized, Message: logic.Unauthorized_Msg,
|
Code: http.StatusUnauthorized, Message: logic.Unauthorized_Msg,
|
||||||
|
@ -184,11 +186,11 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
||||||
logic.ReturnErrorResponse(w, r, errorResponse)
|
logic.ReturnErrorResponse(w, r, errorResponse)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//check if node instead of user
|
// check if host instead of user
|
||||||
if nodesAllowed {
|
if hostAllowed {
|
||||||
// TODO --- should ensure that node is only operating on itself
|
// TODO --- should ensure that node is only operating on itself
|
||||||
if _, _, _, err := logic.VerifyToken(authToken); err == nil {
|
if hostID, _, _, err := logic.VerifyHostToken(authToken); err == nil {
|
||||||
|
r.Header.Set(hostIDHeader, hostID)
|
||||||
// this indicates request is from a node
|
// this indicates request is from a node
|
||||||
// used for failover - if a getNode comes from node, this will trigger a metrics wipe
|
// used for failover - if a getNode comes from node, this will trigger a metrics wipe
|
||||||
next.ServeHTTP(w, r)
|
next.ServeHTTP(w, r)
|
||||||
|
@ -244,6 +246,7 @@ func authorize(nodesAllowed, networkCheck bool, authNetwork string, next http.Ha
|
||||||
} else {
|
} else {
|
||||||
isAuthorized = (nodeID == params["netid"])
|
isAuthorized = (nodeID == params["netid"])
|
||||||
}
|
}
|
||||||
|
case "host":
|
||||||
case "user":
|
case "user":
|
||||||
isAuthorized = true
|
isAuthorized = true
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -129,8 +129,8 @@ func VerifyUserToken(tokenString string) (username string, networks []string, is
|
||||||
return "", nil, false, err
|
return "", nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyToken - [nodes] Only
|
// VerifyHostToken - [hosts] Only
|
||||||
func VerifyToken(tokenString string) (hostID string, mac string, network string, err error) {
|
func VerifyHostToken(tokenString string) (hostID string, mac string, network string, err error) {
|
||||||
claims := &models.Claims{}
|
claims := &models.Claims{}
|
||||||
|
|
||||||
// this may be a stupid way of serving up a master key
|
// this may be a stupid way of serving up a master key
|
||||||
|
|
|
@ -198,6 +198,14 @@ type TrafficKeys struct {
|
||||||
Server []byte `json:"server" bson:"server" yaml:"server"`
|
Server []byte `json:"server" bson:"server" yaml:"server"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HostPull - response of a host's pull
|
||||||
|
type HostPull struct {
|
||||||
|
Host Host `json:"host" yaml:"host"`
|
||||||
|
Peers []wgtypes.PeerConfig `json:"peers" yaml:"peers"`
|
||||||
|
ServerConfig ServerConfig `json:"server_config" yaml:"server_config"`
|
||||||
|
PeerIDs PeerMap `json:"peer_ids,omitempty" yaml:"peer_ids,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// NodeGet - struct for a single node get response
|
// NodeGet - struct for a single node get response
|
||||||
type NodeGet struct {
|
type NodeGet struct {
|
||||||
Node Node `json:"node" bson:"node" yaml:"node"`
|
Node Node `json:"node" bson:"node" yaml:"node"`
|
||||||
|
|
Loading…
Reference in a new issue