mirror of
https://github.com/gravitl/netmaker.git
synced 2025-10-06 17:29:15 +08:00
adding extclient functionality
This commit is contained in:
@@ -58,6 +58,49 @@ func GetPeersList(networkName string) ([]models.PeersResponse, error) {
|
|||||||
return peers, err
|
return peers, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetExtPeersList(networkName string, macaddress string) ([]models.ExtPeersResponse, error) {
|
||||||
|
|
||||||
|
var peers []models.ExtPeersResponse
|
||||||
|
|
||||||
|
//Connection mongoDB with mongoconn class
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
|
//Get all nodes in the relevant network which are NOT in pending state
|
||||||
|
filter := bson.M{"network": networkName, "gatewayid": macaddress}
|
||||||
|
cur, err := collection.Find(ctx, filter)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the cursor once finished and cancel if it takes too long
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
for cur.Next(context.TODO()) {
|
||||||
|
|
||||||
|
var peer models.ExtPeersResponse
|
||||||
|
err := cur.Decode(&peer)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the node to our node array
|
||||||
|
//maybe better to just return this? But then that's just GetNodes...
|
||||||
|
peers = append(peers, peer)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Uh oh, fatal error! This needs some better error handling
|
||||||
|
//TODO: needs appropriate error handling so the server doesnt shut down.
|
||||||
|
if err := cur.Err(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func ValidateNodeCreate(networkName string, node models.Node) error {
|
func ValidateNodeCreate(networkName string, node models.Node) error {
|
||||||
v := validator.New()
|
v := validator.New()
|
||||||
_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
|
_ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
|
||||||
|
@@ -31,6 +31,8 @@ func HandleRESTRequests(wg *sync.WaitGroup) {
|
|||||||
dnsHandlers(r)
|
dnsHandlers(r)
|
||||||
fileHandlers(r)
|
fileHandlers(r)
|
||||||
serverHandlers(r)
|
serverHandlers(r)
|
||||||
|
extClientHandlers(r)
|
||||||
|
|
||||||
|
|
||||||
port := servercfg.GetAPIPort()
|
port := servercfg.GetAPIPort()
|
||||||
|
|
||||||
|
413
controllers/extClientHttpController.go
Normal file
413
controllers/extClientHttpController.go
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
// "fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
|
"github.com/gravitl/netmaker/functions"
|
||||||
|
"github.com/gravitl/netmaker/models"
|
||||||
|
"github.com/gravitl/netmaker/mongoconn"
|
||||||
|
"go.mongodb.org/mongo-driver/bson"
|
||||||
|
"go.mongodb.org/mongo-driver/mongo/options"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
"github.com/skip2/go-qrcode"
|
||||||
|
)
|
||||||
|
|
||||||
|
func extClientHandlers(r *mux.Router) {
|
||||||
|
|
||||||
|
r.HandleFunc("/api/extclients", securityCheck(http.HandlerFunc(getAllExtClients))).Methods("GET")
|
||||||
|
r.HandleFunc("/api/extclients/{network}", securityCheck(http.HandlerFunc(getNetworkExtClients))).Methods("GET")
|
||||||
|
r.HandleFunc("/api/extclients/{network}/{clientid}", securityCheck(http.HandlerFunc(getExtClient))).Methods("GET")
|
||||||
|
r.HandleFunc("/api/extclients/{network}/{clientid}/{type}", securityCheck(http.HandlerFunc(getExtClientConf))).Methods("GET")
|
||||||
|
r.HandleFunc("/api/extclients/{network}/{clientid}", securityCheck(http.HandlerFunc(updateExtClient))).Methods("PUT")
|
||||||
|
r.HandleFunc("/api/extclients/{network}/{clientid}", securityCheck(http.HandlerFunc(deleteExtClient))).Methods("DELETE")
|
||||||
|
r.HandleFunc("/api/extclients/{network}/{macaddress}", securityCheck(http.HandlerFunc(createExtClient))).Methods("POST")
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement Validation
|
||||||
|
func ValidateExtClientCreate(networkName string, extclient models.ExtClient) error {
|
||||||
|
// v := validator.New()
|
||||||
|
// _ = v.RegisterValidation("macaddress_unique", func(fl validator.FieldLevel) bool {
|
||||||
|
// var isFieldUnique bool = functions.IsFieldUnique(networkName, "macaddress", extclient.MacAddress)
|
||||||
|
// return isFieldUnique
|
||||||
|
// })
|
||||||
|
// _ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
|
||||||
|
// _, err := extclient.GetNetwork()
|
||||||
|
// return err == nil
|
||||||
|
// })
|
||||||
|
// err := v.Struct(extclient)
|
||||||
|
|
||||||
|
// if err != nil {
|
||||||
|
// for _, e := range err.(validator.ValidationErrors) {
|
||||||
|
// fmt.Println(e)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Implement Validation
|
||||||
|
func ValidateExtClientUpdate(networkName string, extclient models.ExtClient) error {
|
||||||
|
// v := validator.New()
|
||||||
|
// _ = v.RegisterValidation("network_exists", func(fl validator.FieldLevel) bool {
|
||||||
|
// _, err := extclient.GetNetwork()
|
||||||
|
// return err == nil
|
||||||
|
// })
|
||||||
|
// err := v.Struct(extclient)
|
||||||
|
// if err != nil {
|
||||||
|
// for _, e := range err.(validator.ValidationErrors) {
|
||||||
|
// fmt.Println(e)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkIngressExists(network string, macaddress string) bool {
|
||||||
|
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return node.IsIngressGateway
|
||||||
|
}
|
||||||
|
|
||||||
|
//Gets all extclients associated with network, including pending extclients
|
||||||
|
func getNetworkExtClients(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
var extclients []models.ExtClient
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
extclients, err := GetNetworkExtClients(params["network"])
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns all the extclients in JSON format
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(extclients)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNetworkExtClients(network string) ([]models.ExtClient, error) {
|
||||||
|
var extclients []models.ExtClient
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
filter := bson.M{"network": network}
|
||||||
|
//Filtering out the ID field cuz Dillon doesn't like it. May want to filter out other fields in the future
|
||||||
|
cur, err := collection.Find(ctx, filter, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||||
|
if err != nil {
|
||||||
|
return []models.ExtClient{}, err
|
||||||
|
}
|
||||||
|
defer cancel()
|
||||||
|
for cur.Next(context.TODO()) {
|
||||||
|
//Using a different model for the ReturnExtClient (other than regular extclient).
|
||||||
|
//Either we should do this for ALL structs (so Networks and Keys)
|
||||||
|
//OR we should just use the original struct
|
||||||
|
//My preference is to make some new return structs
|
||||||
|
//TODO: Think about this. Not an immediate concern. Just need to get some consistency eventually
|
||||||
|
var extclient models.ExtClient
|
||||||
|
err := cur.Decode(&extclient)
|
||||||
|
if err != nil {
|
||||||
|
return []models.ExtClient{}, err
|
||||||
|
}
|
||||||
|
// add item our array of extclients
|
||||||
|
extclients = append(extclients, extclient)
|
||||||
|
}
|
||||||
|
//TODO: Another fatal error we should take care of.
|
||||||
|
if err := cur.Err(); err != nil {
|
||||||
|
return []models.ExtClient{}, err
|
||||||
|
}
|
||||||
|
return extclients, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//A separate function to get all extclients, not just extclients for a particular network.
|
||||||
|
//Not quite sure if this is necessary. Probably necessary based on front end but may want to review after iteration 1 if it's being used or not
|
||||||
|
func getAllExtClients(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
extclients, err := functions.GetAllExtClients()
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//Return all the extclients in JSON format
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(extclients)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get an individual extclient. Nothin fancy here folks.
|
||||||
|
func getExtClient(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// set header.
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
|
var extclient models.ExtClient
|
||||||
|
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
|
filter := bson.M{"network": params["network"], "clientid": params["clientid"]}
|
||||||
|
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&extclient)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(extclient)
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get an individual extclient. Nothin fancy here folks.
|
||||||
|
func getExtClientConf(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// set header.
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
|
var extclient models.ExtClient
|
||||||
|
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
|
filter := bson.M{"network": params["network"], "clientid": params["clientid"]}
|
||||||
|
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&extclient)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
gwnode, err := functions.GetNodeByMacAddress(extclient.Network, extclient.IngressGatewayID)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Could not retrieve Ingress Gateway Node " + extclient.IngressGatewayID)
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
network, err := functions.GetParentNetwork(extclient.Network)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Could not retrieve Ingress Gateway Network " + extclient.Network)
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
config := fmt.Sprintf(`[Interface]
|
||||||
|
Address = %s
|
||||||
|
PrivateKey = %s
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = %s
|
||||||
|
AllowedIPs = %s
|
||||||
|
Endpoint = %s
|
||||||
|
|
||||||
|
`, extclient.Address + "/32",
|
||||||
|
extclient.PrivateKey,
|
||||||
|
gwnode.PublicKey,
|
||||||
|
network.AddressRange,
|
||||||
|
network.DefaultKeepalive)
|
||||||
|
|
||||||
|
if params["type"] == "qr" {
|
||||||
|
bytes, err := qrcode.Encode(config, qrcode.Medium, 220)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Set("Content-Type", "image/png")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, err = w.Write(bytes)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if params["type"] == "file" {
|
||||||
|
name := extclient.ClientID + ".conf"
|
||||||
|
w.Header().Set("Content-Type", "application/config")
|
||||||
|
w.Header().Set("Content-Disposition", "attachment; filename=\"" + name + "\"")
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, err := fmt.Fprint(w, config)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(extclient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateExtClient(extclient models.ExtClient) error {
|
||||||
|
fmt.Println(extclient)
|
||||||
|
// Generate Private Key for new ExtClient
|
||||||
|
if extclient.PrivateKey == "" {
|
||||||
|
privateKey, err := wgtypes.GeneratePrivateKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
extclient.PrivateKey = privateKey.String()
|
||||||
|
extclient.PublicKey = privateKey.PublicKey().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
if extclient.Address == "" {
|
||||||
|
newAddress, err := functions.UniqueAddress(extclient.Network)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
extclient.Address = newAddress
|
||||||
|
}
|
||||||
|
|
||||||
|
extclient.LastModified = time.Now().Unix()
|
||||||
|
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
// insert our network into the network table
|
||||||
|
_, err := collection.InsertOne(ctx, extclient)
|
||||||
|
defer cancel()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
//This one's a doozy
|
||||||
|
//To create a extclient
|
||||||
|
//Must have valid key and be unique
|
||||||
|
func createExtClient(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
|
networkName := params["network"]
|
||||||
|
macaddress := params["macaddress"]
|
||||||
|
//Check if network exists first
|
||||||
|
//TODO: This is inefficient. Let's find a better way.
|
||||||
|
//Just a few rows down we grab the network anyway
|
||||||
|
ingressExists := checkIngressExists(networkName, macaddress)
|
||||||
|
if !ingressExists {
|
||||||
|
returnErrorResponse(w, r, formatError(errors.New("ingress does not exist"), "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var extclient models.ExtClient
|
||||||
|
extclient.Network = networkName
|
||||||
|
extclient.IngressGatewayID = macaddress
|
||||||
|
|
||||||
|
//get extclient from body of request
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&extclient)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = ValidateExtClientCreate(params["network"], extclient)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = CreateExtClient(extclient)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateExtClient(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
|
var newExtClient models.ExtClient
|
||||||
|
var oldExtClient models.ExtClient
|
||||||
|
// we decode our body request params
|
||||||
|
_ = json.NewDecoder(r.Body).Decode(&newExtClient)
|
||||||
|
// TODO: Validation for update.
|
||||||
|
// err := ValidateExtClientUpdate(params["network"], params["clientid"], newExtClient)
|
||||||
|
// if err != nil {
|
||||||
|
// returnErrorResponse(w, r, formatError(err, "badrequest"))
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||||
|
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
filter := bson.M{"network": params["network"], "clientid": params["clientid"]}
|
||||||
|
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&oldExtClient)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
success, err := DeleteExtClient(params["network"], params["clientid"])
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
} else if !success {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
oldExtClient.ClientID = newExtClient.ClientID
|
||||||
|
CreateExtClient(oldExtClient)
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
json.NewEncoder(w).Encode(oldExtClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteExtClient(network string, clientid string) (bool, error) {
|
||||||
|
|
||||||
|
deleted := false
|
||||||
|
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||||
|
|
||||||
|
filter := bson.M{"network": network, "clientid": clientid}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
|
result, err := collection.DeleteOne(ctx, filter)
|
||||||
|
|
||||||
|
deletecount := result.DeletedCount
|
||||||
|
|
||||||
|
if deletecount > 0 {
|
||||||
|
deleted = true
|
||||||
|
}
|
||||||
|
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
fmt.Println("Deleted extclient client " + clientid + " from network " + network)
|
||||||
|
return deleted, err
|
||||||
|
}
|
||||||
|
|
||||||
|
//Delete a extclient
|
||||||
|
//Pretty straightforward
|
||||||
|
func deleteExtClient(w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Set header
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
// get params
|
||||||
|
var params = mux.Vars(r)
|
||||||
|
|
||||||
|
success, err := DeleteExtClient(params["network"], params["clientid"])
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
} else if !success {
|
||||||
|
err = errors.New("Could not delete extclient " + params["clientid"])
|
||||||
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
returnSuccessResponse(w, r, params["clientid"]+" deleted.")
|
||||||
|
}
|
@@ -347,8 +347,8 @@ func (s *NodeServiceServer) GetPeers(req *nodepb.GetPeersReq, stream nodepb.Node
|
|||||||
Address: peers[i].Address,
|
Address: peers[i].Address,
|
||||||
Address6: peers[i].Address6,
|
Address6: peers[i].Address6,
|
||||||
Endpoint: peers[i].Endpoint,
|
Endpoint: peers[i].Endpoint,
|
||||||
Gatewayrange: peers[i].GatewayRange,
|
Egressgatewayrange: peers[i].EgressGatewayRange,
|
||||||
Isgateway: peers[i].IsGateway,
|
Isegressgateway: peers[i].IsEgressGateway,
|
||||||
Publickey: peers[i].PublicKey,
|
Publickey: peers[i].PublicKey,
|
||||||
Keepalive: peers[i].KeepAlive,
|
Keepalive: peers[i].KeepAlive,
|
||||||
Listenport: peers[i].ListenPort,
|
Listenport: peers[i].ListenPort,
|
||||||
@@ -369,3 +369,43 @@ func (s *NodeServiceServer) GetPeers(req *nodepb.GetPeersReq, stream nodepb.Node
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *NodeServiceServer) GetExtPeers(req *nodepb.GetExtPeersReq, stream nodepb.NodeService_GetExtPeersServer) error {
|
||||||
|
// Initiate a NodeItem type to write decoded data to
|
||||||
|
//data := &models.PeersResponse{}
|
||||||
|
// collection.Find returns a cursor for our (empty) query
|
||||||
|
//cursor, err := s.NodeDB.Find(context.Background(), bson.M{})
|
||||||
|
peers, err := GetExtPeersList(req.GetNetwork(), req.GetMacaddress())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return status.Errorf(codes.Internal, fmt.Sprintf("Unknown internal error: %v", err))
|
||||||
|
}
|
||||||
|
// cursor.Next() returns a boolean, if false there are no more items and loop will break
|
||||||
|
for i := 0; i < len(peers); i++ {
|
||||||
|
|
||||||
|
// If no error is found send node over stream
|
||||||
|
stream.Send(&nodepb.GetExtPeersRes{
|
||||||
|
Extpeers: &nodepb.ExtPeersResponse{
|
||||||
|
Address: peers[i].Address,
|
||||||
|
Address6: peers[i].Address6,
|
||||||
|
Endpoint: peers[i].Endpoint,
|
||||||
|
Publickey: peers[i].PublicKey,
|
||||||
|
Keepalive: peers[i].KeepAlive,
|
||||||
|
Listenport: peers[i].ListenPort,
|
||||||
|
Localaddress: peers[i].LocalAddress,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
node, err := functions.GetNodeByMacAddress(req.GetNetwork(), req.GetMacaddress())
|
||||||
|
if err != nil {
|
||||||
|
return status.Errorf(codes.Internal, fmt.Sprintf("Could not get node: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = TimestampNode(node, false, true, false)
|
||||||
|
if err != nil {
|
||||||
|
return status.Errorf(codes.Internal, fmt.Sprintf("Internal error occurred: %v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@@ -26,10 +26,10 @@ func nodeHandlers(r *mux.Router) {
|
|||||||
r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(updateNode))).Methods("PUT")
|
r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(updateNode))).Methods("PUT")
|
||||||
r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(deleteNode))).Methods("DELETE")
|
r.HandleFunc("/api/nodes/{network}/{macaddress}", authorize(true, "node", http.HandlerFunc(deleteNode))).Methods("DELETE")
|
||||||
r.HandleFunc("/api/nodes/{network}/{macaddress}/checkin", authorize(true, "node", http.HandlerFunc(checkIn))).Methods("POST")
|
r.HandleFunc("/api/nodes/{network}/{macaddress}/checkin", authorize(true, "node", http.HandlerFunc(checkIn))).Methods("POST")
|
||||||
r.HandleFunc("/api/nodes/{network}/{macaddress}/creategateway", authorize(true, "master", http.HandlerFunc(createGateway))).Methods("POST")
|
r.HandleFunc("/api/nodes/{network}/{macaddress}/creategateway", authorize(true, "master", http.HandlerFunc(createEgressGateway))).Methods("POST")
|
||||||
r.HandleFunc("/api/nodes/{network}/{macaddress}/deletegateway", authorize(true, "master", http.HandlerFunc(deleteGateway))).Methods("DELETE")
|
r.HandleFunc("/api/nodes/{network}/{macaddress}/deletegateway", authorize(true, "master", http.HandlerFunc(deleteEgressGateway))).Methods("DELETE")
|
||||||
r.HandleFunc("/api/nodes/{network}/{macaddress}/createingress", securityCheck(http.HandlerFunc(createIngress))).Methods("POST")
|
r.HandleFunc("/api/nodes/{network}/{macaddress}/createingress", securityCheck(http.HandlerFunc(createIngressGateway))).Methods("POST")
|
||||||
r.HandleFunc("/api/nodes/{network}/{macaddress}/deleteingress", securityCheck(http.HandlerFunc(deleteIngress))).Methods("DELETE")
|
r.HandleFunc("/api/nodes/{network}/{macaddress}/deleteingress", securityCheck(http.HandlerFunc(deleteIngressGateway))).Methods("DELETE")
|
||||||
r.HandleFunc("/api/nodes/{network}/{macaddress}/approve", authorize(true, "master", http.HandlerFunc(uncordonNode))).Methods("POST")
|
r.HandleFunc("/api/nodes/{network}/{macaddress}/approve", authorize(true, "master", http.HandlerFunc(uncordonNode))).Methods("POST")
|
||||||
r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST")
|
r.HandleFunc("/api/nodes/{network}", createNode).Methods("POST")
|
||||||
r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
|
r.HandleFunc("/api/nodes/adm/{network}/lastmodified", authorize(true, "network", http.HandlerFunc(getLastModified))).Methods("GET")
|
||||||
@@ -526,8 +526,8 @@ func UncordonNode(network, macaddress string) (models.Node, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createGateway(w http.ResponseWriter, r *http.Request) {
|
func createEgressGateway(w http.ResponseWriter, r *http.Request) {
|
||||||
var gateway models.GatewayRequest
|
var gateway models.EgressGatewayRequest
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
err := json.NewDecoder(r.Body).Decode(&gateway)
|
err := json.NewDecoder(r.Body).Decode(&gateway)
|
||||||
@@ -537,7 +537,7 @@ func createGateway(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
gateway.NetID = params["network"]
|
gateway.NetID = params["network"]
|
||||||
gateway.NodeID = params["macaddress"]
|
gateway.NodeID = params["macaddress"]
|
||||||
node, err := CreateGateway(gateway)
|
node, err := CreateEgressGateway(gateway)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -546,18 +546,18 @@ func createGateway(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(node)
|
json.NewEncoder(w).Encode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateGateway(gateway models.GatewayRequest) (models.Node, error) {
|
func CreateEgressGateway(gateway models.EgressGatewayRequest) (models.Node, error) {
|
||||||
node, err := functions.GetNodeByMacAddress(gateway.NetID, gateway.NodeID)
|
node, err := functions.GetNodeByMacAddress(gateway.NetID, gateway.NodeID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Node{}, err
|
return models.Node{}, err
|
||||||
}
|
}
|
||||||
err = ValidateGateway(gateway)
|
err = ValidateEgressGateway(gateway)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Node{}, err
|
return models.Node{}, err
|
||||||
}
|
}
|
||||||
var nodechange models.Node
|
var nodechange models.Node
|
||||||
nodechange.IsGateway = true
|
nodechange.IsEgressGateway = true
|
||||||
nodechange.GatewayRange = gateway.RangeString
|
nodechange.EgressGatewayRange = gateway.RangeString
|
||||||
if gateway.PostUp == "" {
|
if gateway.PostUp == "" {
|
||||||
nodechange.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
|
nodechange.PostUp = "iptables -A FORWARD -i " + node.Interface + " -j ACCEPT; iptables -t nat -A POSTROUTING -o " + gateway.Interface + " -j MASQUERADE"
|
||||||
} else {
|
} else {
|
||||||
@@ -579,8 +579,8 @@ func CreateGateway(gateway models.GatewayRequest) (models.Node, error) {
|
|||||||
{"$set", bson.D{
|
{"$set", bson.D{
|
||||||
{"postup", nodechange.PostUp},
|
{"postup", nodechange.PostUp},
|
||||||
{"postdown", nodechange.PostDown},
|
{"postdown", nodechange.PostDown},
|
||||||
{"isgateway", nodechange.IsGateway},
|
{"isgateway", nodechange.IsEgressGateway},
|
||||||
{"gatewayrange", nodechange.GatewayRange},
|
{"gatewayrange", nodechange.EgressGatewayRange},
|
||||||
{"lastmodified", nodechange.LastModified},
|
{"lastmodified", nodechange.LastModified},
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
@@ -602,7 +602,7 @@ func CreateGateway(gateway models.GatewayRequest) (models.Node, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateGateway(gateway models.GatewayRequest) error {
|
func ValidateEgressGateway(gateway models.EgressGatewayRequest) error {
|
||||||
var err error
|
var err error
|
||||||
isIp := functions.IsIpCIDR(gateway.RangeString)
|
isIp := functions.IsIpCIDR(gateway.RangeString)
|
||||||
empty := gateway.RangeString == ""
|
empty := gateway.RangeString == ""
|
||||||
@@ -616,10 +616,10 @@ func ValidateGateway(gateway models.GatewayRequest) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteGateway(w http.ResponseWriter, r *http.Request) {
|
func deleteEgressGateway(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
node, err := DeleteGateway(params["network"], params["macaddress"])
|
node, err := DeleteEgressGateway(params["network"], params["macaddress"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -628,7 +628,7 @@ func deleteGateway(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(node)
|
json.NewEncoder(w).Encode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteGateway(network, macaddress string) (models.Node, error) {
|
func DeleteEgressGateway(network, macaddress string) (models.Node, error) {
|
||||||
|
|
||||||
var nodeupdate models.Node
|
var nodeupdate models.Node
|
||||||
var nodechange models.Node
|
var nodechange models.Node
|
||||||
@@ -637,8 +637,8 @@ func DeleteGateway(network, macaddress string) (models.Node, error) {
|
|||||||
return models.Node{}, err
|
return models.Node{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
nodechange.IsGateway = false
|
nodechange.IsEgressGateway = false
|
||||||
nodechange.GatewayRange = ""
|
nodechange.EgressGatewayRange = ""
|
||||||
nodechange.PostUp = ""
|
nodechange.PostUp = ""
|
||||||
nodechange.PostDown = ""
|
nodechange.PostDown = ""
|
||||||
|
|
||||||
@@ -652,8 +652,8 @@ func DeleteGateway(network, macaddress string) (models.Node, error) {
|
|||||||
{"$set", bson.D{
|
{"$set", bson.D{
|
||||||
{"postup", nodechange.PostUp},
|
{"postup", nodechange.PostUp},
|
||||||
{"postdown", nodechange.PostDown},
|
{"postdown", nodechange.PostDown},
|
||||||
{"isgateway", nodechange.IsGateway},
|
{"isgateway", nodechange.IsEgressGateway},
|
||||||
{"gatewayrange", nodechange.GatewayRange},
|
{"gatewayrange", nodechange.EgressGatewayRange},
|
||||||
{"lastmodified", nodechange.LastModified},
|
{"lastmodified", nodechange.LastModified},
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
@@ -674,10 +674,10 @@ func DeleteGateway(network, macaddress string) (models.Node, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
// == INGRESS ==
|
// == INGRESS ==
|
||||||
func createIngress(w http.ResponseWriter, r *http.Request) {
|
func createIngressGateway(w http.ResponseWriter, r *http.Request) {
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
node, err := CreateIngress(params["network"], params["macaddress"])
|
node, err := CreateIngressGateway(params["network"], params["macaddress"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -686,7 +686,7 @@ func createIngress(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(node)
|
json.NewEncoder(w).Encode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateIngress(network string, macaddress string) (models.Node, error) {
|
func CreateIngressGateway(network string, macaddress string) (models.Node, error) {
|
||||||
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return models.Node{}, err
|
return models.Node{}, err
|
||||||
@@ -717,10 +717,10 @@ func CreateIngress(network string, macaddress string) (models.Node, error) {
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteIngress(w http.ResponseWriter, r *http.Request) {
|
func deleteIngressGateway(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
var params = mux.Vars(r)
|
var params = mux.Vars(r)
|
||||||
node, err := DeleteIngress(params["network"], params["macaddress"])
|
node, err := DeleteIngressGateway(params["network"], params["macaddress"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
returnErrorResponse(w, r, formatError(err, "internal"))
|
returnErrorResponse(w, r, formatError(err, "internal"))
|
||||||
return
|
return
|
||||||
@@ -729,7 +729,7 @@ func deleteIngress(w http.ResponseWriter, r *http.Request) {
|
|||||||
json.NewEncoder(w).Encode(node)
|
json.NewEncoder(w).Encode(node)
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteIngress(network, macaddress string) (models.Node, error) {
|
func DeleteIngressGateway(network, macaddress string) (models.Node, error) {
|
||||||
|
|
||||||
var nodeupdate models.Node
|
var nodeupdate models.Node
|
||||||
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
node, err := functions.GetNodeByMacAddress(network, macaddress)
|
||||||
|
@@ -481,6 +481,34 @@ func GetNodeByMacAddress(network string, macaddress string) (models.Node, error)
|
|||||||
return node, nil
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAllExtClients() ([]models.ExtClient, error) {
|
||||||
|
var extclient models.ExtClient
|
||||||
|
var extclients []models.ExtClient
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
// Filter out them ID's again
|
||||||
|
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
|
||||||
|
if err != nil {
|
||||||
|
return []models.ExtClient{}, err
|
||||||
|
}
|
||||||
|
defer cancel()
|
||||||
|
for cur.Next(context.TODO()) {
|
||||||
|
err := cur.Decode(&extclient)
|
||||||
|
if err != nil {
|
||||||
|
return []models.ExtClient{}, err
|
||||||
|
}
|
||||||
|
// add node to our array
|
||||||
|
extclients = append(extclients, extclient)
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Fatal error
|
||||||
|
if err := cur.Err(); err != nil {
|
||||||
|
return []models.ExtClient{}, err
|
||||||
|
}
|
||||||
|
return extclients, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//This returns a unique address for a node to use
|
//This returns a unique address for a node to use
|
||||||
//it iterates through the list of IP's in the subnet
|
//it iterates through the list of IP's in the subnet
|
||||||
//and checks against all nodes to see if it's taken, until it finds one.
|
//and checks against all nodes to see if it's taken, until it finds one.
|
||||||
@@ -506,7 +534,7 @@ func UniqueAddress(networkName string) (string, error) {
|
|||||||
offset = false
|
offset = false
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if IsIPUnique(networkName, ip.String()) {
|
if IsIPUnique(networkName, ip.String()) && IsIPUniqueExtClients(networkName, ip.String()) {
|
||||||
return ip.String(), err
|
return ip.String(), err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -582,6 +610,33 @@ func GenKeyName() string {
|
|||||||
return "key" + string(b)
|
return "key" + string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsIPUniqueExtClients(network string, ip string) bool {
|
||||||
|
|
||||||
|
var extclient models.ExtClient
|
||||||
|
|
||||||
|
isunique := true
|
||||||
|
|
||||||
|
collection := mongoconn.Client.Database("netmaker").Collection("extclients")
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
|
||||||
|
filter := bson.M{"address": ip, "network": network}
|
||||||
|
|
||||||
|
err := collection.FindOne(ctx, filter).Decode(&extclient)
|
||||||
|
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return isunique
|
||||||
|
}
|
||||||
|
|
||||||
|
if extclient.Address == ip {
|
||||||
|
isunique = false
|
||||||
|
}
|
||||||
|
return isunique
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//checks if IP is unique in the address range
|
//checks if IP is unique in the address range
|
||||||
//used by UniqueAddress
|
//used by UniqueAddress
|
||||||
func IsIPUnique(network string, ip string) bool {
|
func IsIPUnique(network string, ip string) bool {
|
||||||
@@ -749,30 +804,3 @@ func GetAllNodes() ([]models.ReturnNode, error) {
|
|||||||
return nodes, nil
|
return nodes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetAllExternals() ([]models.ReturnNode, error) {
|
|
||||||
var node models.ReturnNode
|
|
||||||
var nodes []models.ReturnNode
|
|
||||||
collection := mongoconn.Client.Database("netmaker").Collection("nodes")
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
||||||
// Filter out them ID's again
|
|
||||||
cur, err := collection.Find(ctx, bson.M{}, options.Find().SetProjection(bson.M{"_id": 0}))
|
|
||||||
if err != nil {
|
|
||||||
return []models.ReturnNode{}, err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
for cur.Next(context.TODO()) {
|
|
||||||
err := cur.Decode(&node)
|
|
||||||
if err != nil {
|
|
||||||
return []models.ReturnNode{}, err
|
|
||||||
}
|
|
||||||
// add node to our array
|
|
||||||
nodes = append(nodes, node)
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: Fatal error
|
|
||||||
if err := cur.Err(); err != nil {
|
|
||||||
return []models.ReturnNode{}, err
|
|
||||||
}
|
|
||||||
return nodes, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
2239
grpc/node.pb.go
2239
grpc/node.pb.go
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,7 @@ service NodeService {
|
|||||||
rpc UpdateNode(UpdateNodeReq) returns (UpdateNodeRes);
|
rpc UpdateNode(UpdateNodeReq) returns (UpdateNodeRes);
|
||||||
rpc DeleteNode(DeleteNodeReq) returns (DeleteNodeRes);
|
rpc DeleteNode(DeleteNodeReq) returns (DeleteNodeRes);
|
||||||
rpc GetPeers(GetPeersReq) returns (stream GetPeersRes);
|
rpc GetPeers(GetPeersReq) returns (stream GetPeersRes);
|
||||||
|
rpc GetExtPeers(GetExtPeersReq) returns (stream GetExtPeersRes);
|
||||||
rpc CheckIn(CheckInReq) returns (CheckInRes);
|
rpc CheckIn(CheckInReq) returns (CheckInRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ message Node {
|
|||||||
string postchanges = 21;
|
string postchanges = 21;
|
||||||
string allowedips = 22;
|
string allowedips = 22;
|
||||||
bool islocal = 23;
|
bool islocal = 23;
|
||||||
|
bool isingressgateway = 28;
|
||||||
bool isdualstack = 27;
|
bool isdualstack = 27;
|
||||||
bool dnsoff = 24;
|
bool dnsoff = 24;
|
||||||
string localrange = 25;
|
string localrange = 25;
|
||||||
@@ -61,8 +63,18 @@ message CheckInResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message PeersResponse {
|
message PeersResponse {
|
||||||
bool isgateway = 1;
|
bool isegressgateway = 1;
|
||||||
string gatewayrange = 2;
|
string egressgatewayrange = 2;
|
||||||
|
string publickey = 5;
|
||||||
|
string endpoint = 6;
|
||||||
|
string address = 3;
|
||||||
|
string address6 = 8;
|
||||||
|
int32 listenport = 4;
|
||||||
|
string localaddress = 7;
|
||||||
|
int32 keepalive = 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ExtPeersResponse {
|
||||||
string publickey = 5;
|
string publickey = 5;
|
||||||
string endpoint = 6;
|
string endpoint = 6;
|
||||||
string address = 3;
|
string address = 3;
|
||||||
@@ -111,10 +123,19 @@ message GetPeersReq {
|
|||||||
string network = 2;
|
string network = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message GetExtPeersReq {
|
||||||
|
string macaddress = 1;
|
||||||
|
string network = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message GetPeersRes {
|
message GetPeersRes {
|
||||||
PeersResponse peers = 1;
|
PeersResponse peers = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message GetExtPeersRes {
|
||||||
|
ExtPeersResponse extpeers = 1;
|
||||||
|
}
|
||||||
|
|
||||||
message CheckInReq {
|
message CheckInReq {
|
||||||
Node node = 1;
|
Node node = 1;
|
||||||
// bool postchanges = 2;
|
// bool postchanges = 2;
|
||||||
|
@@ -24,6 +24,7 @@ type NodeServiceClient interface {
|
|||||||
UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRes, error)
|
UpdateNode(ctx context.Context, in *UpdateNodeReq, opts ...grpc.CallOption) (*UpdateNodeRes, error)
|
||||||
DeleteNode(ctx context.Context, in *DeleteNodeReq, opts ...grpc.CallOption) (*DeleteNodeRes, error)
|
DeleteNode(ctx context.Context, in *DeleteNodeReq, opts ...grpc.CallOption) (*DeleteNodeRes, error)
|
||||||
GetPeers(ctx context.Context, in *GetPeersReq, opts ...grpc.CallOption) (NodeService_GetPeersClient, error)
|
GetPeers(ctx context.Context, in *GetPeersReq, opts ...grpc.CallOption) (NodeService_GetPeersClient, error)
|
||||||
|
GetExtPeers(ctx context.Context, in *GetExtPeersReq, opts ...grpc.CallOption) (NodeService_GetExtPeersClient, error)
|
||||||
CheckIn(ctx context.Context, in *CheckInReq, opts ...grpc.CallOption) (*CheckInRes, error)
|
CheckIn(ctx context.Context, in *CheckInReq, opts ...grpc.CallOption) (*CheckInRes, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +113,38 @@ func (x *nodeServiceGetPeersClient) Recv() (*GetPeersRes, error) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *nodeServiceClient) GetExtPeers(ctx context.Context, in *GetExtPeersReq, opts ...grpc.CallOption) (NodeService_GetExtPeersClient, error) {
|
||||||
|
stream, err := c.cc.NewStream(ctx, &NodeService_ServiceDesc.Streams[1], "/node.NodeService/GetExtPeers", opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
x := &nodeServiceGetExtPeersClient{stream}
|
||||||
|
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := x.ClientStream.CloseSend(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type NodeService_GetExtPeersClient interface {
|
||||||
|
Recv() (*GetExtPeersRes, error)
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeServiceGetExtPeersClient struct {
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *nodeServiceGetExtPeersClient) Recv() (*GetExtPeersRes, error) {
|
||||||
|
m := new(GetExtPeersRes)
|
||||||
|
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *nodeServiceClient) CheckIn(ctx context.Context, in *CheckInReq, opts ...grpc.CallOption) (*CheckInRes, error) {
|
func (c *nodeServiceClient) CheckIn(ctx context.Context, in *CheckInReq, opts ...grpc.CallOption) (*CheckInRes, error) {
|
||||||
out := new(CheckInRes)
|
out := new(CheckInRes)
|
||||||
err := c.cc.Invoke(ctx, "/node.NodeService/CheckIn", in, out, opts...)
|
err := c.cc.Invoke(ctx, "/node.NodeService/CheckIn", in, out, opts...)
|
||||||
@@ -131,6 +164,7 @@ type NodeServiceServer interface {
|
|||||||
UpdateNode(context.Context, *UpdateNodeReq) (*UpdateNodeRes, error)
|
UpdateNode(context.Context, *UpdateNodeReq) (*UpdateNodeRes, error)
|
||||||
DeleteNode(context.Context, *DeleteNodeReq) (*DeleteNodeRes, error)
|
DeleteNode(context.Context, *DeleteNodeReq) (*DeleteNodeRes, error)
|
||||||
GetPeers(*GetPeersReq, NodeService_GetPeersServer) error
|
GetPeers(*GetPeersReq, NodeService_GetPeersServer) error
|
||||||
|
GetExtPeers(*GetExtPeersReq, NodeService_GetExtPeersServer) error
|
||||||
CheckIn(context.Context, *CheckInReq) (*CheckInRes, error)
|
CheckIn(context.Context, *CheckInReq) (*CheckInRes, error)
|
||||||
mustEmbedUnimplementedNodeServiceServer()
|
mustEmbedUnimplementedNodeServiceServer()
|
||||||
}
|
}
|
||||||
@@ -157,6 +191,9 @@ func (UnimplementedNodeServiceServer) DeleteNode(context.Context, *DeleteNodeReq
|
|||||||
func (UnimplementedNodeServiceServer) GetPeers(*GetPeersReq, NodeService_GetPeersServer) error {
|
func (UnimplementedNodeServiceServer) GetPeers(*GetPeersReq, NodeService_GetPeersServer) error {
|
||||||
return status.Errorf(codes.Unimplemented, "method GetPeers not implemented")
|
return status.Errorf(codes.Unimplemented, "method GetPeers not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedNodeServiceServer) GetExtPeers(*GetExtPeersReq, NodeService_GetExtPeersServer) error {
|
||||||
|
return status.Errorf(codes.Unimplemented, "method GetExtPeers not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedNodeServiceServer) CheckIn(context.Context, *CheckInReq) (*CheckInRes, error) {
|
func (UnimplementedNodeServiceServer) CheckIn(context.Context, *CheckInReq) (*CheckInRes, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method CheckIn not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method CheckIn not implemented")
|
||||||
}
|
}
|
||||||
@@ -284,6 +321,27 @@ func (x *nodeServiceGetPeersServer) Send(m *GetPeersRes) error {
|
|||||||
return x.ServerStream.SendMsg(m)
|
return x.ServerStream.SendMsg(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _NodeService_GetExtPeers_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
|
m := new(GetExtPeersReq)
|
||||||
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return srv.(NodeServiceServer).GetExtPeers(m, &nodeServiceGetExtPeersServer{stream})
|
||||||
|
}
|
||||||
|
|
||||||
|
type NodeService_GetExtPeersServer interface {
|
||||||
|
Send(*GetExtPeersRes) error
|
||||||
|
grpc.ServerStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type nodeServiceGetExtPeersServer struct {
|
||||||
|
grpc.ServerStream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *nodeServiceGetExtPeersServer) Send(m *GetExtPeersRes) error {
|
||||||
|
return x.ServerStream.SendMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
func _NodeService_CheckIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _NodeService_CheckIn_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(CheckInReq)
|
in := new(CheckInReq)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
@@ -340,6 +398,11 @@ var NodeService_ServiceDesc = grpc.ServiceDesc{
|
|||||||
Handler: _NodeService_GetPeers_Handler,
|
Handler: _NodeService_GetPeers_Handler,
|
||||||
ServerStreams: true,
|
ServerStreams: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
StreamName: "GetExtPeers",
|
||||||
|
Handler: _NodeService_GetExtPeers_Handler,
|
||||||
|
ServerStreams: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Metadata: "grpc/node.proto",
|
Metadata: "grpc/node.proto",
|
||||||
}
|
}
|
||||||
|
45
models/extclient.go
Normal file
45
models/extclient.go
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||||
|
)
|
||||||
|
//What the client needs to get
|
||||||
|
/*
|
||||||
|
|
||||||
|
[Interface]
|
||||||
|
# The address their computer will use on the network
|
||||||
|
Address = 10.0.0.8/32 # The Address they'll use on the network
|
||||||
|
PrivateKey = XXXXXXXXXXXXXXXX # The private key they'll use
|
||||||
|
|
||||||
|
|
||||||
|
# All of this info can come from the node!!
|
||||||
|
[Peer]
|
||||||
|
# Ingress Gateway's wireguard public key
|
||||||
|
PublicKey = CcZHeaO08z55/x3FXdsSGmOQvZG32SvHlrwHnsWlGTs=
|
||||||
|
|
||||||
|
# Public IP address of the Ingress Gateway
|
||||||
|
# Use the floating IP address if you created one for your VPN server
|
||||||
|
Endpoint = 123.123.123.123:51820
|
||||||
|
|
||||||
|
# 10.0.0.0/24 is the VPN sub
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// External Struct
|
||||||
|
// == BACKEND FIELDS ==
|
||||||
|
// PrivateKey, PublicKey, Address (Private), LastModified, IngressEndpoint
|
||||||
|
// == FRONTEND FIELDS ==
|
||||||
|
// ClientID, Network, IngressGateway
|
||||||
|
type ExtClient struct {
|
||||||
|
ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
|
||||||
|
ClientID string `json:"clientid" bson:"clientid"`
|
||||||
|
Description string `json:"description" bson:"description"`
|
||||||
|
PrivateKey string `json:"privatekey" bson:"privatekey"`
|
||||||
|
PublicKey string `json:"publickey" bson:"publickey"`
|
||||||
|
Network string `json:"network" bson:"network"`
|
||||||
|
Address string `json:"address" bson:"address"`
|
||||||
|
LastModified int64 `json:"lastmodified" bson:"lastmodified"`
|
||||||
|
IngressGatewayID string `json:"ingressgatewayid" bson:"ingressgatewayid"`
|
||||||
|
IngressGatewayEnpoint string `json:"ingressgatewayendpoint" bson:"ingressgatewayendpoint"`
|
||||||
|
}
|
@@ -1,18 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
||||||
)
|
|
||||||
|
|
||||||
//External Struct
|
|
||||||
//At some point, need to replace all instances of Name with something else like Identifier
|
|
||||||
type External struct {
|
|
||||||
ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"`
|
|
||||||
ClientID string `json:"clientid" bson:"clientid"`
|
|
||||||
PrivateKey string `json:"privatekey" bson:"privatekey"`
|
|
||||||
PublicKey string `json:"publickey" bson:"publickey"`
|
|
||||||
Network string `json:"network" bson:"network"`
|
|
||||||
Address string `json:"address" bson:"address"`
|
|
||||||
LastModified string `json:"lastmodified" bson:"lastmodified"`
|
|
||||||
IngressGateway string `json:"ingressgateway" bson:"ingressgateway"`
|
|
||||||
}
|
|
@@ -43,8 +43,9 @@ type Node struct {
|
|||||||
Password string `json:"password" bson:"password" validate:"required,min=6"`
|
Password string `json:"password" bson:"password" validate:"required,min=6"`
|
||||||
Network string `json:"network" bson:"network" validate:"network_exists"`
|
Network string `json:"network" bson:"network" validate:"network_exists"`
|
||||||
IsPending bool `json:"ispending" bson:"ispending"`
|
IsPending bool `json:"ispending" bson:"ispending"`
|
||||||
IsGateway bool `json:"isgateway" bson:"isgateway"`
|
IsEgressGateway bool `json:"isegressgateway" bson:"isegressgateway"`
|
||||||
GatewayRange string `json:"gatewayrange" bson:"gatewayrange"`
|
IsIngressGateway bool `json:"isingressgateway" bson:"isingressgateway"`
|
||||||
|
EgressGatewayRange string `json:"gatewayrange" bson:"gatewayrange"`
|
||||||
PostChanges string `json:"postchanges" bson:"postchanges"`
|
PostChanges string `json:"postchanges" bson:"postchanges"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,8 +76,9 @@ type NodeUpdate struct {
|
|||||||
Password string `json:"password" bson:"password" validate:"omitempty,min=5"`
|
Password string `json:"password" bson:"password" validate:"omitempty,min=5"`
|
||||||
Network string `json:"network" bson:"network" validate:"network_exists"`
|
Network string `json:"network" bson:"network" validate:"network_exists"`
|
||||||
IsPending bool `json:"ispending" bson:"ispending"`
|
IsPending bool `json:"ispending" bson:"ispending"`
|
||||||
IsGateway bool `json:"isgateway" bson:"isgateway"`
|
IsIngressGateway bool `json:"isingressgateway" bson:"isingressgateway"`
|
||||||
GatewayRange string `json:"gatewayrange" bson:"gatewayrange"`
|
IsEgressGateway bool `json:"isegressgateway" bson:"isegressgateway"`
|
||||||
|
EgressGatewayRange string `json:"gatewayrange" bson:"gatewayrange"`
|
||||||
PostChanges string `json:"postchanges" bson:"postchanges"`
|
PostChanges string `json:"postchanges" bson:"postchanges"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -19,8 +19,9 @@ type ReturnNode struct {
|
|||||||
Interface string `json:"interface" bson:"interface"`
|
Interface string `json:"interface" bson:"interface"`
|
||||||
Network string `json:"network" bson:"network"`
|
Network string `json:"network" bson:"network"`
|
||||||
IsPending *bool `json:"ispending" bson:"ispending"`
|
IsPending *bool `json:"ispending" bson:"ispending"`
|
||||||
IsGateway *bool `json:"isgateway" bson:"isgateway"`
|
IsEgressGateway *bool `json:"isegressgateway" bson:"isegressgateway"`
|
||||||
GatewayRange string `json:"gatewayrange" bson:"gatewayrange"`
|
IsIngressGateway *bool `json:"isingressgateway" bson:"isingressgateway"`
|
||||||
|
EgressGatewayRange string `json:"egressgatewayrange" bson:"egressgatewayrange"`
|
||||||
LocalAddress string `json:"localaddress" bson:"localaddress" validate:"localaddress_check"`
|
LocalAddress string `json:"localaddress" bson:"localaddress" validate:"localaddress_check"`
|
||||||
ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime"`
|
ExpirationDateTime int64 `json:"expdatetime" bson:"expdatetime"`
|
||||||
}
|
}
|
||||||
|
@@ -95,13 +95,23 @@ type PeersResponse struct {
|
|||||||
Address string `json:"address" bson:"address"`
|
Address string `json:"address" bson:"address"`
|
||||||
Address6 string `json:"address6" bson:"address6"`
|
Address6 string `json:"address6" bson:"address6"`
|
||||||
LocalAddress string `json:"localaddress" bson:"localaddress"`
|
LocalAddress string `json:"localaddress" bson:"localaddress"`
|
||||||
IsGateway bool `json:"isgateway" bson:"isgateway"`
|
IsEgressGateway bool `json:"isgateway" bson:"isgateway"`
|
||||||
GatewayRange string `json:"gatewayrange" bson:"gatewayrange"`
|
EgressGatewayRange string `json:"gatewayrange" bson:"gatewayrange"`
|
||||||
ListenPort int32 `json:"listenport" bson:"listenport"`
|
ListenPort int32 `json:"listenport" bson:"listenport"`
|
||||||
KeepAlive int32 `json:"persistentkeepalive" bson:"persistentkeepalive"`
|
KeepAlive int32 `json:"persistentkeepalive" bson:"persistentkeepalive"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GatewayRequest struct {
|
type ExtPeersResponse struct {
|
||||||
|
PublicKey string `json:"publickey" bson:"publickey"`
|
||||||
|
Endpoint string `json:"endpoint" bson:"endpoint"`
|
||||||
|
Address string `json:"address" bson:"address"`
|
||||||
|
Address6 string `json:"address6" bson:"address6"`
|
||||||
|
LocalAddress string `json:"localaddress" bson:"localaddress"`
|
||||||
|
ListenPort int32 `json:"listenport" bson:"listenport"`
|
||||||
|
KeepAlive int32 `json:"persistentkeepalive" bson:"persistentkeepalive"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type EgressGatewayRequest struct {
|
||||||
NodeID string `json:"nodeid" bson:"nodeid"`
|
NodeID string `json:"nodeid" bson:"nodeid"`
|
||||||
NetID string `json:"netid" bson:"netid"`
|
NetID string `json:"netid" bson:"netid"`
|
||||||
RangeString string `json:"rangestring" bson:"rangestring"`
|
RangeString string `json:"rangestring" bson:"rangestring"`
|
||||||
|
@@ -2,12 +2,10 @@ package functions
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
"errors"
|
"errors"
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"io"
|
|
||||||
"strings"
|
"strings"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
@@ -454,7 +452,7 @@ func Install(accesskey string, password string, server string, network string, n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
peers, hasGateway, gateways, err := getPeers(node.Macaddress, network, server, node.Isdualstack)
|
peers, hasGateway, gateways, err := getPeers(node.Macaddress, network, server, node.Isdualstack, node.Isingressgateway)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -931,7 +929,7 @@ func setWGConfig(network string) error {
|
|||||||
nodecfg := cfg.Node
|
nodecfg := cfg.Node
|
||||||
node := getNode(network)
|
node := getNode(network)
|
||||||
|
|
||||||
peers, hasGateway, gateways, err := getPeers(node.Macaddress, nodecfg.Network, servercfg.Address, node.Isdualstack)
|
peers, hasGateway, gateways, err := getPeers(node.Macaddress, nodecfg.Network, servercfg.Address, node.Isdualstack, node.Isingressgateway)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -1451,138 +1449,3 @@ func DeleteInterface(ifacename string, postdown string) error{
|
|||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPeers(macaddress string, network string, server string, dualstack bool) ([]wgtypes.PeerConfig, bool, []string, error) {
|
|
||||||
//need to implement checkin on server side
|
|
||||||
hasGateway := false
|
|
||||||
var gateways []string
|
|
||||||
var peers []wgtypes.PeerConfig
|
|
||||||
var wcclient nodepb.NodeServiceClient
|
|
||||||
cfg, err := config.ReadConfig(network)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Issue retrieving config for network: " + network + ". Please investigate: %v", err)
|
|
||||||
}
|
|
||||||
nodecfg := cfg.Node
|
|
||||||
keepalive := nodecfg.KeepAlive
|
|
||||||
keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fmt.Println("Registering with GRPC Server")
|
|
||||||
requestOpts := grpc.WithInsecure()
|
|
||||||
conn, err := grpc.Dial(server, requestOpts)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
|
|
||||||
}
|
|
||||||
// Instantiate the BlogServiceClient with our client connection to the server
|
|
||||||
wcclient = nodepb.NewNodeServiceClient(conn)
|
|
||||||
|
|
||||||
req := &nodepb.GetPeersReq{
|
|
||||||
Macaddress: macaddress,
|
|
||||||
Network: network,
|
|
||||||
}
|
|
||||||
ctx := context.Background()
|
|
||||||
fmt.Println("Authenticating with GRPC Server")
|
|
||||||
ctx, err = SetJWT(wcclient, network)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Failed to authenticate.")
|
|
||||||
return peers, hasGateway, gateways, err
|
|
||||||
}
|
|
||||||
var header metadata.MD
|
|
||||||
|
|
||||||
stream, err := wcclient.GetPeers(ctx, req, grpc.Header(&header))
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error retrieving peers")
|
|
||||||
fmt.Println(err)
|
|
||||||
return nil, hasGateway, gateways, err
|
|
||||||
}
|
|
||||||
fmt.Println("Parsing peers response")
|
|
||||||
for {
|
|
||||||
res, err := stream.Recv()
|
|
||||||
// If end of stream, break the loop
|
|
||||||
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
// if err, return an error
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "mongo: no documents in result") {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
fmt.Println("ERROR ENCOUNTERED WITH RESPONSE")
|
|
||||||
fmt.Println(res)
|
|
||||||
return peers, hasGateway, gateways, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pubkey, err := wgtypes.ParseKey(res.Peers.Publickey)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("error parsing key")
|
|
||||||
return peers, hasGateway, gateways, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if nodecfg.PublicKey == res.Peers.Publickey {
|
|
||||||
fmt.Println("Peer is self. Skipping")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if nodecfg.Endpoint == res.Peers.Endpoint {
|
|
||||||
fmt.Println("Peer is self. Skipping")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var peer wgtypes.PeerConfig
|
|
||||||
var peeraddr = net.IPNet{
|
|
||||||
IP: net.ParseIP(res.Peers.Address),
|
|
||||||
Mask: net.CIDRMask(32, 32),
|
|
||||||
}
|
|
||||||
var allowedips []net.IPNet
|
|
||||||
allowedips = append(allowedips, peeraddr)
|
|
||||||
if res.Peers.Isgateway {
|
|
||||||
hasGateway = true
|
|
||||||
gateways = append(gateways,res.Peers.Gatewayrange)
|
|
||||||
_, ipnet, err := net.ParseCIDR(res.Peers.Gatewayrange)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("ERROR ENCOUNTERED SETTING GATEWAY")
|
|
||||||
fmt.Println("NOT SETTING GATEWAY")
|
|
||||||
fmt.Println(err)
|
|
||||||
} else {
|
|
||||||
fmt.Println(" Gateway Range: " + res.Peers.Gatewayrange)
|
|
||||||
allowedips = append(allowedips, *ipnet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if res.Peers.Address6 != "" && dualstack {
|
|
||||||
var addr6 = net.IPNet{
|
|
||||||
IP: net.ParseIP(res.Peers.Address6),
|
|
||||||
Mask: net.CIDRMask(128, 128),
|
|
||||||
}
|
|
||||||
allowedips = append(allowedips, addr6)
|
|
||||||
}
|
|
||||||
if keepalive != 0 {
|
|
||||||
peer = wgtypes.PeerConfig{
|
|
||||||
PublicKey: pubkey,
|
|
||||||
PersistentKeepaliveInterval: &keepalivedur,
|
|
||||||
Endpoint: &net.UDPAddr{
|
|
||||||
IP: net.ParseIP(res.Peers.Endpoint),
|
|
||||||
Port: int(res.Peers.Listenport),
|
|
||||||
},
|
|
||||||
ReplaceAllowedIPs: true,
|
|
||||||
AllowedIPs: allowedips,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
peer = wgtypes.PeerConfig{
|
|
||||||
PublicKey: pubkey,
|
|
||||||
Endpoint: &net.UDPAddr{
|
|
||||||
IP: net.ParseIP(res.Peers.Endpoint),
|
|
||||||
Port: int(res.Peers.Listenport),
|
|
||||||
},
|
|
||||||
ReplaceAllowedIPs: true,
|
|
||||||
AllowedIPs: allowedips,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
peers = append(peers, peer)
|
|
||||||
|
|
||||||
}
|
|
||||||
fmt.Println("Finished parsing peers response")
|
|
||||||
return peers, hasGateway, gateways, err
|
|
||||||
}
|
|
||||||
|
283
netclient/functions/peers.go
Normal file
283
netclient/functions/peers.go
Normal file
@@ -0,0 +1,283 @@
|
|||||||
|
package functions
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
"github.com/gravitl/netmaker/netclient/config"
|
||||||
|
nodepb "github.com/gravitl/netmaker/grpc"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/metadata"
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
//homedir "github.com/mitchellh/go-homedir"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getPeers(macaddress string, network string, server string, dualstack bool, isIngressGateway bool) ([]wgtypes.PeerConfig, bool, []string, error) {
|
||||||
|
//need to implement checkin on server side
|
||||||
|
hasGateway := false
|
||||||
|
var gateways []string
|
||||||
|
var peers []wgtypes.PeerConfig
|
||||||
|
var wcclient nodepb.NodeServiceClient
|
||||||
|
cfg, err := config.ReadConfig(network)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Issue retrieving config for network: " + network + ". Please investigate: %v", err)
|
||||||
|
}
|
||||||
|
nodecfg := cfg.Node
|
||||||
|
keepalive := nodecfg.KeepAlive
|
||||||
|
keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fmt.Println("Registering with GRPC Server")
|
||||||
|
requestOpts := grpc.WithInsecure()
|
||||||
|
conn, err := grpc.Dial(server, requestOpts)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
|
||||||
|
}
|
||||||
|
// Instantiate the BlogServiceClient with our client connection to the server
|
||||||
|
wcclient = nodepb.NewNodeServiceClient(conn)
|
||||||
|
|
||||||
|
req := &nodepb.GetPeersReq{
|
||||||
|
Macaddress: macaddress,
|
||||||
|
Network: network,
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
fmt.Println("Authenticating with GRPC Server")
|
||||||
|
ctx, err = SetJWT(wcclient, network)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Failed to authenticate.")
|
||||||
|
return peers, hasGateway, gateways, err
|
||||||
|
}
|
||||||
|
var header metadata.MD
|
||||||
|
|
||||||
|
stream, err := wcclient.GetPeers(ctx, req, grpc.Header(&header))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error retrieving peers")
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, hasGateway, gateways, err
|
||||||
|
}
|
||||||
|
fmt.Println("Parsing peers response")
|
||||||
|
for {
|
||||||
|
res, err := stream.Recv()
|
||||||
|
// If end of stream, break the loop
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// if err, return an error
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "mongo: no documents in result") {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
fmt.Println("ERROR ENCOUNTERED WITH RESPONSE")
|
||||||
|
fmt.Println(res)
|
||||||
|
return peers, hasGateway, gateways, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pubkey, err := wgtypes.ParseKey(res.Peers.Publickey)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error parsing key")
|
||||||
|
return peers, hasGateway, gateways, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodecfg.PublicKey == res.Peers.Publickey {
|
||||||
|
fmt.Println("Peer is self. Skipping")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if nodecfg.Endpoint == res.Peers.Endpoint {
|
||||||
|
fmt.Println("Peer is self. Skipping")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var peer wgtypes.PeerConfig
|
||||||
|
var peeraddr = net.IPNet{
|
||||||
|
IP: net.ParseIP(res.Peers.Address),
|
||||||
|
Mask: net.CIDRMask(32, 32),
|
||||||
|
}
|
||||||
|
var allowedips []net.IPNet
|
||||||
|
allowedips = append(allowedips, peeraddr)
|
||||||
|
if res.Peers.Isegressgateway {
|
||||||
|
hasGateway = true
|
||||||
|
gateways = append(gateways,res.Peers.Egressgatewayrange)
|
||||||
|
_, ipnet, err := net.ParseCIDR(res.Peers.Egressgatewayrange)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("ERROR ENCOUNTERED SETTING GATEWAY")
|
||||||
|
fmt.Println("NOT SETTING GATEWAY")
|
||||||
|
fmt.Println(err)
|
||||||
|
} else {
|
||||||
|
fmt.Println(" Gateway Range: " + res.Peers.Egressgatewayrange)
|
||||||
|
allowedips = append(allowedips, *ipnet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if res.Peers.Address6 != "" && dualstack {
|
||||||
|
var addr6 = net.IPNet{
|
||||||
|
IP: net.ParseIP(res.Peers.Address6),
|
||||||
|
Mask: net.CIDRMask(128, 128),
|
||||||
|
}
|
||||||
|
allowedips = append(allowedips, addr6)
|
||||||
|
}
|
||||||
|
if keepalive != 0 {
|
||||||
|
peer = wgtypes.PeerConfig{
|
||||||
|
PublicKey: pubkey,
|
||||||
|
PersistentKeepaliveInterval: &keepalivedur,
|
||||||
|
Endpoint: &net.UDPAddr{
|
||||||
|
IP: net.ParseIP(res.Peers.Endpoint),
|
||||||
|
Port: int(res.Peers.Listenport),
|
||||||
|
},
|
||||||
|
ReplaceAllowedIPs: true,
|
||||||
|
AllowedIPs: allowedips,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
peer = wgtypes.PeerConfig{
|
||||||
|
PublicKey: pubkey,
|
||||||
|
Endpoint: &net.UDPAddr{
|
||||||
|
IP: net.ParseIP(res.Peers.Endpoint),
|
||||||
|
Port: int(res.Peers.Listenport),
|
||||||
|
},
|
||||||
|
ReplaceAllowedIPs: true,
|
||||||
|
AllowedIPs: allowedips,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
peers = append(peers, peer)
|
||||||
|
|
||||||
|
}
|
||||||
|
if isIngressGateway {
|
||||||
|
fmt.Println("Adding external peers...")
|
||||||
|
extPeers, err := getExtPeers(macaddress, network, server, dualstack)
|
||||||
|
if err == nil {
|
||||||
|
peers = append(peers, extPeers...)
|
||||||
|
fmt.Println("Added " + strconv.Itoa(len(extPeers)) + " external clients.")
|
||||||
|
} else {
|
||||||
|
fmt.Println("ERROR RETRIEVING EXTERNAL PEERS")
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fmt.Println("Finished parsing peers response")
|
||||||
|
return peers, hasGateway, gateways, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func getExtPeers(macaddress string, network string, server string, dualstack bool) ([]wgtypes.PeerConfig, error) {
|
||||||
|
var peers []wgtypes.PeerConfig
|
||||||
|
var wcclient nodepb.NodeServiceClient
|
||||||
|
cfg, err := config.ReadConfig(network)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Issue retrieving config for network: " + network + ". Please investigate: %v", err)
|
||||||
|
}
|
||||||
|
nodecfg := cfg.Node
|
||||||
|
keepalive := nodecfg.KeepAlive
|
||||||
|
keepalivedur, err := time.ParseDuration(strconv.FormatInt(int64(keepalive), 10) + "s")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Issue with format of keepalive value. Please update netconfig: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fmt.Println("Registering with GRPC Server")
|
||||||
|
requestOpts := grpc.WithInsecure()
|
||||||
|
conn, err := grpc.Dial(server, requestOpts)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to establish client connection to localhost:50051: %v", err)
|
||||||
|
}
|
||||||
|
// Instantiate the BlogServiceClient with our client connection to the server
|
||||||
|
wcclient = nodepb.NewNodeServiceClient(conn)
|
||||||
|
|
||||||
|
req := &nodepb.GetExtPeersReq{
|
||||||
|
Macaddress: macaddress,
|
||||||
|
Network: network,
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
fmt.Println("Authenticating with GRPC Server")
|
||||||
|
ctx, err = SetJWT(wcclient, network)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Failed to authenticate.")
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
var header metadata.MD
|
||||||
|
|
||||||
|
stream, err := wcclient.GetExtPeers(ctx, req, grpc.Header(&header))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error retrieving peers")
|
||||||
|
fmt.Println(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fmt.Println("Parsing peers response")
|
||||||
|
for {
|
||||||
|
res, err := stream.Recv()
|
||||||
|
// If end of stream, break the loop
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// if err, return an error
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "mongo: no documents in result") {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
fmt.Println("ERROR ENCOUNTERED WITH RESPONSE")
|
||||||
|
fmt.Println(res)
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pubkey, err := wgtypes.ParseKey(res.Extpeers.Publickey)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("error parsing key")
|
||||||
|
return peers, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if nodecfg.PublicKey == res.Extpeers.Publickey {
|
||||||
|
fmt.Println("Peer is self. Skipping")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if nodecfg.Endpoint == res.Extpeers.Endpoint {
|
||||||
|
fmt.Println("Peer is self. Skipping")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var peer wgtypes.PeerConfig
|
||||||
|
var peeraddr = net.IPNet{
|
||||||
|
IP: net.ParseIP(res.Extpeers.Address),
|
||||||
|
Mask: net.CIDRMask(32, 32),
|
||||||
|
}
|
||||||
|
var allowedips []net.IPNet
|
||||||
|
allowedips = append(allowedips, peeraddr)
|
||||||
|
|
||||||
|
if res.Extpeers.Address6 != "" && dualstack {
|
||||||
|
var addr6 = net.IPNet{
|
||||||
|
IP: net.ParseIP(res.Extpeers.Address6),
|
||||||
|
Mask: net.CIDRMask(128, 128),
|
||||||
|
}
|
||||||
|
allowedips = append(allowedips, addr6)
|
||||||
|
}
|
||||||
|
if keepalive != 0 {
|
||||||
|
peer = wgtypes.PeerConfig{
|
||||||
|
PublicKey: pubkey,
|
||||||
|
PersistentKeepaliveInterval: &keepalivedur,
|
||||||
|
Endpoint: &net.UDPAddr{
|
||||||
|
IP: net.ParseIP(res.Extpeers.Endpoint),
|
||||||
|
Port: int(res.Extpeers.Listenport),
|
||||||
|
},
|
||||||
|
ReplaceAllowedIPs: true,
|
||||||
|
AllowedIPs: allowedips,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
peer = wgtypes.PeerConfig{
|
||||||
|
PublicKey: pubkey,
|
||||||
|
Endpoint: &net.UDPAddr{
|
||||||
|
IP: net.ParseIP(res.Extpeers.Endpoint),
|
||||||
|
Port: int(res.Extpeers.Listenport),
|
||||||
|
},
|
||||||
|
ReplaceAllowedIPs: true,
|
||||||
|
AllowedIPs: allowedips,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
peers = append(peers, peer)
|
||||||
|
|
||||||
|
}
|
||||||
|
return peers, err
|
||||||
|
}
|
Reference in New Issue
Block a user