Browse Source

adapted sso to host registration

0xdcarns 2 years ago
parent
commit
18c9bcc58f

+ 3 - 3
auth/auth.go

@@ -114,10 +114,10 @@ func HandleAuthCallback(w http.ResponseWriter, r *http.Request) {
 	if err == nil || errors.Is(err, netcache.ErrExpired) {
 	if err == nil || errors.Is(err, netcache.ErrExpired) {
 		switch len(state) {
 		switch len(state) {
 		case node_signin_length:
 		case node_signin_length:
-			logger.Log(0, "proceeding with node SSO callback")
-			HandleNodeSSOCallback(w, r)
+			logger.Log(1, "proceeding with host SSO callback")
+			HandleHostSSOCallback(w, r)
 		case headless_signin_length:
 		case headless_signin_length:
-			logger.Log(0, "proceeding with headless SSO callback")
+			logger.Log(1, "proceeding with headless SSO callback")
 			HandleHeadlessSSOCallback(w, r)
 			HandleHeadlessSSOCallback(w, r)
 		default:
 		default:
 			logger.Log(1, "invalid state length: ", fmt.Sprintf("%d", len(state)))
 			logger.Log(1, "invalid state length: ", fmt.Sprintf("%d", len(state)))

+ 258 - 0
auth/host_session.go

@@ -0,0 +1,258 @@
+package auth
+
+import (
+	"encoding/json"
+	"fmt"
+	"strings"
+	"time"
+
+	"github.com/google/uuid"
+	"github.com/gorilla/websocket"
+	"github.com/gravitl/netmaker/logger"
+	"github.com/gravitl/netmaker/logic"
+	"github.com/gravitl/netmaker/logic/hostactions"
+	"github.com/gravitl/netmaker/logic/pro/netcache"
+	"github.com/gravitl/netmaker/models"
+	"github.com/gravitl/netmaker/mq"
+	"github.com/gravitl/netmaker/servercfg"
+)
+
+// SessionHandler - called by the HTTP router when user
+// is calling netclient with join/register -s parameter in order to authenticate
+// via SSO mechanism by OAuth2 protocol flow.
+// This triggers a session start and it is managed by the flow implemented here and callback
+// When this method finishes - the auth flow has finished either OK or by timeout or any other error occured
+func SessionHandler(conn *websocket.Conn) {
+	defer conn.Close()
+	// If reached here we have a session from user to handle...
+	messageType, message, err := conn.ReadMessage()
+	if err != nil {
+		logger.Log(0, "Error during message reading:", err.Error())
+		return
+	}
+
+	var registerMessage models.RegisterMsg
+	if err = json.Unmarshal(message, &registerMessage); err != nil {
+		logger.Log(0, "Failed to unmarshall data err=", err.Error())
+		return
+	}
+	if registerMessage.RegisterHost.ID == uuid.Nil {
+		logger.Log(0, "invalid host registration attempted")
+		return
+	}
+
+	req := new(netcache.CValue)
+	req.Value = string(registerMessage.RegisterHost.ID.String())
+	req.Network = registerMessage.Network
+	req.Host = registerMessage.RegisterHost
+	req.ALL = registerMessage.JoinAll
+	req.Pass = ""
+	req.User = registerMessage.User
+	if len(req.User) > 0 && len(registerMessage.Password) == 0 {
+		logger.Log(0, "invalid host registration attempted")
+		return
+	}
+	// Add any extra parameter provided in the configuration to the Authorize Endpoint request??
+	stateStr := logic.RandomString(node_signin_length)
+	if err := netcache.Set(stateStr, req); err != nil {
+		logger.Log(0, "Failed to process sso request -", err.Error())
+		return
+	}
+	// Wait for the user to finish his auth flow...
+	timeout := make(chan bool, 1)
+	answer := make(chan netcache.CValue, 1)
+	defer close(answer)
+	defer close(timeout)
+
+	if len(registerMessage.User) > 0 { // handle basic auth
+		logger.Log(0, "user registration attempted with host:", registerMessage.RegisterHost.Name, "user:", registerMessage.User)
+
+		if !servercfg.IsBasicAuthEnabled() {
+			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+			if err != nil {
+				logger.Log(0, "error during message writing:", err.Error())
+			}
+		}
+		_, err := logic.VerifyAuthRequest(models.UserAuthParams{
+			UserName: registerMessage.User,
+			Password: registerMessage.Password,
+		})
+		if err != nil {
+			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+			if err != nil {
+				logger.Log(0, "error during message writing:", err.Error())
+			}
+			return
+		}
+		req.Pass = req.Host.ID.String()
+
+		if err = netcache.Set(stateStr, req); err != nil { // give the user's host access in the DB
+			logger.Log(0, "machine failed to complete join on network,", registerMessage.Network, "-", err.Error())
+			return
+		}
+	} else { // handle SSO / OAuth
+		if auth_provider == nil {
+			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+			if err != nil {
+				logger.Log(0, "error during message writing:", err.Error())
+			}
+			return
+		}
+		logger.Log(0, "user registration attempted with host:", registerMessage.RegisterHost.Name, "via SSO")
+		redirectUrl = fmt.Sprintf("https://%s/api/oauth/register/%s", servercfg.GetAPIConnString(), stateStr)
+		err = conn.WriteMessage(messageType, []byte(redirectUrl))
+		if err != nil {
+			logger.Log(0, "error during message writing:", err.Error())
+		}
+	}
+
+	go func() {
+		for {
+			cachedReq, err := netcache.Get(stateStr)
+			if err != nil {
+				if strings.Contains(err.Error(), "expired") {
+					logger.Log(1, "timeout occurred while waiting for SSO registration")
+					timeout <- true
+					break
+				}
+				continue
+			} else if len(cachedReq.User) > 0 {
+				logger.Log(0, "host SSO process completed for user", cachedReq.User)
+				answer <- *cachedReq
+				break
+			}
+			time.Sleep(500) // try it 2 times per second to see if auth is completed
+		}
+	}()
+
+	select {
+	case result := <-answer: // a read from req.answerCh has occurred
+		// add the host, if not exists, handle like enrollment registration
+		hostPass := result.Host.HostPass
+		if !logic.HostExists(&result.Host) { // check if host already exists, add if not
+			if servercfg.GetBrokerType() == servercfg.EmqxBrokerType {
+				if err := mq.CreateEmqxUser(result.Host.ID.String(), result.Host.HostPass, false); err != nil {
+					logger.Log(0, "failed to create host credentials for EMQX: ", err.Error())
+					return
+				}
+				if err := mq.CreateHostACL(result.Host.ID.String(), servercfg.GetServerInfo().Server); err != nil {
+					logger.Log(0, "failed to add host ACL rules to EMQX: ", err.Error())
+					return
+				}
+			}
+			logic.CheckHostPorts(&result.Host)
+			if err := logic.CreateHost(&result.Host); err != nil {
+				handleHostRegErr(conn, err)
+				return
+			}
+		}
+		key, keyErr := logic.RetrievePublicTrafficKey()
+		if keyErr != nil {
+			handleHostRegErr(conn, err)
+			return
+		}
+		currHost, err := logic.GetHost(result.Host.ID.String())
+		if err != nil {
+			handleHostRegErr(conn, err)
+			return
+		}
+		var currentNetworks = []string{}
+		if result.ALL {
+			currentNets, err := logic.GetNetworks()
+			if err == nil && len(currentNets) > 0 {
+				for i := range currentNets {
+					currentNetworks = append(currentNetworks, currentNets[i].NetID)
+				}
+			}
+		} else if len(result.Network) > 0 {
+			currentNetworks = append(currentNetworks, result.Network)
+		}
+		var netsToAdd = []string{} // track the networks not currently owned by host
+		hostNets := logic.GetHostNetworks(currHost.ID.String())
+		for _, newNet := range currentNetworks {
+			if !logic.StringSliceContains(hostNets, newNet) {
+				if len(result.User) > 0 {
+					_, err := isUserIsAllowed(result.User, newNet, false)
+					if err != nil {
+						logger.Log(0, "unauthorized user", result.User, "attempted to register to network", newNet)
+						handleHostRegErr(conn, err)
+						return
+					}
+				}
+				netsToAdd = append(netsToAdd, newNet)
+			}
+		}
+		server := servercfg.GetServerInfo()
+		server.TrafficKey = key
+		if servercfg.GetBrokerType() == servercfg.EmqxBrokerType {
+			// set MQ username and password for EMQX clients
+			server.MQUserName = result.Host.ID.String()
+			server.MQPassword = hostPass
+		}
+		result.Host.HostPass = ""
+		response := models.RegisterResponse{
+			ServerConf:    server,
+			RequestedHost: result.Host,
+		}
+		reponseData, err := json.Marshal(&response)
+		if err != nil {
+			handleHostRegErr(conn, err)
+			return
+		}
+		if err = conn.WriteMessage(messageType, reponseData); err != nil {
+			logger.Log(0, "error during message writing:", err.Error())
+		}
+		go CheckNetRegAndHostUpdate(netsToAdd[:], &result.Host)
+	case <-timeout: // the read from req.answerCh has timed out
+		if err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")); err != nil {
+			logger.Log(0, "error during timeout message writing:", err.Error())
+		}
+	}
+	// The entry is not needed anymore, but we will let the producer to close it to avoid panic cases
+	if err = netcache.Del(stateStr); err != nil {
+		logger.Log(0, "failed to remove node SSO cache entry", err.Error())
+	}
+	// Cleanly close the connection by sending a close message and then
+	// waiting (with timeout) for the server to close the connection.
+	if err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")); err != nil {
+		logger.Log(0, "write close:", err.Error())
+		return
+	}
+}
+
+// CheckNetRegAndHostUpdate - run through networks and send a host update
+func CheckNetRegAndHostUpdate(networks []string, h *models.Host) {
+	// publish host update through MQ
+	for i := range networks {
+		network := networks[i]
+		if ok, _ := logic.NetworkExists(network); ok {
+			newNode, err := logic.UpdateHostNetwork(h, network, true)
+			if err != nil {
+				logger.Log(0, "failed to add host to network:", h.ID.String(), h.Name, network, err.Error())
+				continue
+			}
+			logger.Log(1, "added new node", newNode.ID.String(), "to host", h.Name)
+			hostactions.AddAction(models.HostUpdate{
+				Action: models.JoinHostToNetwork,
+				Host:   *h,
+				Node:   *newNode,
+			})
+		}
+	}
+	if servercfg.IsMessageQueueBackend() {
+		mq.HostUpdate(&models.HostUpdate{
+			Action: models.RequestAck,
+			Host:   *h,
+		})
+		if err := mq.PublishPeerUpdate(); err != nil {
+			logger.Log(0, "failed to publish peer update during registration -", err.Error())
+		}
+	}
+}
+
+func handleHostRegErr(conn *websocket.Conn, err error) {
+	_ = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
+	if err != nil {
+		logger.Log(0, "error during host registration via auth:", err.Error())
+	}
+}

+ 0 - 162
auth/nodesession.go

@@ -1,162 +0,0 @@
-package auth
-
-import (
-	"encoding/json"
-	"fmt"
-	"strings"
-	"time"
-
-	"github.com/gorilla/websocket"
-	"github.com/gravitl/netmaker/logger"
-	"github.com/gravitl/netmaker/logic"
-	"github.com/gravitl/netmaker/logic/pro/netcache"
-	"github.com/gravitl/netmaker/models"
-	"github.com/gravitl/netmaker/models/promodels"
-	"github.com/gravitl/netmaker/servercfg"
-)
-
-// SessionHandler - called by the HTTP router when user
-// is calling netclient with --login-server parameter in order to authenticate
-// via SSO mechanism by OAuth2 protocol flow.
-// This triggers a session start and it is managed by the flow implemented here and callback
-// When this method finishes - the auth flow has finished either OK or by timeout or any other error occured
-func SessionHandler(conn *websocket.Conn) {
-	defer conn.Close()
-
-	// If reached here we have a session from user to handle...
-	messageType, message, err := conn.ReadMessage()
-	if err != nil {
-		logger.Log(0, "Error during message reading:", err.Error())
-		return
-	}
-	var loginMessage promodels.LoginMsg
-
-	err = json.Unmarshal(message, &loginMessage)
-	if err != nil {
-		logger.Log(0, "Failed to unmarshall data err=", err.Error())
-		return
-	}
-	logger.Log(1, "SSO node join attempted with info network:", loginMessage.Network, "node identifier:", loginMessage.Mac, "user:", loginMessage.User)
-
-	req := new(netcache.CValue)
-	req.Value = string(loginMessage.Mac)
-	req.Network = loginMessage.Network
-	req.Pass = ""
-	req.User = ""
-	// Add any extra parameter provided in the configuration to the Authorize Endpoint request??
-	stateStr := logic.RandomString(node_signin_length)
-	if err := netcache.Set(stateStr, req); err != nil {
-		logger.Log(0, "Failed to process sso request -", err.Error())
-		return
-	}
-	// Wait for the user to finish his auth flow...
-	// TBD: what should be the timeout here ?
-	timeout := make(chan bool, 1)
-	answer := make(chan string, 1)
-	defer close(answer)
-	defer close(timeout)
-
-	if _, err = logic.GetNetwork(loginMessage.Network); err != nil {
-		err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
-		if err != nil {
-			logger.Log(0, "error during message writing:", err.Error())
-		}
-		return
-	}
-
-	if loginMessage.User != "" { // handle basic auth
-		// verify that server supports basic auth, then authorize the request with given credentials
-		// check if user is allowed to join via node sso
-		// i.e. user is admin or user has network permissions
-		if !servercfg.IsBasicAuthEnabled() {
-			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
-			if err != nil {
-				logger.Log(0, "error during message writing:", err.Error())
-			}
-		}
-		_, err := logic.VerifyAuthRequest(models.UserAuthParams{
-			UserName: loginMessage.User,
-			Password: loginMessage.Password,
-		})
-		if err != nil {
-			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
-			if err != nil {
-				logger.Log(0, "error during message writing:", err.Error())
-			}
-			return
-		}
-		_, err = isUserIsAllowed(loginMessage.User, loginMessage.Network, false)
-		if err != nil {
-			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
-			if err != nil {
-				logger.Log(0, "error during message writing:", err.Error())
-			}
-			return
-		}
-
-		// Give the user the access token via Pass in the DB
-		if err = netcache.Set(stateStr, req); err != nil {
-			logger.Log(0, "machine failed to complete join on network,", loginMessage.Network, "-", err.Error())
-			return
-		}
-	} else { // handle SSO / OAuth
-		if auth_provider == nil {
-			err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
-			if err != nil {
-				logger.Log(0, "error during message writing:", err.Error())
-			}
-			return
-		}
-		redirectUrl = fmt.Sprintf("https://%s/api/oauth/register/%s", servercfg.GetAPIConnString(), stateStr)
-		err = conn.WriteMessage(messageType, []byte(redirectUrl))
-		if err != nil {
-			logger.Log(0, "error during message writing:", err.Error())
-		}
-	}
-
-	go func() {
-		for {
-			cachedReq, err := netcache.Get(stateStr)
-			if err != nil {
-				if strings.Contains(err.Error(), "expired") {
-					logger.Log(0, "timeout occurred while waiting for SSO on network", loginMessage.Network)
-					timeout <- true
-					break
-				}
-				continue
-			} else if cachedReq.Pass != "" {
-				logger.Log(0, "node SSO process completed for user", cachedReq.User, "on network", loginMessage.Network)
-				answer <- cachedReq.Pass
-				break
-			}
-			time.Sleep(500) // try it 2 times per second to see if auth is completed
-		}
-	}()
-
-	select {
-	case result := <-answer:
-		// a read from req.answerCh has occurred
-		err = conn.WriteMessage(messageType, []byte(result))
-		if err != nil {
-			logger.Log(0, "Error during message writing:", err.Error())
-		}
-	case <-timeout:
-		logger.Log(0, "Authentication server time out for a node on network", loginMessage.Network)
-		// the read from req.answerCh has timed out
-		err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
-		if err != nil {
-			logger.Log(0, "Error during message writing:", err.Error())
-		}
-	}
-	// The entry is not needed anymore, but we will let the producer to close it to avoid panic cases
-	if err = netcache.Del(stateStr); err != nil {
-		logger.Log(0, "failed to remove node SSO cache entry", err.Error())
-	}
-	// Cleanly close the connection by sending a close message and then
-	// waiting (with timeout) for the server to close the connection.
-	err = conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
-	if err != nil {
-		logger.Log(0, "write close:", err.Error())
-		return
-	}
-}

+ 8 - 81
auth/nodecallback.go → auth/register_callback.go

@@ -19,13 +19,13 @@ var (
 	redirectUrl string
 	redirectUrl string
 )
 )
 
 
-// HandleNodeSSOCallback handles the callback from the sso endpoint
+// HandleHostSSOCallback handles the callback from the sso endpoint
 // It is the analogue of auth.handleNodeSSOCallback but takes care of the end point flow
 // It is the analogue of auth.handleNodeSSOCallback but takes care of the end point flow
 // Retrieves the mkey from the state cache and adds the machine to the users email namespace
 // Retrieves the mkey from the state cache and adds the machine to the users email namespace
 // TODO: A confirmation page for new machines should be added to avoid phishing vulnerabilities
 // TODO: A confirmation page for new machines should be added to avoid phishing vulnerabilities
 // TODO: Add groups information from OIDC tokens into machine HostInfo
 // TODO: Add groups information from OIDC tokens into machine HostInfo
 // Listens in /oidc/callback.
 // Listens in /oidc/callback.
-func HandleNodeSSOCallback(w http.ResponseWriter, r *http.Request) {
+func HandleHostSSOCallback(w http.ResponseWriter, r *http.Request) {
 
 
 	var functions = getCurrentAuthFunctions()
 	var functions = getCurrentAuthFunctions()
 	if functions == nil {
 	if functions == nil {
@@ -71,16 +71,7 @@ func HandleNodeSSOCallback(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 
 
-	user, err := isUserIsAllowed(userClaims.getUserName(), reqKeyIf.Network, true)
-	if err != nil {
-		logger.Log(0, "error occurred during SSO node join for user", userClaims.getUserName(), "on network", reqKeyIf.Network, "-", err.Error())
-		response := returnErrTemplate(user.UserName, err.Error(), state, reqKeyIf)
-		w.WriteHeader(http.StatusNotAcceptable)
-		w.Write(response)
-		return
-	}
-
-	logger.Log(1, "registering new node for user:", user.UserName, "on network", reqKeyIf.Network)
+	logger.Log(1, "registering host for user:", userClaims.getUserName(), reqKeyIf.Host.Name, reqKeyIf.Host.ID.String())
 
 
 	// Send OK to user in the browser
 	// Send OK to user in the browser
 	var response bytes.Buffer
 	var response bytes.Buffer
@@ -89,32 +80,15 @@ func HandleNodeSSOCallback(w http.ResponseWriter, r *http.Request) {
 		Verb: "Authenticated",
 		Verb: "Authenticated",
 	}); err != nil {
 	}); err != nil {
 		logger.Log(0, "Could not render SSO callback template ", err.Error())
 		logger.Log(0, "Could not render SSO callback template ", err.Error())
-		response := returnErrTemplate(user.UserName, "Could not render SSO callback template", state, reqKeyIf)
+		response := returnErrTemplate(reqKeyIf.User, "Could not render SSO callback template", state, reqKeyIf)
 		w.WriteHeader(http.StatusInternalServerError)
 		w.WriteHeader(http.StatusInternalServerError)
 		w.Write(response)
 		w.Write(response)
-
 	} else {
 	} else {
 		w.WriteHeader(http.StatusOK)
 		w.WriteHeader(http.StatusOK)
 		w.Write(response.Bytes())
 		w.Write(response.Bytes())
 	}
 	}
 
 
-	// Need to send access key to the client
-	logger.Log(1, "Handling new machine addition to network",
-		reqKeyIf.Network, "with key",
-		reqKeyIf.Value, " identity:", userClaims.getUserName(), "claims:", fmt.Sprintf("%+v", userClaims))
-
-	var answer string
-	// The registation logic is starting here:
-	// we request access key with 1 use for the required network
-	// accessToken, err := requestAccessKey(reqKeyIf.Network, 1, userClaims.getUserName())
-	// if err != nil {
-	// 	answer = fmt.Sprintf("Error from the netmaker controller %s", err.Error())
-	// } else {
-	// 	answer = fmt.Sprintf("AccessToken: %s", accessToken)
-	// }
-	logger.Log(0, "Updating the token for the client request ... ")
-	// Give the user the access token via Pass in the DB
-	reqKeyIf.Pass = answer
+	reqKeyIf.User = userClaims.getUserName() // set the cached registering hosts' user
 	if err = netcache.Set(state, reqKeyIf); err != nil {
 	if err = netcache.Set(state, reqKeyIf); err != nil {
 		logger.Log(0, "machine failed to complete join on network,", reqKeyIf.Network, "-", err.Error())
 		logger.Log(0, "machine failed to complete join on network,", reqKeyIf.Network, "-", err.Error())
 		return
 		return
@@ -151,10 +125,10 @@ func returnErrTemplate(uname, message, state string, ncache *netcache.CValue) []
 	return response.Bytes()
 	return response.Bytes()
 }
 }
 
 
-// RegisterNodeSSO redirects to the IDP for authentication
+// RegisterHostSSO redirects to the IDP for authentication
 // Puts machine key in cache so the callback can retrieve it using the oidc state param
 // Puts machine key in cache so the callback can retrieve it using the oidc state param
 // Listens in /oidc/register/:regKey.
 // Listens in /oidc/register/:regKey.
-func RegisterNodeSSO(w http.ResponseWriter, r *http.Request) {
+func RegisterHostSSO(w http.ResponseWriter, r *http.Request) {
 
 
 	if auth_provider == nil {
 	if auth_provider == nil {
 		w.WriteHeader(http.StatusBadRequest)
 		w.WriteHeader(http.StatusBadRequest)
@@ -165,63 +139,16 @@ func RegisterNodeSSO(w http.ResponseWriter, r *http.Request) {
 
 
 	// machineKeyStr this is not key but state
 	// machineKeyStr this is not key but state
 	machineKeyStr := vars["regKey"]
 	machineKeyStr := vars["regKey"]
-	logger.Log(1, "requested key:", machineKeyStr)
-
 	if machineKeyStr == "" {
 	if machineKeyStr == "" {
 		w.WriteHeader(http.StatusBadRequest)
 		w.WriteHeader(http.StatusBadRequest)
 		w.Write([]byte("invalid login attempt"))
 		w.Write([]byte("invalid login attempt"))
 		return
 		return
 	}
 	}
 
 
-	// machineKeyStr this not key but state
-	authURL := auth_provider.AuthCodeURL(machineKeyStr)
-	//authURL = authURL + "&connector_id=" + "google"
-	logger.Log(0, "Redirecting to ", authURL, " for authentication")
-
-	http.Redirect(w, r, authURL, http.StatusSeeOther)
-
+	http.Redirect(w, r, auth_provider.AuthCodeURL(machineKeyStr), http.StatusSeeOther)
 }
 }
 
 
 // == private ==
 // == private ==
-// API to create an access key for a given network with a given name
-// func requestAccessKey(network string, uses int, name string) (accessKey string, err error) {
-
-// 	var sAccessKey models.AccessKey
-// 	var sNetwork models.Network
-
-// 	sNetwork, err = logic.GetParentNetwork(network)
-// 	if err != nil {
-// 		logger.Log(0, "err calling GetParentNetwork API=%s", err.Error())
-// 		return "", fmt.Errorf("internal controller error %s", err.Error())
-// 	}
-// 	// If a key already exists, we recreate it.
-// 	// @TODO Is that a preferred handling ? We could also trying to re-use.
-// 	// can happen if user started log in but did not finish
-// 	for _, currentkey := range sNetwork.AccessKeys {
-// 		if currentkey.Name == name {
-// 			logger.Log(0, "erasing existing AccessKey for: ", name)
-// 			err = logic.DeleteKey(currentkey.Name, network)
-// 			if err != nil {
-// 				logger.Log(0, "err calling CreateAccessKey API ", err.Error())
-// 				return "", fmt.Errorf("key already exists. Contact admin to resolve")
-// 			}
-// 			break
-// 		}
-// 	}
-// 	// Only one usage is needed - for the next time new access key will be required
-// 	// it will be created next time after another IdP approval
-// 	sAccessKey.Uses = 1
-// 	sAccessKey.Name = name
-
-// 	accessToken, err := logic.CreateAccessKey(sAccessKey, sNetwork)
-// 	if err != nil {
-// 		logger.Log(0, "err calling CreateAccessKey API ", err.Error())
-// 		return "", fmt.Errorf("error from the netmaker controller %s", err.Error())
-// 	} else {
-// 		logger.Log(1, "created access key", sAccessKey.Name, "on", network)
-// 	}
-// 	return accessToken.AccessString, nil
-// }
 
 
 func isUserIsAllowed(username, network string, shouldAddUser bool) (*models.User, error) {
 func isUserIsAllowed(username, network string, shouldAddUser bool) (*models.User, error) {
 
 

+ 2 - 32
controllers/enrollmentkeys.go

@@ -7,9 +7,9 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/gorilla/mux"
 	"github.com/gorilla/mux"
+	"github.com/gravitl/netmaker/auth"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
-	"github.com/gravitl/netmaker/logic/hostactions"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/models"
 	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/mq"
 	"github.com/gravitl/netmaker/servercfg"
 	"github.com/gravitl/netmaker/servercfg"
@@ -230,35 +230,5 @@ func handleHostRegister(w http.ResponseWriter, r *http.Request) {
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
 	json.NewEncoder(w).Encode(&response)
 	json.NewEncoder(w).Encode(&response)
 	// notify host of changes, peer and node updates
 	// notify host of changes, peer and node updates
-	go checkNetRegAndHostUpdate(enrollmentKey.Networks, &newHost)
-}
-
-// run through networks and send a host update
-func checkNetRegAndHostUpdate(networks []string, h *models.Host) {
-	// publish host update through MQ
-	for i := range networks {
-		network := networks[i]
-		if ok, _ := logic.NetworkExists(network); ok {
-			newNode, err := logic.UpdateHostNetwork(h, network, true)
-			if err != nil {
-				logger.Log(0, "failed to add host to network:", h.ID.String(), h.Name, network, err.Error())
-				continue
-			}
-			logger.Log(1, "added new node", newNode.ID.String(), "to host", h.Name)
-			hostactions.AddAction(models.HostUpdate{
-				Action: models.JoinHostToNetwork,
-				Host:   *h,
-				Node:   *newNode,
-			})
-		}
-	}
-	if servercfg.IsMessageQueueBackend() {
-		mq.HostUpdate(&models.HostUpdate{
-			Action: models.RequestAck,
-			Host:   *h,
-		})
-		if err := mq.PublishPeerUpdate(); err != nil {
-			logger.Log(0, "failed to publish peer update during registration -", err.Error())
-		}
-	}
+	go auth.CheckNetRegAndHostUpdate(enrollmentKey.Networks, &newHost)
 }
 }

+ 1 - 0
controllers/hosts.go

@@ -28,6 +28,7 @@ func hostHandlers(r *mux.Router) {
 	r.HandleFunc("/api/hosts/{hostid}/relay", logic.SecurityCheck(false, http.HandlerFunc(deleteHostRelay))).Methods(http.MethodDelete)
 	r.HandleFunc("/api/hosts/{hostid}/relay", logic.SecurityCheck(false, http.HandlerFunc(deleteHostRelay))).Methods(http.MethodDelete)
 	r.HandleFunc("/api/hosts/adm/authenticate", authenticateHost).Methods(http.MethodPost)
 	r.HandleFunc("/api/hosts/adm/authenticate", authenticateHost).Methods(http.MethodPost)
 	r.HandleFunc("/api/v1/host", authorize(true, false, "host", http.HandlerFunc(pull))).Methods(http.MethodGet)
 	r.HandleFunc("/api/v1/host", authorize(true, false, "host", http.HandlerFunc(pull))).Methods(http.MethodGet)
+	r.HandleFunc("/api/v1/auth-register/host", socketHandler)
 }
 }
 
 
 // swagger:route GET /api/hosts hosts getHosts
 // swagger:route GET /api/hosts hosts getHosts

+ 2 - 1
controllers/migrate.go

@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"net/http"
 	"net/http"
 
 
+	"github.com/gravitl/netmaker/auth"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logger"
 	"github.com/gravitl/netmaker/logic"
 	"github.com/gravitl/netmaker/logic"
@@ -83,5 +84,5 @@ func migrate(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(&response)
 	json.NewEncoder(w).Encode(&response)
 	logger.Log(0, "successfully migrated host", data.NewHost.Name, data.NewHost.ID.String())
 	logger.Log(0, "successfully migrated host", data.NewHost.Name, data.NewHost.ID.String())
 	// notify host of changes, peer and node updates
 	// notify host of changes, peer and node updates
-	go checkNetRegAndHostUpdate(networksToAdd, &data.NewHost)
+	go auth.CheckNetRegAndHostUpdate(networksToAdd, &data.NewHost)
 }
 }

+ 2 - 3
controllers/user.go

@@ -33,9 +33,8 @@ func userHandlers(r *mux.Router) {
 	r.HandleFunc("/api/users", logic.SecurityCheck(true, http.HandlerFunc(getUsers))).Methods(http.MethodGet)
 	r.HandleFunc("/api/users", logic.SecurityCheck(true, http.HandlerFunc(getUsers))).Methods(http.MethodGet)
 	r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods(http.MethodGet)
 	r.HandleFunc("/api/oauth/login", auth.HandleAuthLogin).Methods(http.MethodGet)
 	r.HandleFunc("/api/oauth/callback", auth.HandleAuthCallback).Methods(http.MethodGet)
 	r.HandleFunc("/api/oauth/callback", auth.HandleAuthCallback).Methods(http.MethodGet)
-	r.HandleFunc("/api/oauth/node-handler", socketHandler)
 	r.HandleFunc("/api/oauth/headless", auth.HandleHeadlessSSO)
 	r.HandleFunc("/api/oauth/headless", auth.HandleHeadlessSSO)
-	r.HandleFunc("/api/oauth/register/{regKey}", auth.RegisterNodeSSO).Methods(http.MethodGet)
+	r.HandleFunc("/api/oauth/register/{regKey}", auth.RegisterHostSSO).Methods(http.MethodGet)
 }
 }
 
 
 // swagger:route POST /api/users/adm/authenticate user authenticateUser
 // swagger:route POST /api/users/adm/authenticate user authenticateUser
@@ -483,5 +482,5 @@ func socketHandler(w http.ResponseWriter, r *http.Request) {
 		return
 		return
 	}
 	}
 	// Start handling the session
 	// Start handling the session
-	// go auth.SessionHandler(conn)
+	go auth.SessionHandler(conn)
 }
 }

+ 8 - 5
logic/pro/netcache/netcache.go

@@ -6,6 +6,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/gravitl/netmaker/database"
 	"github.com/gravitl/netmaker/database"
+	"github.com/gravitl/netmaker/models"
 )
 )
 
 
 const (
 const (
@@ -14,11 +15,13 @@ const (
 
 
 // CValue - the cache object for a network
 // CValue - the cache object for a network
 type CValue struct {
 type CValue struct {
-	Network    string    `json:"network"`
-	Value      string    `json:"value"`
-	Pass       string    `json:"pass"`
-	User       string    `json:"user"`
-	Expiration time.Time `json:"expiration"`
+	Network    string      `json:"network,omitempty"`
+	Value      string      `json:"value"`
+	Host       models.Host `json:"host"`
+	Pass       string      `json:"pass,omitempty"`
+	User       string      `json:"user,omitempty"`
+	ALL        bool        `json:"all,omitempty"`
+	Expiration time.Time   `json:"expiration"`
 }
 }
 
 
 var ErrExpired = fmt.Errorf("expired")
 var ErrExpired = fmt.Errorf("expired")

+ 9 - 0
models/host.go

@@ -120,3 +120,12 @@ type HostUpdate struct {
 	Host   Host
 	Host   Host
 	Node   Node
 	Node   Node
 }
 }
+
+// RegisterMsg - login message struct for hosts to join via SSO login
+type RegisterMsg struct {
+	RegisterHost Host   `json:"host"`
+	Network      string `json:"network,omitempty"`
+	User         string `json:"user,omitempty"`
+	Password     string `json:"password,omitempty"`
+	JoinAll      bool   `json:"join_all,omitempty"`
+}

+ 0 - 9
models/promodels/pro.go

@@ -8,12 +8,3 @@ type ProNetwork struct {
 	AllowedUsers           []string `json:"allowedusers" bson:"allowedusers" yaml:"allowedusers"`
 	AllowedUsers           []string `json:"allowedusers" bson:"allowedusers" yaml:"allowedusers"`
 	AllowedGroups          []string `json:"allowedgroups" bson:"allowedgroups" yaml:"allowedgroups"`
 	AllowedGroups          []string `json:"allowedgroups" bson:"allowedgroups" yaml:"allowedgroups"`
 }
 }
-
-// LoginMsg - login message struct for nodes to join via SSO login
-// Need to change mac to public key for tighter verification ?
-type LoginMsg struct {
-	Mac      string `json:"mac"`
-	Network  string `json:"network"`
-	User     string `json:"user,omitempty"`
-	Password string `json:"password,omitempty"`
-}