got grpc private comms working

This commit is contained in:
root
2021-05-29 19:06:35 +00:00
18 changed files with 283 additions and 57 deletions

View File

@@ -21,6 +21,6 @@ services:
ports: ports:
- "80:80" - "80:80"
environment: environment:
BACKEND_URL: "http://34.228.52.243:8081" BACKEND_URL: "http://3.236.111.47:8081"
volumes: volumes:
mongovol: {} mongovol: {}

View File

@@ -78,8 +78,8 @@ func readConfig() *EnvironmentConfig {
if err != nil { if err != nil {
//log.Fatal(err) //log.Fatal(err)
//os.Exit(2) //os.Exit(2)
log.Println("Unable to open config file at config/environments/" + getEnv()) //log.Println("Unable to open config file at config/environments/" + getEnv())
log.Println("Will proceed with defaults or enironment variables (no config file).") //log.Println("Will proceed with defaults or enironment variables (no config file).")
return &cfg return &cfg
} }
defer f.Close() defer f.Close()

View File

@@ -11,6 +11,7 @@ import (
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"github.com/gravitl/netmaker/mongoconn" "github.com/gravitl/netmaker/mongoconn"
"github.com/gravitl/netmaker/servercfg" "github.com/gravitl/netmaker/servercfg"
"github.com/gravitl/netmaker/serverctl"
"go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options" "go.mongodb.org/mongo-driver/mongo/options"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@@ -299,6 +300,31 @@ func DeleteNode(macaddress string, network string) (bool, error) {
return deleted, err return deleted, err
} }
func DeleteIntClient(clientid string) (bool, error) {
deleted := false
collection := mongoconn.Client.Database("netmaker").Collection("intclients")
filter := bson.M{"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()
err = serverctl.ReconfigureServerWireGuard()
return deleted, err
}
func GetNode(macaddress string, network string) (models.Node, error) { func GetNode(macaddress string, network string) (models.Node, error) {
var node models.Node var node models.Node
@@ -315,6 +341,22 @@ func GetNode(macaddress string, network string) (models.Node, error) {
return node, err return node, err
} }
func GetIntClient(clientid string) (models.IntClient, error) {
var client models.IntClient
collection := mongoconn.Client.Database("netmaker").Collection("intclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"clientid": clientid}
err := collection.FindOne(ctx, filter, options.FindOne().SetProjection(bson.M{"_id": 0})).Decode(&clientid)
defer cancel()
return client, err
}
func CreateNode(node models.Node, networkName string) (models.Node, error) { func CreateNode(node models.Node, networkName string) (models.Node, error) {
//encrypt that password so we never see it again //encrypt that password so we never see it again

View File

@@ -282,12 +282,6 @@ func CreateExtClient(extclient models.ExtClient) error {
extclient.ClientID = clientname extclient.ClientID = clientname
} }
if extclient.ClientID == "" {
cid := StringWithCharset(7, charset)
clientid := "client-" + cid
extclient.ClientID = clientid
}
extclient.LastModified = time.Now().Unix() extclient.LastModified = time.Now().Unix()
collection := mongoconn.Client.Database("netmaker").Collection("extclients") collection := mongoconn.Client.Database("netmaker").Collection("extclients")

View File

@@ -24,6 +24,7 @@ func intClientHandlers(r *mux.Router) {
r.HandleFunc("/api/intclient/{clientid}", securityCheck(http.HandlerFunc(deleteIntClient))).Methods("DELETE") r.HandleFunc("/api/intclient/{clientid}", securityCheck(http.HandlerFunc(deleteIntClient))).Methods("DELETE")
r.HandleFunc("/api/intclient/{clientid}", securityCheck(http.HandlerFunc(updateIntClient))).Methods("PUT") r.HandleFunc("/api/intclient/{clientid}", securityCheck(http.HandlerFunc(updateIntClient))).Methods("PUT")
r.HandleFunc("/api/intclient/register", http.HandlerFunc(registerIntClient)).Methods("POST") r.HandleFunc("/api/intclient/register", http.HandlerFunc(registerIntClient)).Methods("POST")
r.HandleFunc("/api/intclient/{clientid}", http.HandlerFunc(deleteIntClient)).Methods("DELETE")
} }
func getAllIntClients(w http.ResponseWriter, r *http.Request) { func getAllIntClients(w http.ResponseWriter, r *http.Request) {
@@ -45,31 +46,39 @@ func deleteAllIntClients(w http.ResponseWriter, r *http.Request) {
returnErrorResponse(w, r, formatError(err, "internal")) returnErrorResponse(w, r, formatError(err, "internal"))
return return
} }
//Return all the extclients in JSON format
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
} }
func deleteIntClient(w http.ResponseWriter, r *http.Request) { func deleteIntClient(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
err := functions.DeleteIntClient() // get params
var params = mux.Vars(r)
success, err := DeleteIntClient(params["clientid"])
if err != nil { if err != nil {
returnErrorResponse(w, r, formatError(err, "internal")) returnErrorResponse(w, r, formatError(err, "internal"))
return return
} else if !success {
err = errors.New("Could not delete intclient " + params["clientid"])
returnErrorResponse(w, r, formatError(err, "internal"))
return
} }
//Return all the extclients in JSON format returnSuccessResponse(w, r, params["clientid"]+" deleted.")
w.WriteHeader(http.StatusOK)
} }
func getIntClient(w http.ResponseWriter, r *http.Request) { func getIntClient(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
clients, err := functions.GetIntClient() var params = mux.Vars(r)
client, err := GetIntClient(params["clientid"])
if err != nil { if err != nil {
returnErrorResponse(w, r, formatError(err, "internal")) returnErrorResponse(w, r, formatError(err, "internal"))
return return
} }
//Return all the extclients in JSON format
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(clients) json.NewEncoder(w).Encode(client)
} }
func updateIntClient(w http.ResponseWriter, r *http.Request) { func updateIntClient(w http.ResponseWriter, r *http.Request) {
@@ -120,14 +129,14 @@ func RegisterIntClient(client models.IntClient) (models.IntClient, error) {
} }
if client.Address == "" { if client.Address == "" {
newAddress, err := functions.UniqueAddress6(client.Network) newAddress, err := functions.UniqueAddress(client.Network)
if err != nil { if err != nil {
return client, err return client, err
} }
if newAddress == "" { if newAddress == "" {
return client, errors.New("Could not find an address.") return client, errors.New("Could not find an address.")
} }
client.Address6 = newAddress client.Address = newAddress
} }
if client.Network == "" { client.Network = "comms" } if client.Network == "" { client.Network = "comms" }
server, err := serverctl.GetServerWGConf() server, err := serverctl.GetServerWGConf()
@@ -135,10 +144,18 @@ func RegisterIntClient(client models.IntClient) (models.IntClient, error) {
return client, err return client, err
} }
client.ServerEndpoint = server.ServerEndpoint client.ServerEndpoint = server.ServerEndpoint
client.ServerAPIEndpoint = servercfg.GetAPIHost() + ":" + servercfg.GetAPIPort()
client.ServerAddress = server.ServerAddress client.ServerAddress = server.ServerAddress
client.ServerPort = server.ServerPort client.ServerPort = server.ServerPort
client.ServerKey = server.ServerKey client.ServerKey = server.ServerKey
if client.ClientID == "" {
clientid := StringWithCharset(7, charset)
clientname := "client-" + clientid
client.ClientID = clientname
}
collection := mongoconn.Client.Database("netmaker").Collection("intclients") collection := mongoconn.Client.Database("netmaker").Collection("intclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
// insert our network into the network table // insert our network into the network table

View File

@@ -702,9 +702,15 @@ func UniqueAddress(networkName string) (string, error) {
offset = false offset = false
continue continue
} }
if IsIPUnique(networkName, ip.String()) && IsIPUniqueExtClients(networkName, ip.String()) { if networkName == "comms" {
return ip.String(), err if IsIPUniqueClients(networkName, ip.String()) {
} return ip.String(), err
}
} else {
if IsIPUnique(networkName, ip.String()) && IsIPUniqueExtClients(networkName, ip.String()) {
return ip.String(), err
}
}
} }
//TODO //TODO
@@ -894,6 +900,33 @@ func IsIP6UniqueClients(network string, ip string) bool {
return isunique return isunique
} }
//checks if IP is unique in the address range
//used by UniqueAddress
func IsIPUniqueClients(network string, ip string) bool {
var client models.IntClient
isunique := true
collection := mongoconn.Client.Database("netmaker").Collection("intclients")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
filter := bson.M{"address": ip, "network": network}
err := collection.FindOne(ctx, filter).Decode(&client)
defer cancel()
if err != nil {
return isunique
}
if client.Address == ip {
isunique = false
}
return isunique
}
//called once key has been used by createNode //called once key has been used by createNode
//reduces value by one and deletes if necessary //reduces value by one and deletes if necessary
func DecrimentKey(networkName string, keyvalue string) { func DecrimentKey(networkName string, keyvalue string) {

15
main.go
View File

@@ -61,14 +61,19 @@ func main() {
} }
if servercfg.IsGRPCWireGuard() { if servercfg.IsGRPCWireGuard() {
err = serverctl.InitServerWireGuard() exists, err := functions.ServerIntClientExists()
if err != nil { if err == nil {
log.Fatal(err) if !exists {
} err = serverctl.InitServerWireGuard()
if err != nil {
log.Fatal(err)
}
}
}
err = serverctl.ReconfigureServerWireGuard() err = serverctl.ReconfigureServerWireGuard()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
//NOTE: Removed Check and Logic for DNS Mode //NOTE: Removed Check and Logic for DNS Mode
//Reasoning. DNS Logic is very small on server. Can run with little/no impact. Just sets a tiny config file. //Reasoning. DNS Logic is very small on server. Can run with little/no impact. Just sets a tiny config file.

View File

@@ -1,8 +1,7 @@
package models package models
import (
)
type IntClient struct { type IntClient struct {
ClientID string `json:"clientid" bson:"clientid"`
PrivateKey string `json:"privatekey" bson:"privatekey"` PrivateKey string `json:"privatekey" bson:"privatekey"`
PublicKey string `json:"publickey" bson:"publickey"` PublicKey string `json:"publickey" bson:"publickey"`
AccessKey string `json:"accesskey" bson:"accesskey"` AccessKey string `json:"accesskey" bson:"accesskey"`
@@ -10,6 +9,7 @@ type IntClient struct {
Address6 string `json:"address6" bson:"address6"` Address6 string `json:"address6" bson:"address6"`
Network string `json:"network" bson:"network"` Network string `json:"network" bson:"network"`
ServerEndpoint string `json:"serverendpoint" bson:"serverendpoint"` ServerEndpoint string `json:"serverendpoint" bson:"serverendpoint"`
ServerAPIEndpoint string `json:"serverapiendpoint" bson:"serverapiendpoint"`
ServerAddress string `json:"serveraddress" bson:"serveraddress"` ServerAddress string `json:"serveraddress" bson:"serveraddress"`
ServerPort string `json:"serverport" bson:"serverport"` ServerPort string `json:"serverport" bson:"serverport"`
ServerKey string `json:"serverkey" bson:"serverkey"` ServerKey string `json:"serverkey" bson:"serverkey"`

View File

@@ -87,12 +87,19 @@ func Pull(cfg config.ClientConfig) error {
return nil return nil
} }
func List(cfg config.ClientConfig) error {
err := functions.List()
return err
}
func Status(cfg config.ClientConfig) error { func Status(cfg config.ClientConfig) error {
log.Println("retrieving network status") log.Println("retrieving network status")
return nil return nil
} }
func Uninstall(cfg config.ClientConfig) error { func Uninstall(cfg config.GlobalConfig) error {
log.Println("uninstalling") log.Println("Uninstalling netclient")
return nil err := functions.Uninstall()
err = functions.Unregister(cfg)
return err
} }

View File

@@ -30,6 +30,14 @@ type ServerConfig struct {
AccessKey string `yaml:"accesskey"` AccessKey string `yaml:"accesskey"`
} }
type ListConfig struct {
Name string `yaml:"name"`
Interface string `yaml:"interface"`
PrivateIPv4 string `yaml:"wgaddress"`
PrivateIPv6 string `yaml:"wgaddress6"`
PublicEndpoint string `yaml:"endpoint"`
}
type NodeConfig struct { type NodeConfig struct {
Name string `yaml:"name"` Name string `yaml:"name"`
Interface string `yaml:"interface"` Interface string `yaml:"interface"`
@@ -412,7 +420,7 @@ func GetCLIConfig(c *cli.Context) (ClientConfig, error){
} }
func GetCLIConfigRegister(c *cli.Context) (GlobalConfig, error){ func GetCLIConfigRegister(c *cli.Context) (GlobalConfig, error){
var cfg GlobalConfig var cfg GlobalConfig
if c.String("token") != "" { if c.String("token") != "" {
tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token")) tokenbytes, err := base64.StdEncoding.DecodeString(c.String("token"))
if err != nil { if err != nil {

View File

@@ -2,6 +2,7 @@ package functions
import ( import (
"fmt" "fmt"
"encoding/json"
"errors" "errors"
"context" "context"
"net/http" "net/http"
@@ -258,7 +259,21 @@ func GetNode(network string) nodepb.Node {
return node return node
} }
func Uninstall() error {
networks, err := GetNetworks()
if err != nil {
log.Println("unable to retrieve networks: ", err)
log.Println("continuing uninstall without leaving networks")
} else {
for _, network := range networks {
err = LeaveNetwork(network)
if err != nil {
log.Println("Encounter issue leaving network " + network + ": ", err)
}
}
}
return err
}
func LeaveNetwork(network string) error { func LeaveNetwork(network string) error {
//need to implement checkin on server side //need to implement checkin on server side
@@ -330,3 +345,59 @@ func DeleteInterface(ifacename string, postdown string) error{
} }
return err return err
} }
func List() error{
networks, err := GetNetworks()
if err != nil {
return err
}
for _, network := range networks {
cfg, err := config.ReadConfig(network)
if err == nil {
//cfg2 := *cfg
listconfig := &config.ListConfig{
Name: cfg.Node.Name,
Interface: cfg.Node.Interface,
PrivateIPv4: cfg.Node.WGAddress,
PrivateIPv6: cfg.Node.WGAddress6,
PublicEndpoint: cfg.Node.Endpoint,
}
jsoncfg, _ := json.Marshal(listconfig)
fmt.Println(network + ": " + string(jsoncfg))
} else {
fmt.Println(network + ": Could not retrieve network configuration.")
}
}
return nil
}
func GetNetworks() ([]string, error) {
var networks []string
files, err := ioutil.ReadDir("/etc/netclient")
if err != nil {
return networks, err
}
for _, f := range files {
if strings.Contains(f.Name(), "netconfig-") && !strings.Contains(f.Name(), "global-001"){
networkname := stringAfter(f.Name(), "netconfig-")
networks = append(networks, networkname)
}
}
return networks, err
}
func stringAfter(original string, substring string) string {
position := strings.LastIndex(original, substring)
if position == -1 {
return ""
}
adjustedPosition := position + len(substring)
if adjustedPosition >= len(original) {
return ""
}
return original[adjustedPosition:len(original)]
}

View File

@@ -1,10 +1,12 @@
package functions package functions
import ( import (
"time"
"log" "log"
"io/ioutil" "io/ioutil"
"bytes" "bytes"
"github.com/gravitl/netmaker/netclient/config" "github.com/gravitl/netmaker/netclient/config"
"github.com/gravitl/netmaker/netclient/local"
"github.com/gravitl/netmaker/netclient/wireguard" "github.com/gravitl/netmaker/netclient/wireguard"
"github.com/gravitl/netmaker/models" "github.com/gravitl/netmaker/models"
"encoding/json" "encoding/json"
@@ -57,3 +59,24 @@ func Register(cfg config.GlobalConfig) error {
return err return err
} }
func Unregister(cfg config.GlobalConfig) error {
client := &http.Client{ Timeout: 7 * time.Second,}
req, err := http.NewRequest("DELETE", "http://"+cfg.Client.ServerEndpoint+"/api/intclient/"+cfg.Client.ClientID, nil)
if err != nil {
return err
}
res, err := client.Do(req)
if res == nil {
err = local.WipeGRPCClient()
if err == nil {
log.Println("successfully removed grpc client interface")
}
} else {
if res.StatusCode != http.StatusOK {
return errors.New("request to server failed: " + res.Status)
defer res.Body.Close()
}
}
return err
}

View File

@@ -314,6 +314,22 @@ func WipeLocal(network string) error{
} }
func WipeGRPCClient() error{
home := "/etc/netclient"
_ = os.Remove(home + "/netconfig-global-001")
ipExec, err := exec.LookPath("ip")
cmdIPLinkDel := &exec.Cmd {
Path: ipExec,
Args: []string{ ipExec, "link", "del", "grpc-wg-001" },
Stdout: os.Stdout,
Stderr: os.Stdout,
}
err = cmdIPLinkDel.Run()
return err
}
func HasNetwork(network string) bool{ func HasNetwork(network string) bool{
return FileExists("/etc/systemd/system/netclient-"+network+".timer") || return FileExists("/etc/systemd/system/netclient-"+network+".timer") ||

View File

@@ -281,8 +281,8 @@ func main() {
}, },
}, },
{ {
Name: "status", Name: "list",
Usage: "Check network status.", Usage: "Get list of networks.",
Flags: cliFlags, Flags: cliFlags,
// the action, or code that will be executed when // the action, or code that will be executed when
// we execute our `ns` command // we execute our `ns` command
@@ -291,7 +291,7 @@ func main() {
if err != nil { if err != nil {
return err return err
} }
err = command.Status(cfg) err = command.List(cfg)
return err return err
}, },
}, },
@@ -302,11 +302,13 @@ func main() {
// the action, or code that will be executed when // the action, or code that will be executed when
// we execute our `ns` command // we execute our `ns` command
Action: func(c *cli.Context) error { Action: func(c *cli.Context) error {
cfg, err := config.GetCLIConfig(c) cfg, err := config.ReadGlobalConfig()
if err != nil { if err != nil {
return err return err
} }
err = command.Uninstall(cfg) var gconf config.GlobalConfig
gconf = *cfg
err = command.Uninstall(gconf)
return err return err
}, },
}, },

View File

@@ -90,27 +90,35 @@ func GetAPIPort() string {
func GetGRPCHost() string { func GetGRPCHost() string {
serverhost := "127.0.0.1" serverhost := "127.0.0.1"
if os.Getenv("SERVER_GRPC_HOST") != "" { if IsGRPCWireGuard() {
serverhost = os.Getenv("SERVER_GRPC_HOST") serverhost = GetGRPCWGAddress()
} else if config.Config.Server.GRPCHost != "" {
serverhost = config.Config.Server.GRPCHost
} else if os.Getenv("SERVER_HOST") != "" {
serverhost = os.Getenv("SERVER_HOST")
} else { } else {
remoteip, _ := GetPublicIP() if os.Getenv("SERVER_GRPC_HOST") != "" {
if remoteip != "" { serverhost = os.Getenv("SERVER_GRPC_HOST")
serverhost = remoteip } else if config.Config.Server.GRPCHost != "" {
serverhost = config.Config.Server.GRPCHost
} else if os.Getenv("SERVER_HOST") != "" {
serverhost = os.Getenv("SERVER_HOST")
} else {
remoteip, _ := GetPublicIP()
if remoteip != "" {
serverhost = remoteip
}
} }
} }
return serverhost return serverhost
} }
func GetGRPCPort() string { func GetGRPCPort() string {
grpcport := "50051" grpcport := "50051"
if os.Getenv("GRPC_PORT") != "" { if IsGRPCWireGuard() {
grpcport = os.Getenv("GRPC_PORT") grpcport = GetGRPCWGPort()
} else if config.Config.Server.GRPCPort != "" { } else {
grpcport = config.Config.Server.GRPCPort if os.Getenv("GRPC_PORT") != "" {
} grpcport = os.Getenv("GRPC_PORT")
} else if config.Config.Server.GRPCPort != "" {
grpcport = config.Config.Server.GRPCPort
}
}
return grpcport return grpcport
} }
func GetMasterKey() string { func GetMasterKey() string {

View File

@@ -49,7 +49,7 @@ func GetGRPCWGAddress() string {
return address return address
} }
func GetGRPCWGAddressRange() string { func GetGRPCWGAddressRange() string {
address := "fd73:0093:84f3:a13d::/64" address := "10.101.0.0/16"
if os.Getenv("SERVER_GRPC_WG_ADDRESS_RANGE") != "" { if os.Getenv("SERVER_GRPC_WG_ADDRESS_RANGE") != "" {
address = os.Getenv("SERVER_GRPC_WG_ADDRESS_RANGE") address = os.Getenv("SERVER_GRPC_WG_ADDRESS_RANGE")
} else if config.Config.WG.GRPCWGAddressRange != "" { } else if config.Config.WG.GRPCWGAddressRange != "" {

View File

@@ -88,10 +88,10 @@ func CreateCommsNetwork() (bool, error) {
var network models.Network var network models.Network
network.NetID = "comms" network.NetID = "comms"
network.IsIPv6 = "yes" network.IsIPv6 = "no"
network.IsIPv4 = "no" network.IsIPv4 = "yes"
network.IsGRPCHub = "yes" network.IsGRPCHub = "yes"
network.AddressRange6 = servercfg.GetGRPCWGAddressRange() network.AddressRange = servercfg.GetGRPCWGAddressRange()
network.DisplayName = "comms" network.DisplayName = "comms"
network.SetDefaults() network.SetDefaults()
network.SetNodesLastModified() network.SetNodesLastModified()

View File

@@ -155,7 +155,7 @@ func ReconfigureServerWireGuard() error {
if peer.Address != "" { if peer.Address != "" {
var peeraddr = net.IPNet{ var peeraddr = net.IPNet{
IP: net.ParseIP(peer.Address), IP: net.ParseIP(peer.Address),
Mask: net.CIDRMask(128, 128), Mask: net.CIDRMask(32, 32),
} }
allowedips = append(allowedips, peeraddr) allowedips = append(allowedips, peeraddr)
} }