Browse Source

- support masteradmin
- return hosts with partial access

Tobias Cudnik 2 years ago
parent
commit
8953f41805
6 changed files with 60 additions and 17 deletions
  1. 18 8
      controllers/enrollmentkeys.go
  2. 28 5
      controllers/hosts.go
  3. 1 4
      controllers/network.go
  4. 11 0
      controllers/user.go
  5. 1 0
      logic/security.go
  6. 1 0
      logic/users.go

+ 18 - 8
controllers/enrollmentkeys.go

@@ -34,22 +34,32 @@ func enrollmentKeyHandlers(r *mux.Router) {
 //			Responses:
 //			Responses:
 //				200: getEnrollmentKeysSlice
 //				200: getEnrollmentKeysSlice
 func getEnrollmentKeys(w http.ResponseWriter, r *http.Request) {
 func getEnrollmentKeys(w http.ResponseWriter, r *http.Request) {
-	user, err := logic.GetUser(r.Header.Get("user"))
+	keys, err := logic.GetAllEnrollmentKeys()
 	if err != nil {
 	if err != nil {
-		logger.Log(0, r.Header.Get("user"), "failed to fetch user: ", err.Error())
+		logger.Log(0, r.Header.Get("user"), "failed to fetch enrollment keys: ", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}
-	keys, err := logic.GetAllEnrollmentKeys()
+	// handle masteradmin non-logged-in user
+	// TODO unify the user flow
+	headerNetworks, err := getHeaderNetworks(r)
 	if err != nil {
 	if err != nil {
-		logger.Log(0, r.Header.Get("user"), "failed to fetch enrollment keys: ", err.Error())
+		logger.Log(0, r.Header.Get("user"), "failed to parse networks: ", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+	isMasterAdmin := len(headerNetworks) > 0 && headerNetworks[0] == logic.ALL_NETWORK_ACCESS
+	// regular user flow
+	user, err := logic.GetUser(r.Header.Get("user"))
+	if err != nil && !isMasterAdmin {
+		logger.Log(0, r.Header.Get("user"), "failed to fetch user: ", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}
 	// TODO drop double pointer
 	// TODO drop double pointer
-	accessKeys := []*models.EnrollmentKey{}
+	ret := []*models.EnrollmentKey{}
 	for _, key := range keys {
 	for _, key := range keys {
-		if !logic.UserHasNetworksAccess(key.Networks, user) {
+		if !isMasterAdmin && !logic.UserHasNetworksAccess(key.Networks, user) {
 			continue
 			continue
 		}
 		}
 		if err = logic.Tokenize(key, servercfg.GetAPIHost()); err != nil {
 		if err = logic.Tokenize(key, servercfg.GetAPIHost()); err != nil {
@@ -57,12 +67,12 @@ func getEnrollmentKeys(w http.ResponseWriter, r *http.Request) {
 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 			logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 			return
 			return
 		}
 		}
-		accessKeys = append(accessKeys, key)
+		ret = append(ret, key)
 	}
 	}
 	// return JSON/API formatted keys
 	// return JSON/API formatted keys
 	logger.Log(2, r.Header.Get("user"), "fetched enrollment keys")
 	logger.Log(2, r.Header.Get("user"), "fetched enrollment keys")
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)
-	json.NewEncoder(w).Encode(accessKeys)
+	json.NewEncoder(w).Encode(ret)
 }
 }
 
 
 // swagger:route DELETE /api/v1/enrollment-keys/{keyID} enrollmentKeys deleteEnrollmentKey
 // swagger:route DELETE /api/v1/enrollment-keys/{keyID} enrollmentKeys deleteEnrollmentKey

+ 28 - 5
controllers/hosts.go

@@ -52,8 +52,17 @@ func getHosts(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
 	}
 	}
-	user, err := logic.GetUser(r.Header.Get("user"))
+	// handle masteradmin non-logged-in user
+	// TODO unify the user flow
+	headerNetworks, err := getHeaderNetworks(r)
 	if err != nil {
 	if err != nil {
+		logger.Log(0, r.Header.Get("user"), "failed to parse networks: ", err.Error())
+		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+		return
+	}
+	isMasterAdmin := len(headerNetworks) > 0 && headerNetworks[0] == logic.ALL_NETWORK_ACCESS
+	user, err := logic.GetUser(r.Header.Get("user"))
+	if err != nil && !isMasterAdmin {
 		logger.Log(0, r.Header.Get("user"), "failed to fetch user: ", err.Error())
 		logger.Log(0, r.Header.Get("user"), "failed to fetch user: ", err.Error())
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
 		return
 		return
@@ -63,11 +72,25 @@ func getHosts(w http.ResponseWriter, r *http.Request) {
 	apiHosts := logic.GetAllHostsAPI(currentHosts[:])
 	apiHosts := logic.GetAllHostsAPI(currentHosts[:])
 	logger.Log(2, r.Header.Get("user"), "fetched all hosts")
 	logger.Log(2, r.Header.Get("user"), "fetched all hosts")
 	for _, host := range apiHosts {
 	for _, host := range apiHosts {
-		networks := logic.GetHostNetworks(host.ID)
-		if !logic.UserHasNetworksAccess(networks, user) {
-			continue
+		nodes := host.Nodes
+		// work on the copy
+		host.Nodes = []string{}
+		for _, nid := range nodes {
+			node, err := logic.GetNodeByID(nid)
+			if err != nil {
+				logger.Log(0, r.Header.Get("user"), "failed to fetch node: ", err.Error())
+				logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
+				return
+			}
+			if !isMasterAdmin && !logic.UserHasNetworksAccess([]string{node.Network}, user) {
+				continue
+			}
+			host.Nodes = append(host.Nodes, nid)
+		}
+		// add to the response only if has perms to some nodes / networks
+		if len(host.Nodes) > 0 {
+			ret = append(ret, host)
 		}
 		}
-		ret = append(ret, host)
 	}
 	}
 	logic.SortApiHosts(ret[:])
 	logic.SortApiHosts(ret[:])
 	w.WriteHeader(http.StatusOK)
 	w.WriteHeader(http.StatusOK)

+ 1 - 4
controllers/network.go

@@ -40,10 +40,7 @@ func networkHandlers(r *mux.Router) {
 //			Responses:
 //			Responses:
 //				200: getNetworksSliceResponse
 //				200: getNetworksSliceResponse
 func getNetworks(w http.ResponseWriter, r *http.Request) {
 func getNetworks(w http.ResponseWriter, r *http.Request) {
-
-	headerNetworks := r.Header.Get("networks")
-	networksSlice := []string{}
-	marshalErr := json.Unmarshal([]byte(headerNetworks), &networksSlice)
+	networksSlice, marshalErr := getHeaderNetworks(r)
 	if marshalErr != nil {
 	if marshalErr != nil {
 		logger.Log(0, r.Header.Get("user"), "error unmarshalling networks: ",
 		logger.Log(0, r.Header.Get("user"), "error unmarshalling networks: ",
 			marshalErr.Error())
 			marshalErr.Error())

+ 11 - 0
controllers/user.go

@@ -491,3 +491,14 @@ func socketHandler(w http.ResponseWriter, r *http.Request) {
 	// Start handling the session
 	// Start handling the session
 	go auth.SessionHandler(conn)
 	go auth.SessionHandler(conn)
 }
 }
+
+// getHeaderNetworks returns a slice of networks parsed form the request header.
+func getHeaderNetworks(r *http.Request) ([]string, error) {
+	headerNetworks := r.Header.Get("networks")
+	networksSlice := []string{}
+	err := json.Unmarshal([]byte(headerNetworks), &networksSlice)
+	if err != nil {
+		return nil, err
+	}
+	return networksSlice, nil
+}

+ 1 - 0
logic/security.go

@@ -147,6 +147,7 @@ func UserPermissions(reqAdmin bool, netname string, token string) ([]string, str
 	}
 	}
 	//all endpoints here require master so not as complicated
 	//all endpoints here require master so not as complicated
 	if authenticateMaster(authToken) {
 	if authenticateMaster(authToken) {
+		// TODO log in as an actual admin user
 		return []string{ALL_NETWORK_ACCESS}, master_uname, nil
 		return []string{ALL_NETWORK_ACCESS}, master_uname, nil
 	}
 	}
 	username, networks, isadmin, err := VerifyUserToken(authToken)
 	username, networks, isadmin, err := VerifyUserToken(authToken)

+ 1 - 0
logic/users.go

@@ -12,6 +12,7 @@ import (
 )
 )
 
 
 // GetUser - gets a user
 // GetUser - gets a user
+// TODO support "masteradmin"
 func GetUser(username string) (*models.User, error) {
 func GetUser(username string) (*models.User, error) {
 
 
 	var user models.User
 	var user models.User