diff --git a/.gitignore b/.gitignore index 995aa2bc..defe793f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ netclient/netclient32 netclient/netclient.exe config/dnsconfig/ data/ +.vscode/ diff --git a/auth/azure-ad.go b/auth/azure-ad.go index 8ad9a8e3..ffe1a173 100644 --- a/auth/azure-ad.go +++ b/auth/azure-ad.go @@ -5,7 +5,6 @@ import ( "fmt" "io/ioutil" "net/http" - "os" "github.com/gravitl/netmaker/logger" "github.com/gravitl/netmaker/logic" @@ -36,7 +35,7 @@ func initAzureAD(redirectURL string, clientID string, clientSecret string) { ClientID: clientID, ClientSecret: clientSecret, Scopes: []string{"User.Read"}, - Endpoint: microsoft.AzureADEndpoint(os.Getenv("AZURE_TENANT")), + Endpoint: microsoft.AzureADEndpoint(servercfg.GetAzureTenant()), } } diff --git a/config/config.go b/config/config.go index c3b2fbd5..044d1a88 100644 --- a/config/config.go +++ b/config/config.go @@ -12,7 +12,7 @@ import ( "gopkg.in/yaml.v3" ) -//setting dev by default +// setting dev by default func getEnv() string { env := os.Getenv("NETMAKER_ENV") @@ -27,13 +27,13 @@ func getEnv() string { // Config : application config stored as global variable var Config *EnvironmentConfig -// EnvironmentConfig : +// EnvironmentConfig - environment conf struct type EnvironmentConfig struct { Server ServerConfig `yaml:"server"` SQL SQLConfig `yaml:"sql"` } -// ServerConfig : +// ServerConfig - server conf struct type ServerConfig struct { CoreDNSAddr string `yaml:"corednsaddr"` APIConnString string `yaml:"apiconn"` @@ -58,8 +58,8 @@ type ServerConfig struct { Version string `yaml:"version"` SQLConn string `yaml:"sqlconn"` Platform string `yaml:"platform"` - Database string `yaml:database` - CheckinInterval string `yaml:checkininterval` + Database string `yaml:"database"` + CheckinInterval string `yaml:"checkininterval"` DefaultNodeLimit int32 `yaml:"defaultnodelimit"` Verbosity int32 `yaml:"verbosity"` ServerCheckinInterval int64 `yaml:"servercheckininterval"` @@ -68,9 +68,10 @@ type ServerConfig struct { ClientSecret string `yaml:"clientsecret"` FrontendURL string `yaml:"frontendurl"` DisplayKeys string `yaml:"displaykeys"` + AzureTenant string `yaml:"azuretenant"` } -// Generic SQL Config +// SQLConfig - Generic SQL Config type SQLConfig struct { Host string `yaml:"host"` Port int32 `yaml:"port"` @@ -80,7 +81,7 @@ type SQLConfig struct { SSLMode string `yaml:"sslmode"` } -//reading in the env file +// reading in the env file func readConfig() *EnvironmentConfig { file := fmt.Sprintf("config/environments/%s.yaml", getEnv()) f, err := os.Open(file) diff --git a/controllers/user.go b/controllers/user.go index f08328c7..c9e387e3 100644 --- a/controllers/user.go +++ b/controllers/user.go @@ -23,7 +23,7 @@ func userHandlers(r *mux.Router) { r.HandleFunc("/api/users/networks/{username}", securityCheck(true, http.HandlerFunc(updateUserNetworks))).Methods("PUT") r.HandleFunc("/api/users/{username}/adm", securityCheck(true, http.HandlerFunc(updateUserAdm))).Methods("PUT") r.HandleFunc("/api/users/{username}", securityCheck(true, http.HandlerFunc(createUser))).Methods("POST") - r.HandleFunc("/api/users/{username}", securityCheck(false, continueIfUserMatch(http.HandlerFunc(deleteUser)))).Methods("DELETE") + r.HandleFunc("/api/users/{username}", securityCheck(true, http.HandlerFunc(deleteUser))).Methods("DELETE") r.HandleFunc("/api/users/{username}", securityCheck(false, continueIfUserMatch(http.HandlerFunc(getUser)))).Methods("GET") r.HandleFunc("/api/users", securityCheck(true, http.HandlerFunc(getUsers))).Methods("GET") r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods("GET") diff --git a/logic/util.go b/logic/util.go index d7ce5534..989bff4e 100644 --- a/logic/util.go +++ b/logic/util.go @@ -184,26 +184,18 @@ func GetNode(macaddress string, network string) (models.Node, error) { // GetNodePeers - fetches peers for a given node func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error) { var peers []models.Node - collection, err := database.FetchRecords(database.NODES_TABLE_NAME) + var networkNodes, egressNetworkNodes, err = getNetworkEgressAndNodes(networkName) if err != nil { - if database.IsEmptyRecord(err) { - return peers, nil - } - logger.Log(2, err.Error()) - return nil, err + return peers, nil } + udppeers, errN := database.GetPeers(networkName) if errN != nil { logger.Log(2, errN.Error()) } - for _, value := range collection { - var node = &models.Node{} + + for _, node := range networkNodes { var peer = models.Node{} - err := json.Unmarshal([]byte(value), node) - if err != nil { - logger.Log(2, err.Error()) - continue - } if node.IsEgressGateway == "yes" { // handle egress stuff peer.EgressGatewayRanges = node.EgressGatewayRanges peer.IsEgressGateway = node.IsEgressGateway @@ -211,7 +203,7 @@ func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error allow := node.IsRelayed != "yes" || !excludeRelayed if node.Network == networkName && node.IsPending != "yes" && allow { - peer = setPeerInfo(node) + peer = setPeerInfo(&node) if node.UDPHolePunch == "yes" && errN == nil && CheckEndpoint(udppeers[node.PublicKey]) { endpointstring := udppeers[node.PublicKey] endpointarr := strings.Split(endpointstring, ":") @@ -230,6 +222,11 @@ func GetNodePeers(networkName string, excludeRelayed bool) ([]models.Node, error } else { peer.AllowedIPs = append(peer.AllowedIPs, node.RelayAddrs...) } + for _, egressNode := range egressNetworkNodes { + if egressNode.IsRelayed == "yes" && StringSliceContains(node.RelayAddrs, egressNode.Address) { + peer.AllowedIPs = append(peer.AllowedIPs, egressNode.EgressGatewayRanges...) + } + } } peers = append(peers, peer) } @@ -252,6 +249,14 @@ func GetPeersList(networkName string, excludeRelayed bool, relayedNodeAddr strin network, err := GetNetwork(networkName) if err == nil { peerNode.AllowedIPs = append(peerNode.AllowedIPs, network.AddressRange) + var _, egressNetworkNodes, err = getNetworkEgressAndNodes(networkName) + if err == nil { + for _, egress := range egressNetworkNodes { + if egress.Address != relayedNodeAddr { + peerNode.AllowedIPs = append(peerNode.AllowedIPs, egress.EgressGatewayRanges...) + } + } + } } else { peerNode.AllowedIPs = append(peerNode.AllowedIPs, peerNode.RelayAddrs...) } @@ -286,6 +291,34 @@ func RandomString(length int) string { // == Private Methods == +func getNetworkEgressAndNodes(networkName string) ([]models.Node, []models.Node, error) { + var networkNodes, egressNetworkNodes []models.Node + collection, err := database.FetchRecords(database.NODES_TABLE_NAME) + if err != nil { + if database.IsEmptyRecord(err) { + return networkNodes, egressNetworkNodes, nil + } + logger.Log(2, err.Error()) + return nil, nil, err + } + + for _, value := range collection { + var node = models.Node{} + err := json.Unmarshal([]byte(value), &node) + if err != nil { + logger.Log(2, err.Error()) + continue + } + if node.Network == networkName { + networkNodes = append(networkNodes, node) + if node.IsEgressGateway == "yes" { + egressNetworkNodes = append(egressNetworkNodes, node) + } + } + } + return networkNodes, egressNetworkNodes, nil +} + func setPeerInfo(node *models.Node) models.Node { var peer models.Node peer.RelayAddrs = node.RelayAddrs @@ -326,3 +359,13 @@ func setIPForwardingLinux() error { } return nil } + +// StringSliceContains - sees if a string slice contains a string element +func StringSliceContains(slice []string, item string) bool { + for _, s := range slice { + if s == item { + return true + } + } + return false +} diff --git a/logic/wireguard.go b/logic/wireguard.go index 2090ec18..f903ae43 100644 --- a/logic/wireguard.go +++ b/logic/wireguard.go @@ -87,7 +87,8 @@ func initWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig if !ncutils.IsKernel() { var newConf string - newConf, _ = ncutils.CreateWireGuardConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, servercfg.GetCoreDNSAddr(), node.PersistentKeepalive, peers) + var nameserver string + newConf, _ = ncutils.CreateWireGuardConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, nameserver, servercfg.GetCoreDNSAddr(), node.PersistentKeepalive, peers) confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf" logger.Log(1, "writing wg conf file to:", confPath) err = ioutil.WriteFile(confPath, []byte(newConf), 0644) diff --git a/main.go b/main.go index 384302d7..c908c5bb 100644 --- a/main.go +++ b/main.go @@ -43,7 +43,7 @@ func initialize() { // Client Mode Prereq Check var authProvider = auth.InitializeAuthProvider() if authProvider != "" { - logger.Log(0, "OAuth provider, ", authProvider, ", initialized") + logger.Log(0, "OAuth provider,", authProvider+",", "initialized") } else { logger.Log(0, "no OAuth provider found or not configured, continuing without OAuth") } diff --git a/netclient/command/commands.go b/netclient/command/commands.go index fa8013df..1aecdb4b 100644 --- a/netclient/command/commands.go +++ b/netclient/command/commands.go @@ -205,8 +205,9 @@ func List(cfg config.ClientConfig) error { // Uninstall - runs uninstall command from cli func Uninstall() error { - ncutils.PrintLog("uninstalling netclient", 0) + ncutils.PrintLog("uninstalling netclient...", 0) err := functions.Uninstall() + ncutils.PrintLog("uninstalled netclient", 0) return err } diff --git a/netclient/ncutils/netclientutils_darwin.go b/netclient/ncutils/netclientutils_darwin.go index 79fc85d7..a073f989 100644 --- a/netclient/ncutils/netclientutils_darwin.go +++ b/netclient/ncutils/netclientutils_darwin.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" + "github.com/gravitl/netmaker/models" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -33,12 +34,12 @@ func GetEmbedded() error { return nil } -// CreateUserSpaceConf - creates a user space WireGuard conf -func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { - peersString, err := parsePeers(perskeepalive, peers) +// CreateWireGuardConf - creates a WireGuard conf string +func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) { + peersString, err := parsePeers(node.PersistentKeepalive, peers) var listenPortString string - if mtu <= 0 { - mtu = 1280 + if node.MTU <= 0 { + node.MTU = 1280 } if listenPort != "" { listenPortString += "ListenPort = " + listenPort @@ -55,9 +56,9 @@ MTU = %s %s `, - address+"/32", + node.Address+"/32", privatekey, - strconv.Itoa(int(mtu)), + strconv.Itoa(int(node.MTU)), listenPortString, peersString) return config, nil diff --git a/netclient/ncutils/netclientutils_freebsd.go b/netclient/ncutils/netclientutils_freebsd.go index 19d3aa19..bbacdc6c 100644 --- a/netclient/ncutils/netclientutils_freebsd.go +++ b/netclient/ncutils/netclientutils_freebsd.go @@ -3,13 +3,15 @@ package ncutils import ( "context" "fmt" - "golang.zx2c4.com/wireguard/wgctrl/wgtypes" "log" "os/exec" "strconv" "strings" "syscall" "time" + + "github.com/gravitl/netmaker/models" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) // RunCmdFormatted - run a command formatted for freebsd @@ -41,12 +43,12 @@ func RunCmd(command string, printerr bool) (string, error) { return string(out), err } -// CreateUserSpaceConf - creates a user space WireGuard conf -func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { - peersString, err := parsePeers(perskeepalive, peers) +// CreateWireGuardConf - creates a WireGuard conf string +func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) { + peersString, err := parsePeers(node.PersistentKeepalive, peers) var listenPortString string - if mtu <= 0 { - mtu = 1280 + if node.MTU <= 0 { + node.MTU = 1280 } if listenPort != "" { listenPortString += "ListenPort = " + listenPort @@ -63,9 +65,9 @@ MTU = %s %s `, - address+"/32", + node.Address+"/32", privatekey, - strconv.Itoa(int(mtu)), + strconv.Itoa(int(node.MTU)), listenPortString, peersString) return config, nil diff --git a/netclient/ncutils/netclientutils_linux.go b/netclient/ncutils/netclientutils_linux.go index ae40c292..bc4c399e 100644 --- a/netclient/ncutils/netclientutils_linux.go +++ b/netclient/ncutils/netclientutils_linux.go @@ -6,6 +6,7 @@ import ( "strconv" "strings" + "github.com/gravitl/netmaker/models" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -33,15 +34,23 @@ func GetEmbedded() error { } // CreateWireGuardConf - creates a user space WireGuard conf -func CreateWireGuardConf(address string, privatekey string, listenPort string, mtu int32, dns string, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { - peersString, err := parsePeers(perskeepalive, peers) - var listenPortString string - if mtu <= 0 { - mtu = 1280 +func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) { + peersString, err := parsePeers(node.PersistentKeepalive, peers) + var listenPortString, postDownString, postUpString string + if node.MTU <= 0 { + node.MTU = 1280 } + if node.PostDown != "" { + postDownString = fmt.Sprintf("PostDown = %s", node.PostDown) + } + if node.PostUp != "" { + postUpString = fmt.Sprintf("PostUp = %s", node.PostUp) + } + if listenPort != "" { - listenPortString += "ListenPort = " + listenPort + listenPortString = fmt.Sprintf("ListenPort = %s", listenPort) } + if err != nil { return "", err } @@ -51,14 +60,18 @@ DNS = %s PrivateKey = %s MTU = %s %s +%s +%s %s `, - address+"/32", + node.Address+"/32", dns, privatekey, - strconv.Itoa(int(mtu)), + strconv.Itoa(int(node.MTU)), + postDownString, + postUpString, listenPortString, peersString) return config, nil diff --git a/netclient/ncutils/netclientutils_windows.go b/netclient/ncutils/netclientutils_windows.go index 45974297..5acf73a7 100644 --- a/netclient/ncutils/netclientutils_windows.go +++ b/netclient/ncutils/netclientutils_windows.go @@ -10,6 +10,7 @@ import ( "strings" "syscall" + "github.com/gravitl/netmaker/models" "golang.zx2c4.com/wireguard/wgctrl/wgtypes" ) @@ -47,12 +48,12 @@ func RunCmdFormatted(command string, printerr bool) (string, error) { return string(out), err } -// CreateUserSpaceConf - creates a user space WireGuard conf -func CreateUserSpaceConf(address string, privatekey string, listenPort string, mtu int32, perskeepalive int32, peers []wgtypes.PeerConfig) (string, error) { - peersString, err := parsePeers(perskeepalive, peers) +// CreateWireGuardConf - creates a WireGuard conf string +func CreateWireGuardConf(node *models.Node, privatekey string, listenPort string, dns string, peers []wgtypes.PeerConfig) (string, error) { + peersString, err := parsePeers(node.PersistentKeepalive, peers) var listenPortString string - if mtu <= 0 { - mtu = 1280 + if node.MTU <= 0 { + node.MTU = 1280 } if listenPort != "" { listenPortString += "ListenPort = " + listenPort @@ -69,9 +70,9 @@ MTU = %s %s `, - address+"/32", + node.Address+"/32", privatekey, - strconv.Itoa(int(mtu)), + strconv.Itoa(int(node.MTU)), listenPortString, peersString) return config, nil diff --git a/netclient/wireguard/common.go b/netclient/wireguard/common.go index 53613790..f65016dd 100644 --- a/netclient/wireguard/common.go +++ b/netclient/wireguard/common.go @@ -149,9 +149,9 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig } var newConf string if node.UDPHolePunch != "yes" { - newConf, _ = ncutils.CreateWireGuardConf(node.Address, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), node.MTU, nameserver, node.PersistentKeepalive, peers) + newConf, _ = ncutils.CreateWireGuardConf(node, key.String(), strconv.FormatInt(int64(node.ListenPort), 10), nameserver, peers) } else { - newConf, _ = ncutils.CreateWireGuardConf(node.Address, key.String(), "", node.MTU, nameserver, node.PersistentKeepalive, peers) + newConf, _ = ncutils.CreateWireGuardConf(node, key.String(), "", nameserver, peers) } confPath := ncutils.GetNetclientPathSpecific() + ifacename + ".conf" ncutils.PrintLog("writing wg conf file to: "+confPath, 1) @@ -182,7 +182,7 @@ func InitWireguard(node *models.Node, privkey string, peers []wgtypes.PeerConfig } else { d, _ := wgclient.Device(deviceiface) for d != nil && d.Name == deviceiface { - _ = RemoveConf(ifacename, false) // remove interface first + RemoveConf(ifacename, false) // remove interface first time.Sleep(time.Second >> 2) d, _ = wgclient.Device(deviceiface) } diff --git a/netclient/wireguard/unix.go b/netclient/wireguard/unix.go index 8b557d0a..6e9e52af 100644 --- a/netclient/wireguard/unix.go +++ b/netclient/wireguard/unix.go @@ -1,6 +1,7 @@ package wireguard import ( + "fmt" "io/ioutil" "log" "os" @@ -86,7 +87,7 @@ func SyncWGQuickConf(iface string, confPath string) error { // RemoveWGQuickConf - calls wg-quick down func RemoveWGQuickConf(confPath string, printlog bool) error { - _, err := ncutils.RunCmd("wg-quick down "+confPath, printlog) + _, err := ncutils.RunCmd(fmt.Sprintf("wg-quick down %s", confPath), printlog) return err } diff --git a/servercfg/serverconf.go b/servercfg/serverconf.go index fb7a67cb..7c1ebd74 100644 --- a/servercfg/serverconf.go +++ b/servercfg/serverconf.go @@ -502,6 +502,17 @@ func GetAuthProviderInfo() []string { return []string{"", "", ""} } +// GetAzureTenant - retrieve the azure tenant ID from env variable or config file +func GetAzureTenant() string { + var azureTenant = "" + if os.Getenv("AZURE_TENANT") != "" { + azureTenant = os.Getenv("AZURE_TENANT") + } else if config.Config.Server.AzureTenant != "" { + azureTenant = config.Config.Server.AzureTenant + } + return azureTenant +} + // GetMacAddr - get's mac address func getMacAddr() string { ifas, err := net.Interfaces()