auth/service support for micro clients (rules from mutltiple namespaces
This commit is contained in:
parent
8f5ef012ff
commit
e876cb917d
@ -6,6 +6,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/micro/go-micro/v2/metadata"
|
||||||
|
|
||||||
"github.com/micro/go-micro/v2/auth"
|
"github.com/micro/go-micro/v2/auth"
|
||||||
"github.com/micro/go-micro/v2/auth/rules"
|
"github.com/micro/go-micro/v2/auth/rules"
|
||||||
pb "github.com/micro/go-micro/v2/auth/service/proto"
|
pb "github.com/micro/go-micro/v2/auth/service/proto"
|
||||||
@ -22,7 +24,7 @@ type svc struct {
|
|||||||
auth pb.AuthService
|
auth pb.AuthService
|
||||||
rule pb.RulesService
|
rule pb.RulesService
|
||||||
jwt token.Provider
|
jwt token.Provider
|
||||||
rules []*auth.Rule
|
rules map[string][]*auth.Rule
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +93,7 @@ func (s *svc) Grant(rule *auth.Rule) error {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
go s.loadRules()
|
go s.loadRules(s.options.Namespace)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,12 +102,12 @@ func (s *svc) Revoke(rule *auth.Rule) error {
|
|||||||
_, err := s.rule.Delete(context.TODO(), &pb.DeleteRequest{
|
_, err := s.rule.Delete(context.TODO(), &pb.DeleteRequest{
|
||||||
Id: rule.ID,
|
Id: rule.ID,
|
||||||
})
|
})
|
||||||
go s.loadRules()
|
go s.loadRules(s.options.Namespace)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *svc) Rules() ([]*auth.Rule, error) {
|
func (s *svc) Rules() ([]*auth.Rule, error) {
|
||||||
return s.rules, nil
|
return s.rules[s.options.Namespace], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify an account has access to a resource
|
// Verify an account has access to a resource
|
||||||
@ -116,10 +118,10 @@ func (s *svc) Verify(acc *auth.Account, res *auth.Resource, opts ...auth.VerifyO
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load the rules if none are loaded
|
// load the rules if none are loaded
|
||||||
s.loadRulesIfEmpty()
|
s.loadRulesIfEmpty(options.Scope)
|
||||||
|
|
||||||
// verify the request using the rules
|
// verify the request using the rules
|
||||||
return rules.Verify(options.Scope, s.rules, acc, res)
|
return rules.Verify(options.Scope, s.rules[options.Scope], acc, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inspect a token
|
// Inspect a token
|
||||||
@ -184,18 +186,17 @@ func accessForRule(rule *pb.Rule, acc *auth.Account, res *auth.Resource) pb.Acce
|
|||||||
return pb.Access_UNKNOWN
|
return pb.Access_UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadRules retrieves the rules from the auth service
|
// loadRules retrieves the rules from the auth service. Since this implementation is used by micro
|
||||||
func (s *svc) loadRules() {
|
// clients, which support muti-tenancy we may have to persist rules in multiple namespaces.
|
||||||
rsp, err := s.rule.List(context.TODO(), &pb.ListRequest{})
|
func (s *svc) loadRules(namespace string) {
|
||||||
s.Lock()
|
ctx := metadata.Set(context.TODO(), "Micro-Namespace", namespace)
|
||||||
defer s.Unlock()
|
rsp, err := s.rule.List(ctx, &pb.ListRequest{})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error listing rules: %v", err)
|
log.Errorf("Error listing rules: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.rules = make([]*auth.Rule, 0, len(rsp.Rules))
|
rules := make([]*auth.Rule, 0, len(rsp.Rules))
|
||||||
for _, r := range rsp.Rules {
|
for _, r := range rsp.Rules {
|
||||||
var access auth.Access
|
var access auth.Access
|
||||||
if r.Access == pb.Access_GRANTED {
|
if r.Access == pb.Access_GRANTED {
|
||||||
@ -204,7 +205,7 @@ func (s *svc) loadRules() {
|
|||||||
access = auth.AccessDenied
|
access = auth.AccessDenied
|
||||||
}
|
}
|
||||||
|
|
||||||
s.rules = append(s.rules, &auth.Rule{
|
rules = append(rules, &auth.Rule{
|
||||||
ID: r.Id,
|
ID: r.Id,
|
||||||
Role: r.Role,
|
Role: r.Role,
|
||||||
Access: access,
|
Access: access,
|
||||||
@ -216,15 +217,19 @@ func (s *svc) loadRules() {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.Lock()
|
||||||
|
s.rules[namespace] = rules
|
||||||
|
s.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *svc) loadRulesIfEmpty() {
|
func (s *svc) loadRulesIfEmpty(namespace string) {
|
||||||
s.Lock()
|
s.Lock()
|
||||||
rules := s.rules
|
rules := s.rules
|
||||||
s.Unlock()
|
s.Unlock()
|
||||||
|
|
||||||
if len(rules) == 0 {
|
if _, ok := rules[namespace]; !ok {
|
||||||
s.loadRules()
|
s.loadRules(namespace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,6 +263,7 @@ func NewAuth(opts ...auth.Option) auth.Auth {
|
|||||||
service := &svc{
|
service := &svc{
|
||||||
auth: pb.NewAuthService("go.micro.auth", options.Client),
|
auth: pb.NewAuthService("go.micro.auth", options.Client),
|
||||||
rule: pb.NewRulesService("go.micro.auth", options.Client),
|
rule: pb.NewRulesService("go.micro.auth", options.Client),
|
||||||
|
rules: make(map[string][]*auth.Rule),
|
||||||
options: options,
|
options: options,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -268,7 +274,10 @@ func NewAuth(opts ...auth.Option) auth.Auth {
|
|||||||
for {
|
for {
|
||||||
<-ruleTimer.C
|
<-ruleTimer.C
|
||||||
time.Sleep(jitter.Do(time.Second * 5))
|
time.Sleep(jitter.Do(time.Second * 5))
|
||||||
service.loadRules()
|
|
||||||
|
for ns := range service.rules {
|
||||||
|
service.loadRules(ns)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user