Implement very basic authorization for routes
This commit is contained in:
		
							parent
							
								
									a2df979e66
								
							
						
					
					
						commit
						b6bc9adf29
					
				
							
								
								
									
										51
									
								
								http.go
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								http.go
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -9,6 +9,7 @@ import (
 | 
			
		|||
	"io"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type ServerCollection []*server.Server
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +27,10 @@ func (sc *ServerCollection) Get(uuid string) *server.Server {
 | 
			
		|||
 | 
			
		||||
type Router struct {
 | 
			
		||||
	Servers ServerCollection
 | 
			
		||||
 | 
			
		||||
	// The authentication token defined in the config.yml file that allows
 | 
			
		||||
	// a request to perform any action aganist the daemon.
 | 
			
		||||
	token string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Middleware to protect server specific routes. This will ensure that the server exists and
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +46,45 @@ func (rt *Router) AuthenticateServer(h httprouter.Handle) httprouter.Handle {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Authenticates the request token aganist the given permission string, ensuring that
 | 
			
		||||
// if it is a server permission, the token has control over that server. If it is a global
 | 
			
		||||
// token, this will ensure that the request is using a properly signed global token.
 | 
			
		||||
func (rt *Router) AuthenticateToken(permission string, h httprouter.Handle) httprouter.Handle {
 | 
			
		||||
	return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
 | 
			
		||||
		t := strings.Split(permission, ":")[0]
 | 
			
		||||
 | 
			
		||||
		auth := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
 | 
			
		||||
		if len(auth) != 2 || auth[0] != "Bearer" {
 | 
			
		||||
			w.Header().Set("WWW-Authenticate", "Bearer")
 | 
			
		||||
			http.Error(w, "authorization failed", http.StatusUnauthorized)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if t != "i" && t != "s" {
 | 
			
		||||
			zap.S().Warnw("could not match a permission string", zap.String("permission", permission), zap.String("route", r.URL.String()))
 | 
			
		||||
 | 
			
		||||
			// If for whatever reason we didn't match a permission string just
 | 
			
		||||
			// return a 404. This should only ever happen because of developer error.
 | 
			
		||||
			http.NotFound(w, r)
 | 
			
		||||
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Try to match the request aganist the global token for the Daemon, regardless
 | 
			
		||||
		// of the permission type. If nothing is matched we will fall through to the Panel
 | 
			
		||||
		// API to try and validate permissions for a server.
 | 
			
		||||
		if t == "s" || t == "i" {
 | 
			
		||||
			if auth[1] == rt.token {
 | 
			
		||||
				h(w, r, ps)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		http.Error(w, "not implemented", http.StatusNotImplemented)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns the basic Wings index page without anything else.
 | 
			
		||||
func (rt *Router) routeIndex(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
 | 
			
		||||
	fmt.Fprint(w, "Welcome!\n")
 | 
			
		||||
| 
						 | 
				
			
			@ -125,13 +169,14 @@ func (rt *Router) routeServerPower(w http.ResponseWriter, r *http.Request, ps ht
 | 
			
		|||
	w.WriteHeader(http.StatusAccepted)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Configures the router and all of the associated routes.
 | 
			
		||||
func (rt *Router) ConfigureRouter() *httprouter.Router {
 | 
			
		||||
	router := httprouter.New()
 | 
			
		||||
 | 
			
		||||
	router.GET("/", rt.routeIndex)
 | 
			
		||||
	router.GET("/api/servers", rt.routeAllServers)
 | 
			
		||||
	router.GET("/api/servers/:server", rt.AuthenticateServer(rt.routeServer))
 | 
			
		||||
	router.POST("/api/servers/:server/power", rt.AuthenticateServer(rt.routeServerPower))
 | 
			
		||||
	router.GET("/api/servers", rt.AuthenticateToken("i:servers", rt.routeAllServers))
 | 
			
		||||
	router.GET("/api/servers/:server", rt.AuthenticateToken("s:view", rt.AuthenticateServer(rt.routeServer)))
 | 
			
		||||
	router.POST("/api/servers/:server/power", rt.AuthenticateToken("s:power", rt.AuthenticateServer(rt.routeServerPower)))
 | 
			
		||||
 | 
			
		||||
	return router
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user