From 4999f6dfd4cae3d233ae6d7aa7b6af84516da7ab Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Thu, 2 Apr 2020 17:01:06 +0100 Subject: [PATCH 01/11] Namespace requests coming via api & web --- api/server/auth/auth.go | 90 +++++++++++++++++++++++++++----- auth/auth.go | 18 ++++--- auth/default.go | 12 +++-- auth/service/proto/auth.pb.go | 97 +++++++++++++++++++---------------- auth/service/proto/auth.proto | 1 + auth/service/service.go | 57 +++++++++++++------- 6 files changed, 189 insertions(+), 86 deletions(-) diff --git a/api/server/auth/auth.go b/api/server/auth/auth.go index 1bd60508..34f4c654 100644 --- a/api/server/auth/auth.go +++ b/api/server/auth/auth.go @@ -2,27 +2,44 @@ package auth import ( "fmt" + "net" "net/http" "net/url" "strings" + "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 func CombinedAuthHandler(h http.Handler) http.Handler { return authHandler{ - handler: h, - auth: auth.DefaultAuth, + handler: h, + auth: auth.DefaultAuth, + resolver: path.NewResolver(), + // namespace: } } type authHandler struct { - handler http.Handler - auth auth.Auth + handler http.Handler + auth auth.Auth + resolver resolver.Resolver } func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { + // Determine the namespace + namespace, err := namespaceFromRequest(req) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + + // 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 { @@ -43,23 +60,39 @@ 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) + } + + // WIP: Determine the name of the service being requested + // endpoint, err := h.resolver.Resolve(req) + // fmt.Printf("EndpointName: %v\n", endpoint.Name) + // fmt.Printf("EndpointMethod: %v\n", endpoint.Method) + // fmt.Printf("EndpointPath: %v\n", endpoint.Path) + + // Perform the verification check to see if the account has access to + // the resource they're requesting err = h.auth.Verify(acc, &auth.Resource{ - Type: "service", - Name: "go.micro.web", - Endpoint: req.URL.Path, + Type: "service", + Name: "go.micro.web", + Endpoint: req.URL.Path, + Namespace: namespace, }) - // The account has the necessary permissions to access the - // resource + // The account has the necessary permissions to access the resource if err == nil { 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 @@ -77,3 +110,36 @@ 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) { + // check for an ip address + if net.ParseIP(req.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 +} diff --git a/auth/auth.go b/auth/auth.go index 206d2d76..5f954776 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -21,8 +21,6 @@ var ( ErrInvalidRole = errors.New("invalid role") // ErrForbidden is returned when a user does not have the necessary roles to access a resource ErrForbidden = errors.New("resource forbidden") - // BearerScheme used for Authorization header - BearerScheme = "Bearer " ) // Auth providers authentication and authorization @@ -50,11 +48,13 @@ type Auth interface { // Resource is an entity such as a user or type Resource struct { // Name of the resource - Name string + Name string `json:"name"` // Type of resource, e.g. - Type string + Type string `json:"type"` // Endpoint resource e.g NotesService.Create - Endpoint string + Endpoint string `json:"endpoint"` + // Namespace the resource belongs to + Namespace string `json:"namespace"` } // Account provided by an auth provider @@ -69,7 +69,7 @@ type Account struct { Roles []string `json:"roles"` // Any other associated metadata Metadata map[string]string `json:"metadata"` - // Namespace the account belongs to, default blank + // Namespace the account belongs to Namespace string `json:"namespace"` // Secret for the account, e.g. the password Secret string `json:"secret"` @@ -88,12 +88,18 @@ type Token struct { } const ( + // DefaultNamespace used for auth + DefaultNamespace = "micro" + // NamespaceKey is the key used when storing the namespace in metadata + NamespaceKey = "Micro-Namespace" // MetadataKey is the key used when storing the account in metadata MetadataKey = "auth-account" // TokenCookieName is the name of the cookie which stores the auth token TokenCookieName = "micro-token" // SecretCookieName is the name of the cookie which stores the auth secret SecretCookieName = "micro-secret" + // BearerScheme used for Authorization header + BearerScheme = "Bearer " ) // AccountFromContext gets the account from the context, which diff --git a/auth/default.go b/auth/default.go index 20f16a4f..358cf099 100644 --- a/auth/default.go +++ b/auth/default.go @@ -38,10 +38,11 @@ func (n *noop) Generate(id string, opts ...GenerateOption) (*Account, error) { options := NewGenerateOptions(opts...) return &Account{ - ID: id, - Roles: options.Roles, - Secret: options.Secret, - Metadata: options.Metadata, + ID: id, + Roles: options.Roles, + Secret: options.Secret, + Metadata: options.Metadata, + Namespace: DefaultNamespace, }, nil } @@ -63,7 +64,8 @@ func (n *noop) Verify(acc *Account, res *Resource) error { // Inspect a token func (n *noop) Inspect(token string) (*Account, error) { return &Account{ - ID: uuid.New().String(), + ID: uuid.New().String(), + Namespace: DefaultNamespace, }, nil } diff --git a/auth/service/proto/auth.pb.go b/auth/service/proto/auth.pb.go index 3cffecb4..aac61c2a 100644 --- a/auth/service/proto/auth.pb.go +++ b/auth/service/proto/auth.pb.go @@ -272,6 +272,7 @@ type Resource struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` Endpoint string `protobuf:"bytes,3,opt,name=endpoint,proto3" json:"endpoint,omitempty"` + Namespace string `protobuf:"bytes,4,opt,name=namespace,proto3" json:"namespace,omitempty"` XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_unrecognized []byte `json:"-"` XXX_sizecache int32 `json:"-"` @@ -323,6 +324,13 @@ func (m *Resource) GetEndpoint() string { return "" } +func (m *Resource) GetNamespace() string { + if m != nil { + return m.Namespace + } + return "" +} + type GenerateRequest struct { Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` Roles []string `protobuf:"bytes,2,rep,name=roles,proto3" json:"roles,omitempty"` @@ -1123,12 +1131,12 @@ func init() { } var fileDescriptor_11312eec02fd5712 = []byte{ - // 896 bytes of a gzipped FileDescriptorProto + // 901 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0x4b, 0x6f, 0xdb, 0x46, 0x10, 0x36, 0x49, 0x89, 0x92, 0x47, 0x0f, 0x0b, 0x1b, 0x27, 0x25, 0x98, 0x47, 0x1d, 0xa6, 0x28, 0xdc, 0xa0, 0xa1, 0x0b, 0xe5, 0xd0, 0x47, 0x2e, 0x35, 0x22, 0x41, 0x4d, 0xda, 0xa8, 0x28, 0x91, - 0x22, 0xbd, 0x14, 0x01, 0x43, 0x4d, 0x6d, 0xc2, 0x32, 0xc9, 0xee, 0x2e, 0x8d, 0xfa, 0x52, 0xa0, - 0xa7, 0xde, 0x7a, 0xea, 0x4f, 0xe8, 0xcf, 0xea, 0xbd, 0x7f, 0xa3, 0xe0, 0x3e, 0x28, 0x91, 0xa2, + 0x22, 0xbd, 0x14, 0x01, 0x43, 0x4d, 0x6d, 0xc2, 0x32, 0xc9, 0xee, 0x2e, 0x8d, 0xea, 0x52, 0xa0, + 0xa7, 0xde, 0x7a, 0xea, 0x4f, 0xe8, 0xcf, 0xea, 0xbd, 0x7f, 0xa3, 0xe0, 0x3e, 0x68, 0x91, 0xa2, 0x02, 0xa3, 0xf5, 0x21, 0xb7, 0x9d, 0x07, 0x67, 0xe6, 0xfb, 0x66, 0x76, 0xb8, 0xf0, 0xe9, 0x49, 0xcc, 0x4f, 0xf3, 0x37, 0x7e, 0x94, 0x9e, 0x1f, 0x9d, 0xc7, 0x11, 0x4d, 0x8f, 0x4e, 0xd2, 0x47, 0xf2, 0x10, 0xe6, 0xfc, 0xf4, 0x88, 0x21, 0xbd, 0x88, 0x23, 0x3c, 0xca, 0x68, 0xca, 0xa5, 0xca, @@ -1139,45 +1147,46 @@ var fileDescriptor_11312eec02fd5712 = []byte{ 0x4c, 0xc8, 0x7d, 0xe8, 0x87, 0x51, 0x84, 0x8c, 0xbd, 0xe6, 0x85, 0xec, 0x18, 0x07, 0xc6, 0xe1, 0x6e, 0xd0, 0x93, 0x3a, 0xe9, 0xf2, 0x00, 0x06, 0x14, 0x7f, 0xa2, 0xc8, 0x4e, 0x95, 0x8f, 0x29, 0x7c, 0xfa, 0x4a, 0x29, 0x9d, 0x1c, 0xe8, 0x44, 0x14, 0x43, 0x8e, 0x0b, 0xc7, 0x3a, 0x30, 0x0e, - 0xad, 0x40, 0x8b, 0xe4, 0x16, 0xd8, 0xf8, 0x4b, 0x16, 0xd3, 0x4b, 0xa7, 0x25, 0x0c, 0x4a, 0xf2, - 0xfe, 0x34, 0xa1, 0xa3, 0x2a, 0x23, 0x43, 0x30, 0xe3, 0x85, 0xca, 0x6d, 0xc6, 0x0b, 0x42, 0xa0, - 0xc5, 0x2f, 0x33, 0x54, 0x99, 0xc4, 0x99, 0xec, 0x43, 0x9b, 0xa6, 0x4b, 0x64, 0x8e, 0x75, 0x60, - 0x1d, 0xee, 0x06, 0x52, 0x20, 0x5f, 0x42, 0xf7, 0x1c, 0x79, 0xb8, 0x08, 0x79, 0xe8, 0xb4, 0x04, - 0xfa, 0x0f, 0x9a, 0xd1, 0xfb, 0x2f, 0x94, 0xdb, 0x34, 0xe1, 0xf4, 0x32, 0x28, 0xbf, 0x22, 0x77, - 0x60, 0x37, 0x09, 0xcf, 0x91, 0x65, 0x61, 0x84, 0x4e, 0x5b, 0x24, 0x5c, 0x29, 0x88, 0x0b, 0xdd, - 0x8c, 0xa6, 0x17, 0xf1, 0x02, 0xa9, 0x63, 0x0b, 0x63, 0x29, 0x17, 0xc8, 0x18, 0x46, 0x14, 0xb9, - 0xd3, 0x11, 0x16, 0x25, 0xb9, 0x4f, 0x60, 0x50, 0x49, 0x46, 0x46, 0x60, 0x9d, 0xe1, 0xa5, 0xc2, - 0x57, 0x1c, 0x0b, 0x30, 0x17, 0xe1, 0x32, 0xd7, 0x08, 0xa5, 0xf0, 0x85, 0xf9, 0x99, 0xe1, 0xcd, - 0xa1, 0x1b, 0x20, 0x4b, 0x73, 0x1a, 0x61, 0x41, 0x43, 0x51, 0x89, 0xfa, 0x50, 0x9c, 0x1b, 0xa9, - 0x71, 0xa1, 0x8b, 0xc9, 0x22, 0x4b, 0xe3, 0x84, 0x0b, 0xf6, 0x77, 0x83, 0x52, 0xf6, 0xfe, 0x32, - 0x61, 0x6f, 0x86, 0x09, 0xd2, 0x90, 0xa3, 0x1a, 0xa5, 0x0d, 0xba, 0x4b, 0x6a, 0xcd, 0x75, 0x6a, - 0xbf, 0x5a, 0xa3, 0xd6, 0x12, 0xd4, 0x7e, 0x5c, 0xa3, 0xb6, 0x16, 0xf7, 0x6a, 0x14, 0xb7, 0xea, - 0x14, 0xaf, 0x68, 0x6c, 0xaf, 0xd3, 0x58, 0x22, 0xb5, 0xab, 0x48, 0xcb, 0x76, 0x74, 0xaa, 0xed, - 0xf8, 0x7f, 0xb4, 0x4f, 0x60, 0xb4, 0x42, 0xa3, 0x6e, 0xd6, 0x27, 0xd0, 0x51, 0x37, 0x46, 0xc4, - 0xd8, 0x7e, 0xb1, 0xb4, 0x9b, 0xf7, 0x0a, 0xfa, 0x33, 0x1a, 0x26, 0x5c, 0x13, 0x4d, 0xa0, 0x55, - 0x70, 0xa9, 0x1b, 0x58, 0x9c, 0xc9, 0x63, 0xe8, 0x52, 0xd5, 0x60, 0x51, 0x46, 0x6f, 0xfc, 0x5e, - 0x2d, 0xac, 0xee, 0x7f, 0x50, 0x3a, 0x7a, 0x7b, 0x30, 0x50, 0x81, 0x65, 0x6d, 0xde, 0x0f, 0x30, - 0x08, 0xf0, 0x22, 0x3d, 0xc3, 0x6b, 0x4f, 0x35, 0x82, 0xa1, 0x8e, 0xac, 0x72, 0x7d, 0x08, 0xc3, - 0x67, 0x09, 0xcb, 0x30, 0x2a, 0x71, 0xed, 0x43, 0x7b, 0x7d, 0x5d, 0x48, 0xc1, 0x7b, 0x0a, 0x7b, - 0xa5, 0xdf, 0x7f, 0xa6, 0xf0, 0x57, 0xe8, 0x8b, 0x8d, 0xb2, 0x6d, 0x56, 0x57, 0xd3, 0x62, 0x56, - 0xa6, 0x65, 0x63, 0x4b, 0x59, 0x0d, 0x5b, 0xea, 0x3e, 0xf4, 0x85, 0xf1, 0x75, 0x65, 0x23, 0xf5, - 0x84, 0x6e, 0x2a, 0xd7, 0xd2, 0x13, 0x18, 0xa8, 0xfc, 0x0a, 0xc2, 0xc3, 0x75, 0xac, 0xbd, 0xf1, - 0x7e, 0x0d, 0x80, 0x74, 0x56, 0x0c, 0xfc, 0x61, 0x40, 0x2b, 0xc8, 0x97, 0xd8, 0xb4, 0xd0, 0x44, - 0x77, 0xcc, 0x2d, 0xdd, 0xb1, 0xae, 0xd8, 0x1d, 0xf2, 0x08, 0x6c, 0xb9, 0x9b, 0x45, 0xed, 0xc3, - 0xf1, 0xcd, 0x4d, 0x3e, 0x91, 0xb1, 0x40, 0x39, 0x79, 0xbf, 0x1b, 0x30, 0x78, 0x2a, 0x16, 0xf1, - 0x75, 0xcf, 0xc9, 0x5a, 0x25, 0xd6, 0x55, 0x2a, 0x19, 0xc1, 0x50, 0x17, 0xa2, 0xc6, 0xaa, 0xa8, - 0x6d, 0x82, 0x4b, 0x7c, 0x27, 0x6a, 0xd3, 0x85, 0xa8, 0xda, 0x06, 0xd0, 0x2b, 0x7e, 0xb6, 0xfa, - 0xdf, 0xfb, 0x39, 0xf4, 0xa5, 0xa8, 0x66, 0xe2, 0x23, 0x68, 0xd3, 0xbc, 0x58, 0x98, 0xf2, 0x87, - 0x7b, 0xa3, 0x5e, 0x51, 0xbe, 0xc4, 0x40, 0x7a, 0x3c, 0xf4, 0xc1, 0x96, 0xd9, 0x48, 0x0f, 0x3a, - 0xdf, 0xcf, 0xbf, 0x9e, 0x7f, 0xfb, 0x6a, 0x3e, 0xda, 0x29, 0x84, 0x59, 0x70, 0x3c, 0x7f, 0x39, - 0x9d, 0x8c, 0x0c, 0x02, 0x60, 0x4f, 0xa6, 0xf3, 0x67, 0xd3, 0xc9, 0xc8, 0x1c, 0xff, 0x63, 0x40, - 0xeb, 0x38, 0xe7, 0xa7, 0xe4, 0x05, 0x74, 0xf5, 0x46, 0x22, 0xf7, 0xde, 0xbe, 0x78, 0xdd, 0xf7, - 0xb7, 0xda, 0x15, 0x9e, 0x1d, 0xf2, 0x1c, 0x3a, 0xea, 0x72, 0x92, 0xbb, 0x35, 0xef, 0xea, 0xe5, - 0x76, 0xef, 0x6d, 0x33, 0x97, 0xb1, 0x26, 0xfa, 0xf5, 0x70, 0xbb, 0xf1, 0x32, 0xa8, 0x38, 0x77, - 0x9a, 0x8d, 0x3a, 0xca, 0xf8, 0x47, 0xe8, 0xea, 0xc7, 0x0c, 0xf9, 0x0e, 0x5a, 0x05, 0xc1, 0xc4, - 0xab, 0x7d, 0xd3, 0xf0, 0x10, 0x72, 0x1f, 0xbc, 0xd5, 0xa7, 0x0c, 0xff, 0xb7, 0x01, 0xed, 0xa2, - 0x11, 0x8c, 0xcc, 0xc0, 0x96, 0xa3, 0x47, 0xea, 0x25, 0x55, 0xae, 0x86, 0x7b, 0x77, 0x8b, 0xb5, - 0xc4, 0x3d, 0x03, 0x5b, 0xce, 0xc9, 0x46, 0xa0, 0xca, 0x1c, 0x6f, 0x04, 0xaa, 0x0d, 0xd7, 0x0e, - 0x39, 0x56, 0x70, 0xdd, 0x06, 0x28, 0x3a, 0xc8, 0xed, 0x46, 0x9b, 0x0e, 0xf1, 0xc6, 0x16, 0x6f, - 0xc7, 0xc7, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x4b, 0x8f, 0xf4, 0x22, 0x76, 0x0a, 0x00, 0x00, + 0xad, 0x40, 0x8b, 0xe4, 0x16, 0xd8, 0xf8, 0x4b, 0x16, 0xd3, 0x95, 0xd3, 0x12, 0x06, 0x25, 0x79, + 0x7f, 0x9a, 0xd0, 0x51, 0x95, 0x91, 0x21, 0x98, 0xf1, 0x42, 0xe5, 0x36, 0xe3, 0x05, 0x21, 0xd0, + 0xe2, 0xab, 0x0c, 0x55, 0x26, 0x71, 0x26, 0xfb, 0xd0, 0xa6, 0xe9, 0x12, 0x99, 0x63, 0x1d, 0x58, + 0x87, 0xbb, 0x81, 0x14, 0xc8, 0x97, 0xd0, 0x3d, 0x47, 0x1e, 0x2e, 0x42, 0x1e, 0x3a, 0x2d, 0x81, + 0xfe, 0x83, 0x66, 0xf4, 0xfe, 0x0b, 0xe5, 0x36, 0x4d, 0x38, 0x5d, 0x05, 0xe5, 0x57, 0xe4, 0x0e, + 0xec, 0x26, 0xe1, 0x39, 0xb2, 0x2c, 0x8c, 0xd0, 0x69, 0x8b, 0x84, 0x97, 0x0a, 0xe2, 0x42, 0x37, + 0xa3, 0xe9, 0x45, 0xbc, 0x40, 0xea, 0xd8, 0xc2, 0x58, 0xca, 0x05, 0x32, 0x86, 0x11, 0x45, 0xee, + 0x74, 0x84, 0x45, 0x49, 0xee, 0x13, 0x18, 0x54, 0x92, 0x91, 0x11, 0x58, 0x67, 0xb8, 0x52, 0xf8, + 0x8a, 0x63, 0x01, 0xe6, 0x22, 0x5c, 0xe6, 0x1a, 0xa1, 0x14, 0xbe, 0x30, 0x3f, 0x33, 0xbc, 0x25, + 0x74, 0x03, 0x64, 0x69, 0x4e, 0x23, 0x2c, 0x68, 0x28, 0x2a, 0x51, 0x1f, 0x8a, 0x73, 0x23, 0x35, + 0x2e, 0x74, 0x31, 0x59, 0x64, 0x69, 0x9c, 0x70, 0xc1, 0xfe, 0x6e, 0x50, 0xca, 0x55, 0x78, 0xad, + 0x1a, 0x3c, 0xef, 0x2f, 0x13, 0xf6, 0x66, 0x98, 0x20, 0x0d, 0x39, 0xaa, 0x41, 0xdb, 0x68, 0x46, + 0x49, 0xbc, 0xb9, 0x4e, 0xfc, 0x57, 0x6b, 0xc4, 0x5b, 0x82, 0xf8, 0x8f, 0x6b, 0xc4, 0xd7, 0xe2, + 0x5e, 0xad, 0x01, 0xf5, 0x0a, 0xd7, 0x48, 0x6e, 0xaf, 0x93, 0x5c, 0xf2, 0x60, 0x57, 0x79, 0x28, + 0x9b, 0xd5, 0xa9, 0x36, 0xeb, 0xff, 0x35, 0x65, 0x02, 0xa3, 0x4b, 0x34, 0xea, 0xde, 0x7d, 0x02, + 0x1d, 0x75, 0x9f, 0x44, 0x8c, 0xed, 0xd7, 0x4e, 0xbb, 0x79, 0xaf, 0xa0, 0x3f, 0xa3, 0x61, 0xc2, + 0x35, 0xd1, 0x04, 0x5a, 0x05, 0x97, 0xba, 0xbd, 0xc5, 0x99, 0x3c, 0x86, 0x2e, 0x55, 0xed, 0x17, + 0x65, 0xf4, 0xc6, 0xef, 0xd5, 0xc2, 0xea, 0xe9, 0x08, 0x4a, 0x47, 0x6f, 0x0f, 0x06, 0x2a, 0xb0, + 0xac, 0xcd, 0xfb, 0x01, 0x06, 0x01, 0x5e, 0xa4, 0x67, 0x78, 0xed, 0xa9, 0x46, 0x30, 0xd4, 0x91, + 0x55, 0xae, 0x0f, 0x61, 0xf8, 0x2c, 0x61, 0x19, 0x46, 0x25, 0xae, 0x7d, 0x68, 0xaf, 0x2f, 0x13, + 0x29, 0x78, 0x4f, 0x61, 0xaf, 0xf4, 0xfb, 0xcf, 0x14, 0xfe, 0x0a, 0x7d, 0xb1, 0x6f, 0xb6, 0xcd, + 0xea, 0xe5, 0xb4, 0x98, 0x95, 0x69, 0xd9, 0xd8, 0x61, 0x56, 0xc3, 0x0e, 0xbb, 0x0f, 0x7d, 0x61, + 0x7c, 0x5d, 0xd9, 0x57, 0x3d, 0xa1, 0x9b, 0xca, 0xa5, 0xf5, 0x04, 0x06, 0x2a, 0xbf, 0x82, 0xf0, + 0x70, 0x1d, 0x6b, 0x6f, 0xbc, 0x5f, 0x03, 0x20, 0x9d, 0x15, 0x03, 0x7f, 0x18, 0xd0, 0x0a, 0xf2, + 0x25, 0x36, 0xad, 0x3b, 0xd1, 0x1d, 0x73, 0x4b, 0x77, 0xac, 0x2b, 0x76, 0x87, 0x3c, 0x02, 0x5b, + 0x6e, 0x6e, 0x51, 0xfb, 0x70, 0x7c, 0x73, 0x93, 0x4f, 0x64, 0x2c, 0x50, 0x4e, 0xde, 0xef, 0x06, + 0x0c, 0x9e, 0x8a, 0x35, 0x7d, 0xdd, 0x73, 0xb2, 0x56, 0x89, 0x75, 0x95, 0x4a, 0x46, 0x30, 0xd4, + 0x85, 0xa8, 0xb1, 0x2a, 0x6a, 0x9b, 0xe0, 0x12, 0xdf, 0x89, 0xda, 0x74, 0x21, 0xaa, 0xb6, 0x01, + 0xf4, 0x8a, 0x5f, 0xb1, 0xfe, 0x33, 0x7f, 0x0e, 0x7d, 0x29, 0xaa, 0x99, 0xf8, 0x08, 0xda, 0x34, + 0x2f, 0x16, 0xa6, 0xfc, 0x1d, 0xdf, 0xa8, 0x57, 0x94, 0x2f, 0x31, 0x90, 0x1e, 0x0f, 0x7d, 0xb0, + 0x65, 0x36, 0xd2, 0x83, 0xce, 0xf7, 0xf3, 0xaf, 0xe7, 0xdf, 0xbe, 0x9a, 0x8f, 0x76, 0x0a, 0x61, + 0x16, 0x1c, 0xcf, 0x5f, 0x4e, 0x27, 0x23, 0x83, 0x00, 0xd8, 0x93, 0xe9, 0xfc, 0xd9, 0x74, 0x32, + 0x32, 0xc7, 0xff, 0x18, 0xd0, 0x3a, 0xce, 0xf9, 0x29, 0x79, 0x01, 0x5d, 0xbd, 0x91, 0xc8, 0xbd, + 0xb7, 0x2f, 0x5e, 0xf7, 0xfd, 0xad, 0x76, 0x85, 0x67, 0x87, 0x3c, 0x87, 0x8e, 0xba, 0x9c, 0xe4, + 0x6e, 0xcd, 0xbb, 0x7a, 0xb9, 0xdd, 0x7b, 0xdb, 0xcc, 0x65, 0xac, 0x89, 0x7e, 0x5b, 0xdc, 0x6e, + 0xbc, 0x0c, 0x2a, 0xce, 0x9d, 0x66, 0xa3, 0x8e, 0x32, 0xfe, 0x11, 0xba, 0xfa, 0xa9, 0x43, 0xbe, + 0x83, 0x56, 0x41, 0x30, 0xf1, 0x6a, 0xdf, 0x34, 0x3c, 0x93, 0xdc, 0x07, 0x6f, 0xf5, 0x29, 0xc3, + 0xff, 0x6d, 0x40, 0xbb, 0x68, 0x04, 0x23, 0x33, 0xb0, 0xe5, 0xe8, 0x91, 0x7a, 0x49, 0x95, 0xab, + 0xe1, 0xde, 0xdd, 0x62, 0x2d, 0x71, 0xcf, 0xc0, 0x96, 0x73, 0xb2, 0x11, 0xa8, 0x32, 0xc7, 0x1b, + 0x81, 0x6a, 0xc3, 0xb5, 0x43, 0x8e, 0x15, 0x5c, 0xb7, 0x01, 0x8a, 0x0e, 0x72, 0xbb, 0xd1, 0xa6, + 0x43, 0xbc, 0xb1, 0xc5, 0xcb, 0xf2, 0xf1, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfa, 0x51, 0x05, + 0x6e, 0x94, 0x0a, 0x00, 0x00, } diff --git a/auth/service/proto/auth.proto b/auth/service/proto/auth.proto index d7d09418..77a44af8 100644 --- a/auth/service/proto/auth.proto +++ b/auth/service/proto/auth.proto @@ -46,6 +46,7 @@ message Resource{ string name = 1; string type = 2; string endpoint = 3; + string namespace = 4; } message GenerateRequest { diff --git a/auth/service/service.go b/auth/service/service.go index a0ce48b7..166886d1 100644 --- a/auth/service/service.go +++ b/auth/service/service.go @@ -132,9 +132,10 @@ func (s *svc) Grant(role string, res *auth.Resource) error { Role: role, Access: pb.Access_GRANTED, Resource: &pb.Resource{ - Type: res.Type, - Name: res.Name, - Endpoint: res.Endpoint, + Namespace: res.Namespace, + Type: res.Type, + Name: res.Name, + Endpoint: res.Endpoint, }, }) return err @@ -146,9 +147,10 @@ func (s *svc) Revoke(role string, res *auth.Resource) error { Role: role, Access: pb.Access_GRANTED, Resource: &pb.Resource{ - Type: res.Type, - Name: res.Name, - Endpoint: res.Endpoint, + Namespace: res.Namespace, + Type: res.Type, + Name: res.Name, + Endpoint: res.Endpoint, }, }) return err @@ -157,10 +159,11 @@ func (s *svc) Revoke(role string, res *auth.Resource) error { // Verify an account has access to a resource func (s *svc) Verify(acc *auth.Account, res *auth.Resource) error { queries := [][]string{ - {res.Type, res.Name, res.Endpoint}, // check for specific role, e.g. service.foo.ListFoo:admin (role is checked in accessForRule) - {res.Type, res.Name, "*"}, // check for wildcard endpoint, e.g. service.foo* - {res.Type, "*"}, // check for wildcard name, e.g. service.* - {"*"}, // check for wildcard type, e.g. * + {res.Namespace, res.Type, res.Name, res.Endpoint}, // check for specific role, e.g. service.foo.ListFoo:admin (role is checked in accessForRule) + {res.Namespace, res.Type, res.Name, "*"}, // check for wildcard endpoint, e.g. service.foo* + {res.Namespace, res.Type, "*"}, // check for wildcard name, e.g. service.* + {res.Namespace, "*"}, // check for wildcard type, e.g. * + {"*"}, // check for wildcard namespace } // endpoint is a url which can have wildcard excludes, e.g. @@ -172,23 +175,30 @@ func (s *svc) Verify(acc *auth.Account, res *auth.Resource) error { } } + // set a default account id to log + logID := acc.ID + if len(logID) == 0 { + logID = "[no account]" + } + for _, q := range queries { for _, rule := range s.listRules(q...) { switch accessForRule(rule, acc, res) { case pb.Access_UNKNOWN: continue // rule did not specify access, check the next rule case pb.Access_GRANTED: - log.Infof("%v granted access to %v:%v:%v by rule %v", acc.ID, res.Type, res.Name, res.Endpoint, rule.Id) + log.Infof("%v:%v granted access to %v:%v:%v:%v by rule %v", acc.Namespace, logID, res.Namespace, res.Type, res.Name, res.Endpoint, rule.Id) return nil // rule grants the account access to the resource case pb.Access_DENIED: - log.Infof("%v denied access to %v:%v:%v by rule %v", acc.ID, res.Type, res.Name, res.Endpoint, rule.Id) + log.Infof("%v:%v denied access to %v:%v:%v:%v by rule %v", acc.Namespace, logID, res.Namespace, res.Type, res.Name, res.Endpoint, rule.Id) return auth.ErrForbidden // rule denies access to the resource } } } // no rules were found for the resource, default to denying access - log.Infof("%v denied access to %v:%v:%v by lack of rule (%v rules found)", acc.ID, res.Type, res.Name, res.Endpoint, len(s.rules)) + log.Infof("%v:%v denied access to %v:%v:%v:%v by lack of rule (%v rules found for namespace)", acc.Namespace, logID, res.Namespace, res.Type, res.Name, res.Endpoint, len(s.listRules(res.Namespace))) + fmt.Println(s.rules) return auth.ErrForbidden } @@ -249,19 +259,28 @@ func accessForRule(rule *pb.Rule, acc *auth.Account, res *auth.Resource) pb.Acce return pb.Access_UNKNOWN } -// listRules gets all the rules from the store which have an id -// prefix matching the filters +// listRules gets all the rules from the store which match the filters. +// filters are namespace, type, name and then endpoint. func (s *svc) listRules(filters ...string) []*pb.Rule { s.Lock() defer s.Unlock() - prefix := strings.Join(filters, ruleJoinKey) - var rules []*pb.Rule for _, r := range s.rules { - if strings.HasPrefix(r.Id, prefix) { - rules = append(rules, r) + if len(filters) > 0 && r.Resource.Namespace != filters[0] { + continue } + if len(filters) > 1 && r.Resource.Type != filters[1] { + continue + } + if len(filters) > 2 && r.Resource.Name != filters[2] { + continue + } + if len(filters) > 3 && r.Resource.Endpoint != filters[3] { + continue + } + + rules = append(rules, r) } return rules From 4a4c6665282c2418bc0518b4c1bc46413402e02b Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Thu, 2 Apr 2020 18:03:21 +0100 Subject: [PATCH 02/11] Remove resolver logic --- api/server/auth/auth.go | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/api/server/auth/auth.go b/api/server/auth/auth.go index 34f4c654..15373277 100644 --- a/api/server/auth/auth.go +++ b/api/server/auth/auth.go @@ -8,7 +8,6 @@ import ( "strings" "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" ) @@ -16,10 +15,8 @@ import ( // CombinedAuthHandler wraps a server and authenticates requests func CombinedAuthHandler(h http.Handler) http.Handler { return authHandler{ - handler: h, - auth: auth.DefaultAuth, - resolver: path.NewResolver(), - // namespace: + handler: h, + auth: auth.DefaultAuth, } } @@ -70,12 +67,6 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusForbidden) } - // WIP: Determine the name of the service being requested - // endpoint, err := h.resolver.Resolve(req) - // fmt.Printf("EndpointName: %v\n", endpoint.Name) - // fmt.Printf("EndpointMethod: %v\n", endpoint.Method) - // fmt.Printf("EndpointPath: %v\n", endpoint.Path) - // Perform the verification check to see if the account has access to // the resource they're requesting err = h.auth.Verify(acc, &auth.Resource{ From cfde3ec3d94a3010ae71d2977f38df1ad52fb9b9 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Thu, 2 Apr 2020 18:03:57 +0100 Subject: [PATCH 03/11] Remove resolver logic --- api/server/auth/auth.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/api/server/auth/auth.go b/api/server/auth/auth.go index 15373277..e01b95a0 100644 --- a/api/server/auth/auth.go +++ b/api/server/auth/auth.go @@ -7,7 +7,6 @@ import ( "net/url" "strings" - "github.com/micro/go-micro/v2/api/resolver" "github.com/micro/go-micro/v2/auth" "github.com/micro/go-micro/v2/logger" ) @@ -21,9 +20,8 @@ func CombinedAuthHandler(h http.Handler) http.Handler { } type authHandler struct { - handler http.Handler - auth auth.Auth - resolver resolver.Resolver + handler http.Handler + auth auth.Auth } func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { From ce23ab36cb58871e469c8fc4e69e2ea9973a7074 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Thu, 2 Apr 2020 18:41:06 +0100 Subject: [PATCH 04/11] Improve Err Handling --- auth/service/service.go | 1 - service.go | 2 +- util/wrapper/wrapper.go | 36 +++++++++++++++++++++++++++++++----- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/auth/service/service.go b/auth/service/service.go index 166886d1..57d6082e 100644 --- a/auth/service/service.go +++ b/auth/service/service.go @@ -198,7 +198,6 @@ func (s *svc) Verify(acc *auth.Account, res *auth.Resource) error { // no rules were found for the resource, default to denying access log.Infof("%v:%v denied access to %v:%v:%v:%v by lack of rule (%v rules found for namespace)", acc.Namespace, logID, res.Namespace, res.Type, res.Name, res.Endpoint, len(s.listRules(res.Namespace))) - fmt.Println(s.rules) return auth.ErrForbidden } diff --git a/service.go b/service.go index a13b4e19..2feb5db4 100644 --- a/service.go +++ b/service.go @@ -35,7 +35,7 @@ func newService(opts ...Option) Service { serviceName := options.Server.Options().Name // TODO: better accessors - authFn := func() auth.Auth { return service.opts.Auth } + authFn := func() auth.Auth { return options.Auth } // wrap client to inject From-Service header on any calls options.Client = wrapper.FromService(serviceName, options.Client, authFn) diff --git a/util/wrapper/wrapper.go b/util/wrapper/wrapper.go index f795e705..a2878a20 100644 --- a/util/wrapper/wrapper.go +++ b/util/wrapper/wrapper.go @@ -2,6 +2,7 @@ package wrapper import ( "context" + "fmt" "strings" "github.com/micro/go-micro/v2/auth" @@ -9,6 +10,7 @@ import ( "github.com/micro/go-micro/v2/debug/stats" "github.com/micro/go-micro/v2/debug/trace" "github.com/micro/go-micro/v2/errors" + "github.com/micro/go-micro/v2/logger" "github.com/micro/go-micro/v2/metadata" "github.com/micro/go-micro/v2/server" ) @@ -165,24 +167,48 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper { if header, ok := metadata.Get(ctx, "Authorization"); ok { // Ensure the correct scheme is being used if !strings.HasPrefix(header, auth.BearerScheme) { - return errors.Unauthorized("go.micro.auth", "invalid authorization header. expected Bearer schema") + return errors.Unauthorized(req.Service(), "invalid authorization header. expected Bearer schema") } token = header[len(auth.BearerScheme):] } + // Get the namespace for the request + namespace, ok := metadata.Get(ctx, auth.NamespaceKey) + if !ok { + logger.Errorf("Missing request namespace") + namespace = auth.DefaultNamespace + } + fmt.Printf("Namespace is %v\n", namespace) + // Inspect the token and get the account account, err := a.Inspect(token) if err != nil { - account = &auth.Account{} + account = &auth.Account{Namespace: auth.DefaultNamespace} + } + + // Check the accounts namespace matches the namespace we're operating + // within. If not forbid the request and log the occurance. + if account.Namespace != namespace { + logger.Warnf("Cross namespace request forbidden: account %v (%v) requested access to %v %v in the %v namespace", + account.ID, account.Namespace, req.Service(), req.Endpoint(), namespace) + return errors.Forbidden(req.Service(), "cross namespace request") + } + + // construct the resource + res := &auth.Resource{ + Type: "service", + Name: req.Service(), + Endpoint: req.Endpoint(), + Namespace: namespace, } // Verify the caller has access to the resource - err = a.Verify(account, &auth.Resource{Type: "service", Name: req.Service(), Endpoint: req.Endpoint()}) + err = a.Verify(account, res) if err != nil && len(account.ID) > 0 { - return errors.Forbidden("go.micro.auth", "Forbidden call made to %v:%v by %v", req.Service(), req.Endpoint(), account.ID) + return errors.Forbidden(req.Service(), "Forbidden call made to %v:%v by %v", req.Service(), req.Endpoint(), account.ID) } else if err != nil { - return errors.Unauthorized("go.micro.auth", "Unauthorised call made to %v:%v", req.Service(), req.Endpoint()) + return errors.Unauthorized(req.Service(), "Unauthorised call made to %v:%v", req.Service(), req.Endpoint()) } // There is an account, set it in the context From dea2d7ab9f1ede5f29307cef73cdf8a579c05258 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Fri, 3 Apr 2020 12:27:01 +0100 Subject: [PATCH 05/11] Fix go-micro auth wrapper init --- config/cmd/cmd.go | 1 + service.go | 5 +++-- util/wrapper/wrapper.go | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/cmd/cmd.go b/config/cmd/cmd.go index 7b90b29a..021156b9 100644 --- a/config/cmd/cmd.go +++ b/config/cmd/cmd.go @@ -494,6 +494,7 @@ func (c *cmd) Before(ctx *cli.Context) error { *c.opts.Auth = a() clientOpts = append(clientOpts, client.Auth(*c.opts.Auth)) + serverOpts = append(serverOpts, server.Auth(*c.opts.Auth)) } // Set the profile diff --git a/service.go b/service.go index 2feb5db4..36044338 100644 --- a/service.go +++ b/service.go @@ -34,8 +34,9 @@ func newService(opts ...Option) Service { // service name serviceName := options.Server.Options().Name - // TODO: better accessors - authFn := func() auth.Auth { return options.Auth } + // authFn returns the auth, we pass as a function since auth + // has not yet been set at this point. + authFn := func() auth.Auth { return options.Server.Options().Auth } // wrap client to inject From-Service header on any calls options.Client = wrapper.FromService(serviceName, options.Client, authFn) diff --git a/util/wrapper/wrapper.go b/util/wrapper/wrapper.go index a2878a20..a599ac80 100644 --- a/util/wrapper/wrapper.go +++ b/util/wrapper/wrapper.go @@ -2,7 +2,6 @@ package wrapper import ( "context" - "fmt" "strings" "github.com/micro/go-micro/v2/auth" @@ -179,7 +178,6 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper { logger.Errorf("Missing request namespace") namespace = auth.DefaultNamespace } - fmt.Printf("Namespace is %v\n", namespace) // Inspect the token and get the account account, err := a.Inspect(token) From 49a568e9c05b04125bf22449727ca5c56156bc65 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Fri, 3 Apr 2020 12:33:19 +0100 Subject: [PATCH 06/11] Set default server auth --- server/options.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/options.go b/server/options.go index 5caba936..63b895bb 100644 --- a/server/options.go +++ b/server/options.go @@ -60,6 +60,10 @@ func newOptions(opt ...Option) Options { o(&opts) } + if opts.Auth == nil { + opts.Auth = auth.DefaultAuth + } + if opts.Broker == nil { opts.Broker = broker.DefaultBroker } From a9c0e043d2872bb5567b1a79bcf9d380aea595b8 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Fri, 3 Apr 2020 12:50:50 +0100 Subject: [PATCH 07/11] Fix nil grpc server auth bug --- server/grpc/options.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/grpc/options.go b/server/grpc/options.go index 5cd52cb0..6591fac2 100644 --- a/server/grpc/options.go +++ b/server/grpc/options.go @@ -5,6 +5,7 @@ import ( "crypto/tls" "net" + "github.com/micro/go-micro/v2/auth" "github.com/micro/go-micro/v2/broker" "github.com/micro/go-micro/v2/codec" "github.com/micro/go-micro/v2/registry" @@ -66,6 +67,7 @@ func MaxMsgSize(s int) server.Option { func newOptions(opt ...server.Option) server.Options { opts := server.Options{ + Auth: auth.DefaultAuth, Codecs: make(map[string]codec.NewCodec), Metadata: map[string]string{}, Broker: broker.DefaultBroker, From 1374a9e52883ea5d072c148d0fa39d55ea8d9c14 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Fri, 3 Apr 2020 13:03:27 +0100 Subject: [PATCH 08/11] Fix namespace bug in auth wrapper --- util/wrapper/wrapper.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/wrapper/wrapper.go b/util/wrapper/wrapper.go index a599ac80..839240c2 100644 --- a/util/wrapper/wrapper.go +++ b/util/wrapper/wrapper.go @@ -182,7 +182,7 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper { // Inspect the token and get the account account, err := a.Inspect(token) if err != nil { - account = &auth.Account{Namespace: auth.DefaultNamespace} + account = &auth.Account{Namespace: namespace} } // Check the accounts namespace matches the namespace we're operating From d0e47206cc6df6e487750af5f5d753753f2546e1 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Fri, 3 Apr 2020 13:29:48 +0100 Subject: [PATCH 09/11] Fix --- api/server/auth/auth.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/server/auth/auth.go b/api/server/auth/auth.go index e01b95a0..6fce9712 100644 --- a/api/server/auth/auth.go +++ b/api/server/auth/auth.go @@ -28,7 +28,9 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { // Determine the namespace namespace, err := namespaceFromRequest(req) if err != nil { - w.WriteHeader(http.StatusInternalServerError) + logger.Error(err) + // w.WriteHeader(http.StatusInternalServerError) + namespace = auth.DefaultNamespace return } From 906263291b5a09f3d9ee07d8c5d10a9317e46b98 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Fri, 3 Apr 2020 13:37:02 +0100 Subject: [PATCH 10/11] Hotfix --- api/server/auth/auth.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/api/server/auth/auth.go b/api/server/auth/auth.go index 6fce9712..615392a8 100644 --- a/api/server/auth/auth.go +++ b/api/server/auth/auth.go @@ -29,9 +29,7 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { namespace, err := namespaceFromRequest(req) if err != nil { logger.Error(err) - // w.WriteHeader(http.StatusInternalServerError) namespace = auth.DefaultNamespace - return } // Set the namespace in the header From b864b3e350b7a76818447f549f98ddc3702171b7 Mon Sep 17 00:00:00 2001 From: Ben Toogood Date: Fri, 3 Apr 2020 14:09:25 +0100 Subject: [PATCH 11/11] Fix auth hosts bug --- api/server/auth/auth.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/api/server/auth/auth.go b/api/server/auth/auth.go index 615392a8..186e71c7 100644 --- a/api/server/auth/auth.go +++ b/api/server/auth/auth.go @@ -101,8 +101,14 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { } 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(req.Host) != nil { + if net.ParseIP(host) != nil { return auth.DefaultNamespace, nil }