mirror of
https://github.com/go-micro/go-micro.git
synced 2024-12-24 10:07:04 +02:00
Refactor Namespace Resolver
This commit is contained in:
parent
3df87510a1
commit
4362a885eb
@ -11,6 +11,12 @@ var (
|
|||||||
ErrInvalidPath = errors.New("invalid path")
|
ErrInvalidPath = errors.New("invalid path")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// NamespaceResolver resolves request to the namespace
|
||||||
|
type NamespaceResolver interface {
|
||||||
|
Resolve(r *http.Request) string
|
||||||
|
String() string
|
||||||
|
}
|
||||||
|
|
||||||
// Resolver resolves requests to endpoints
|
// Resolver resolves requests to endpoints
|
||||||
type Resolver interface {
|
type Resolver interface {
|
||||||
Resolve(r *http.Request) (*Endpoint, error)
|
Resolve(r *http.Request) (*Endpoint, error)
|
||||||
@ -27,6 +33,8 @@ type Endpoint struct {
|
|||||||
Method string
|
Method string
|
||||||
// HTTP Path e.g /greeter.
|
// HTTP Path e.g /greeter.
|
||||||
Path string
|
Path string
|
||||||
|
// Namespace, g.g. go.micro
|
||||||
|
Namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
|
@ -3,44 +3,35 @@ package auth
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/micro/go-micro/v2/api/resolver"
|
"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/auth"
|
||||||
"github.com/micro/go-micro/v2/logger"
|
"github.com/micro/go-micro/v2/logger"
|
||||||
"golang.org/x/net/publicsuffix"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CombinedAuthHandler wraps a server and authenticates requests
|
// CombinedAuthHandler wraps a server and authenticates requests
|
||||||
func CombinedAuthHandler(prefix, namespace string, r resolver.Resolver, h http.Handler) http.Handler {
|
func CombinedAuthHandler(r resolver.Resolver, nr resolver.NamespaceResolver, h http.Handler) http.Handler {
|
||||||
if r == nil {
|
|
||||||
r = path.NewResolver()
|
|
||||||
}
|
|
||||||
|
|
||||||
return authHandler{
|
return authHandler{
|
||||||
handler: h,
|
handler: h,
|
||||||
resolver: r,
|
resolver: r,
|
||||||
auth: auth.DefaultAuth,
|
nsResolver: nr,
|
||||||
servicePrefix: prefix,
|
auth: auth.DefaultAuth,
|
||||||
namespace: namespace,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type authHandler struct {
|
type authHandler struct {
|
||||||
handler http.Handler
|
handler http.Handler
|
||||||
auth auth.Auth
|
auth auth.Auth
|
||||||
resolver resolver.Resolver
|
resolver resolver.Resolver
|
||||||
namespace string
|
nsResolver resolver.NamespaceResolver
|
||||||
servicePrefix string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
// Determine the namespace and set it in the header
|
// Determine the namespace and set it in the header
|
||||||
namespace := h.NamespaceFromRequest(req)
|
namespace := h.nsResolver.Resolve(req)
|
||||||
req.Header.Set(auth.NamespaceKey, namespace)
|
req.Header.Set(auth.NamespaceKey, namespace)
|
||||||
|
|
||||||
// Extract the token from the request
|
// Extract the token from the request
|
||||||
@ -63,14 +54,7 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
// account doesn't necesserially mean a forbidden request
|
// account doesn't necesserially mean a forbidden request
|
||||||
acc, err := h.auth.Inspect(token)
|
acc, err := h.auth.Inspect(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
acc = &auth.Account{Namespace: namespace}
|
acc = &auth.Account{}
|
||||||
}
|
|
||||||
|
|
||||||
// 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.Debugf("Cross namespace request warning: account %v (%v) requested access to %v in the %v namespace", acc.ID, acc.Namespace, req.URL.Path, namespace)
|
|
||||||
// http.Error(w, "Forbidden namespace", 403)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the name of the service being requested
|
// Determine the name of the service being requested
|
||||||
@ -90,9 +74,9 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// construct the resource name, e.g. home => go.micro.web.home
|
// construct the resource name, e.g. home => go.micro.web.home
|
||||||
resName := h.servicePrefix
|
resName := namespace
|
||||||
if len(endpoint.Name) > 0 {
|
if len(endpoint.Name) > 0 {
|
||||||
resName = resName + "." + endpoint.Name
|
resName = namespace + "." + endpoint.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
// determine the resource path. there is an inconsistency in how resolvers
|
// determine the resource path. there is an inconsistency in how resolvers
|
||||||
@ -127,59 +111,7 @@ func (h authHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Redirect to the login path
|
// Redirect to the login path
|
||||||
params := url.Values{"redirect_to": {req.URL.Path}}
|
params := url.Values{"redirect_to": {req.URL.String()}}
|
||||||
loginWithRedirect := fmt.Sprintf("%v?%v", loginURL, params.Encode())
|
loginWithRedirect := fmt.Sprintf("%v?%v", loginURL, params.Encode())
|
||||||
http.Redirect(w, req, loginWithRedirect, http.StatusTemporaryRedirect)
|
http.Redirect(w, req, loginWithRedirect, http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h authHandler) NamespaceFromRequest(req *http.Request) string {
|
|
||||||
// check to see what the provided namespace is, we only do
|
|
||||||
// domain mapping if the namespace is set to 'domain'
|
|
||||||
if h.namespace != "domain" {
|
|
||||||
return h.namespace
|
|
||||||
}
|
|
||||||
|
|
||||||
// determine the host, e.g. dev.micro.mu:8080
|
|
||||||
host := req.URL.Hostname()
|
|
||||||
if len(host) == 0 {
|
|
||||||
if h, _, err := net.SplitHostPort(req.Host); err == nil {
|
|
||||||
host = h // host does contain a port
|
|
||||||
} else if strings.Contains(err.Error(), "missing port in address") {
|
|
||||||
host = req.Host // host does not contain a port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for an ip address
|
|
||||||
if net.ParseIP(host) != nil {
|
|
||||||
return auth.DefaultNamespace
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for dev enviroment
|
|
||||||
if host == "localhost" || host == "127.0.0.1" {
|
|
||||||
return auth.DefaultNamespace
|
|
||||||
}
|
|
||||||
|
|
||||||
// extract the top level domain plus one (e.g. 'myapp.com')
|
|
||||||
domain, err := publicsuffix.EffectiveTLDPlusOne(host)
|
|
||||||
if err != nil {
|
|
||||||
logger.Debugf("Unable to extract domain from %v", host)
|
|
||||||
return auth.DefaultNamespace
|
|
||||||
}
|
|
||||||
|
|
||||||
// check to see if the domain matches the host of micro.mu, in
|
|
||||||
// these cases we return the default namespace
|
|
||||||
if domain == host || domain == "micro.mu" {
|
|
||||||
return auth.DefaultNamespace
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the domain from the host, leaving the subdomain
|
|
||||||
subdomain := strings.TrimSuffix(host, "."+domain)
|
|
||||||
|
|
||||||
// return the reversed subdomain as the namespace
|
|
||||||
comps := strings.Split(subdomain, ".")
|
|
||||||
for i := len(comps)/2 - 1; i >= 0; i-- {
|
|
||||||
opp := len(comps) - 1 - i
|
|
||||||
comps[i], comps[opp] = comps[opp], comps[i]
|
|
||||||
}
|
|
||||||
return strings.Join(comps, ".")
|
|
||||||
}
|
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
package auth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/micro/go-micro/v2/auth"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNamespaceFromRequest(t *testing.T) {
|
|
||||||
tt := []struct {
|
|
||||||
Host string
|
|
||||||
Namespace string
|
|
||||||
}{
|
|
||||||
{Host: "micro.mu", Namespace: auth.DefaultNamespace},
|
|
||||||
{Host: "micro.com.au", Namespace: auth.DefaultNamespace},
|
|
||||||
{Host: "web.micro.mu", Namespace: auth.DefaultNamespace},
|
|
||||||
{Host: "api.micro.mu", Namespace: auth.DefaultNamespace},
|
|
||||||
{Host: "myapp.com", Namespace: auth.DefaultNamespace},
|
|
||||||
{Host: "staging.myapp.com", Namespace: "staging"},
|
|
||||||
{Host: "staging.myapp.m3o.app", Namespace: "myapp.staging"},
|
|
||||||
{Host: "127.0.0.1", Namespace: auth.DefaultNamespace},
|
|
||||||
{Host: "localhost", Namespace: auth.DefaultNamespace},
|
|
||||||
{Host: "81.151.101.146", Namespace: auth.DefaultNamespace},
|
|
||||||
}
|
|
||||||
|
|
||||||
h := &authHandler{namespace: "domain"}
|
|
||||||
|
|
||||||
for _, tc := range tt {
|
|
||||||
t.Run(tc.Host, func(t *testing.T) {
|
|
||||||
ns := h.NamespaceFromRequest(&http.Request{Host: tc.Host, URL: &url.URL{Host: tc.Host}})
|
|
||||||
if ns != tc.Namespace {
|
|
||||||
t.Errorf("Expected namespace %v for host %v, actually got %v", tc.Namespace, tc.Host, ns)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
@ -53,7 +53,7 @@ func (s *httpServer) Init(opts ...server.Option) error {
|
|||||||
|
|
||||||
func (s *httpServer) Handle(path string, handler http.Handler) {
|
func (s *httpServer) Handle(path string, handler http.Handler) {
|
||||||
h := handlers.CombinedLoggingHandler(os.Stdout, handler)
|
h := handlers.CombinedLoggingHandler(os.Stdout, handler)
|
||||||
h = auth.CombinedAuthHandler(s.opts.ServicePrefix, s.opts.Namespace, s.opts.Resolver, handler)
|
h = auth.CombinedAuthHandler(s.opts.Resolver, s.opts.NamespaceResolver, handler)
|
||||||
|
|
||||||
if s.opts.EnableCORS {
|
if s.opts.EnableCORS {
|
||||||
h = cors.CombinedCORSHandler(h)
|
h = cors.CombinedCORSHandler(h)
|
||||||
|
@ -10,15 +10,14 @@ import (
|
|||||||
type Option func(o *Options)
|
type Option func(o *Options)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
EnableACME bool
|
EnableACME bool
|
||||||
EnableCORS bool
|
EnableCORS bool
|
||||||
ACMEProvider acme.Provider
|
ACMEProvider acme.Provider
|
||||||
EnableTLS bool
|
EnableTLS bool
|
||||||
ACMEHosts []string
|
ACMEHosts []string
|
||||||
TLSConfig *tls.Config
|
TLSConfig *tls.Config
|
||||||
Resolver resolver.Resolver
|
Resolver resolver.Resolver
|
||||||
Namespace string
|
NamespaceResolver resolver.NamespaceResolver
|
||||||
ServicePrefix string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func EnableCORS(b bool) Option {
|
func EnableCORS(b bool) Option {
|
||||||
@ -57,20 +56,14 @@ func TLSConfig(t *tls.Config) Option {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ServicePrefix(n string) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.ServicePrefix = n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Namespace(n string) Option {
|
|
||||||
return func(o *Options) {
|
|
||||||
o.Namespace = n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Resolver(r resolver.Resolver) Option {
|
func Resolver(r resolver.Resolver) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
o.Resolver = r
|
o.Resolver = r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NamespaceResolver(r resolver.NamespaceResolver) Option {
|
||||||
|
return func(o *Options) {
|
||||||
|
o.NamespaceResolver = r
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -158,6 +158,11 @@ func (s *svc) Revoke(role string, res *auth.Resource) error {
|
|||||||
|
|
||||||
// Verify an account has access to a resource
|
// Verify an account has access to a resource
|
||||||
func (s *svc) Verify(acc *auth.Account, res *auth.Resource) error {
|
func (s *svc) Verify(acc *auth.Account, res *auth.Resource) error {
|
||||||
|
// set the namespace on the resource
|
||||||
|
if len(res.Namespace) == 0 {
|
||||||
|
res.Namespace = s.Options().Namespace
|
||||||
|
}
|
||||||
|
|
||||||
queries := [][]string{
|
queries := [][]string{
|
||||||
{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, 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, res.Name, "*"}, // check for wildcard endpoint, e.g. service.foo*
|
||||||
@ -205,16 +210,15 @@ func (s *svc) Verify(acc *auth.Account, res *auth.Resource) error {
|
|||||||
func (s *svc) Inspect(token string) (*auth.Account, error) {
|
func (s *svc) Inspect(token string) (*auth.Account, error) {
|
||||||
// try to decode JWT locally and fall back to srv if an error occurs
|
// try to decode JWT locally and fall back to srv if an error occurs
|
||||||
if len(strings.Split(token, ".")) == 3 && s.jwt != nil {
|
if len(strings.Split(token, ".")) == 3 && s.jwt != nil {
|
||||||
if acc, err := s.jwt.Inspect(token); err == nil {
|
return s.jwt.Inspect(token)
|
||||||
return acc, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the token is not a JWT or we do not have the keys to decode it,
|
||||||
|
// fall back to the auth service
|
||||||
rsp, err := s.auth.Inspect(context.TODO(), &pb.InspectRequest{Token: token})
|
rsp, err := s.auth.Inspect(context.TODO(), &pb.InspectRequest{Token: token})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return serializeAccount(rsp.Account), nil
|
return serializeAccount(rsp.Account), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
4
go.sum
4
go.sum
@ -399,6 +399,7 @@ go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
|||||||
go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
|
go.uber.org/multierr v1.3.0 h1:sFPn2GLc3poCkfrpIXGhBD2X0CMIo4Q/zSULXrj/+uc=
|
||||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||||
go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y=
|
go.uber.org/ratelimit v0.0.0-20180316092928-c15da0234277/go.mod h1:2X8KaoNd1J0lZV+PxJk/5+DGbO/tpwLR1m++a7FnB/Y=
|
||||||
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4=
|
||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
|
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
|
||||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||||
@ -432,6 +433,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
|||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
@ -529,6 +531,7 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn
|
|||||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361 h1:RIIXAeV6GvDBuADKumTODatUqANFZ+5BPMnzsy4hulY=
|
||||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -600,6 +603,7 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
|
|||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/micro/go-micro/v2/debug/stats"
|
"github.com/micro/go-micro/v2/debug/stats"
|
||||||
"github.com/micro/go-micro/v2/debug/trace"
|
"github.com/micro/go-micro/v2/debug/trace"
|
||||||
"github.com/micro/go-micro/v2/errors"
|
"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/metadata"
|
||||||
"github.com/micro/go-micro/v2/server"
|
"github.com/micro/go-micro/v2/server"
|
||||||
)
|
)
|
||||||
@ -155,11 +154,6 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper {
|
|||||||
return h(ctx, req, rsp)
|
return h(ctx, req, rsp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for auth service endpoints which should be excluded from auth
|
|
||||||
if strings.HasPrefix(req.Endpoint(), "Auth.") {
|
|
||||||
return h(ctx, req, rsp)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the token if present. Note: if noop is being used
|
// Extract the token if present. Note: if noop is being used
|
||||||
// then the token can be blank without erroring
|
// then the token can be blank without erroring
|
||||||
var token string
|
var token string
|
||||||
@ -172,33 +166,17 @@ func AuthHandler(fn func() auth.Auth) server.HandlerWrapper {
|
|||||||
token = header[len(auth.BearerScheme):]
|
token = header[len(auth.BearerScheme):]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the namespace for the request
|
|
||||||
namespace, ok := metadata.Get(ctx, auth.NamespaceKey)
|
|
||||||
if !ok {
|
|
||||||
logger.Debugf("Missing request namespace")
|
|
||||||
namespace = auth.DefaultNamespace
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inspect the token and get the account
|
// Inspect the token and get the account
|
||||||
account, err := a.Inspect(token)
|
account, err := a.Inspect(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
account = &auth.Account{Namespace: namespace}
|
account = &auth.Account{}
|
||||||
}
|
|
||||||
|
|
||||||
// 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.Debugf("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
|
// construct the resource
|
||||||
res := &auth.Resource{
|
res := &auth.Resource{
|
||||||
Type: "service",
|
Type: "service",
|
||||||
Name: req.Service(),
|
Name: req.Service(),
|
||||||
Endpoint: req.Endpoint(),
|
Endpoint: req.Endpoint(),
|
||||||
Namespace: namespace,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify the caller has access to the resource
|
// Verify the caller has access to the resource
|
||||||
|
Loading…
Reference in New Issue
Block a user