Merge branch 'master' into auth-resolver
This commit is contained in:
		@@ -2,6 +2,7 @@ package auth
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"strings"
 | 
			
		||||
@@ -9,6 +10,7 @@ import (
 | 
			
		||||
	"github.com/micro/go-micro/v2/api/resolver"
 | 
			
		||||
	"github.com/micro/go-micro/v2/api/resolver/path"
 | 
			
		||||
	"github.com/micro/go-micro/v2/auth"
 | 
			
		||||
	"github.com/micro/go-micro/v2/logger"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// CombinedAuthHandler wraps a server and authenticates requests
 | 
			
		||||
@@ -36,6 +38,16 @@ type authHandler struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
	// Determine the namespace
 | 
			
		||||
	namespace, err := namespaceFromRequest(req)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error(err)
 | 
			
		||||
		namespace = auth.DefaultNamespace
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Set the namespace in the header
 | 
			
		||||
	req.Header.Set(auth.NamespaceKey, namespace)
 | 
			
		||||
 | 
			
		||||
	// Extract the token from the request
 | 
			
		||||
	var token string
 | 
			
		||||
	if header := req.Header.Get("Authorization"); len(header) > 0 {
 | 
			
		||||
@@ -56,7 +68,14 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
	// account doesn't necesserially mean a forbidden request
 | 
			
		||||
	acc, err := h.auth.Inspect(token)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		acc = &auth.Account{}
 | 
			
		||||
		acc = &auth.Account{Namespace: namespace}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Check the accounts namespace matches the namespace we're operating
 | 
			
		||||
	// within. If not forbid the request and log the occurance.
 | 
			
		||||
	if acc.Namespace != namespace {
 | 
			
		||||
		logger.Warnf("Cross namespace request forbidden: account %v (%v) requested access to %v in the %v namespace", acc.ID, acc.Namespace, req.URL.Path, namespace)
 | 
			
		||||
		w.WriteHeader(http.StatusForbidden)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Determine the name of the service being requested
 | 
			
		||||
@@ -85,15 +104,15 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
 | 
			
		||||
	// Perform the verification check to see if the account has access to
 | 
			
		||||
	// the resource they're requesting
 | 
			
		||||
	res := &auth.Resource{Type: "service", Name: resName, Endpoint: resEndpoint}
 | 
			
		||||
	res := &auth.Resource{Type: "service", Name: resName, Endpoint: resEndpoint, Namespace: namespace}
 | 
			
		||||
	if err := h.auth.Verify(acc, res); err == nil {
 | 
			
		||||
		// The account has the necessary permissions to access the resource
 | 
			
		||||
		h.handler.ServeHTTP(w, req)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// The account is set, but they don't have enough permissions,
 | 
			
		||||
	// hence we 403.
 | 
			
		||||
	// The account is set, but they don't have enough permissions, hence
 | 
			
		||||
	// we return a forbidden error.
 | 
			
		||||
	if len(acc.ID) > 0 {
 | 
			
		||||
		w.WriteHeader(http.StatusForbidden)
 | 
			
		||||
		return
 | 
			
		||||
@@ -111,3 +130,42 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
	loginWithRedirect := fmt.Sprintf("%v?%v", loginURL, params.Encode())
 | 
			
		||||
	http.Redirect(w, req, loginWithRedirect, http.StatusTemporaryRedirect)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func namespaceFromRequest(req *http.Request) (string, error) {
 | 
			
		||||
	// determine the host, e.g. dev.micro.mu:8080
 | 
			
		||||
	host := req.URL.Host
 | 
			
		||||
	if len(host) == 0 {
 | 
			
		||||
		host = req.Host
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check for an ip address
 | 
			
		||||
	if net.ParseIP(host) != nil {
 | 
			
		||||
		return auth.DefaultNamespace, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// split the host to remove the port
 | 
			
		||||
	host, _, err := net.SplitHostPort(req.Host)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check for dev enviroment
 | 
			
		||||
	if host == "localhost" || host == "127.0.0.1" {
 | 
			
		||||
		return auth.DefaultNamespace, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// if host is not a subdomain, deturn default namespace
 | 
			
		||||
	comps := strings.Split(host, ".")
 | 
			
		||||
	if len(comps) != 3 {
 | 
			
		||||
		return auth.DefaultNamespace, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// check for the micro.mu domain
 | 
			
		||||
	domain := fmt.Sprintf("%v.%v", comps[1], comps[2])
 | 
			
		||||
	if domain == "micro.mu" {
 | 
			
		||||
		return auth.DefaultNamespace, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// return the subdomain as the host
 | 
			
		||||
	return comps[0], nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user