diff --git a/service.go b/service.go index f37dc83b..9c414654 100644 --- a/service.go +++ b/service.go @@ -1,13 +1,11 @@ package micro import ( - "fmt" "os" "os/signal" rtime "runtime" "strings" "sync" - "time" "github.com/micro/go-micro/v2/auth" "github.com/micro/go-micro/v2/client" @@ -19,6 +17,7 @@ import ( "github.com/micro/go-micro/v2/plugin" "github.com/micro/go-micro/v2/server" "github.com/micro/go-micro/v2/store" + authutil "github.com/micro/go-micro/v2/util/auth" signalutil "github.com/micro/go-micro/v2/util/signal" "github.com/micro/go-micro/v2/util/wrapper" ) @@ -177,7 +176,7 @@ func (s *service) Stop() error { func (s *service) Run() error { // generate an auth account - if err := s.generateAccount(); err != nil { + if err := authutil.Generate(s.Server().Options().Id, s.Name(), s.Options().Auth); err != nil { return err } @@ -224,73 +223,3 @@ func (s *service) Run() error { return s.Stop() } - -func (s *service) generateAccount() error { - // extract the account creds from options, these can be set by flags - accID := s.Options().Auth.Options().ID - accSecret := s.Options().Auth.Options().Secret - - // if no credentials were provided, generate an account - if len(accID) == 0 || len(accSecret) == 0 { - name := fmt.Sprintf("%v-%v", s.Name(), s.Server().Options().Id) - opts := []auth.GenerateOption{ - auth.WithType("service"), - auth.WithRoles("service"), - auth.WithNamespace(s.Options().Auth.Options().Namespace), - } - - acc, err := s.Options().Auth.Generate(name, opts...) - if err != nil { - return err - } - logger.Infof("Auth [%v] Authenticated as %v", s.Options().Auth, name) - - accID = acc.ID - accSecret = acc.Secret - } - - // generate the first token - token, err := s.Options().Auth.Token( - auth.WithCredentials(accID, accSecret), - auth.WithExpiry(time.Minute*10), - ) - if err != nil { - return err - } - - // set the credentials and token in auth options - s.Options().Auth.Init( - auth.ClientToken(token), - auth.Credentials(accID, accSecret), - ) - - // periodically check to see if the token needs refreshing - go func() { - timer := time.NewTicker(time.Second * 15) - - for { - <-timer.C - - // don't refresh the token if it's not close to expiring - tok := s.Options().Auth.Options().Token - if tok.Expiry.Unix() > time.Now().Add(time.Minute).Unix() { - continue - } - - // generate the first token - tok, err := s.Options().Auth.Token( - auth.WithCredentials(accID, accSecret), - auth.WithExpiry(time.Minute*10), - ) - if err != nil { - logger.Warnf("[Auth] Error refreshing token: %v", err) - continue - } - - // set the token - s.Options().Auth.Init(auth.ClientToken(tok)) - } - }() - - return nil -} diff --git a/util/auth/auth.go b/util/auth/auth.go new file mode 100644 index 00000000..454c5e9e --- /dev/null +++ b/util/auth/auth.go @@ -0,0 +1,81 @@ +package auth + +import ( + "fmt" + "time" + + "github.com/micro/go-micro/v2/auth" + "github.com/micro/go-micro/v2/logger" +) + +// Generate generates a service account for and continually +// refreshes the access token. +func Generate(id string, name string, a auth.Auth) error { + // extract the account creds from options, these can be set by flags + accID := a.Options().ID + accSecret := a.Options().Secret + + // if no credentials were provided, generate an account + if len(accID) == 0 || len(accSecret) == 0 { + name := fmt.Sprintf("%v-%v", name, id) + opts := []auth.GenerateOption{ + auth.WithType("service"), + auth.WithRoles("service"), + auth.WithNamespace(a.Options().Namespace), + } + + acc, err := a.Generate(name, opts...) + if err != nil { + return err + } + logger.Infof("Auth [%v] Authenticated as %v in the %v namespace", a, name, acc.Namespace) + + accID = acc.ID + accSecret = acc.Secret + } + + // generate the first token + token, err := a.Token( + auth.WithCredentials(accID, accSecret), + auth.WithExpiry(time.Minute*10), + ) + if err != nil { + return err + } + + // set the credentials and token in auth options + a.Init( + auth.ClientToken(token), + auth.Credentials(accID, accSecret), + ) + + // periodically check to see if the token needs refreshing + go func() { + timer := time.NewTicker(time.Second * 15) + + for { + <-timer.C + + // don't refresh the token if it's not close to expiring + tok := a.Options().Token + if tok.Expiry.Unix() > time.Now().Add(time.Minute).Unix() { + continue + } + + // generate the first token + tok, err := a.Token( + auth.WithCredentials(accID, accSecret), + auth.WithExpiry(time.Minute*10), + ) + if err != nil { + logger.Warnf("[Auth] Error refreshing token: %v", err) + continue + } + + // set the token + a.Init(auth.ClientToken(tok)) + } + }() + + return nil +} diff --git a/web/service.go b/web/service.go index 4ca54f88..c9efc25a 100644 --- a/web/service.go +++ b/web/service.go @@ -17,6 +17,7 @@ import ( "github.com/micro/go-micro/v2/logger" "github.com/micro/go-micro/v2/registry" maddr "github.com/micro/go-micro/v2/util/addr" + authutil "github.com/micro/go-micro/v2/util/auth" mhttp "github.com/micro/go-micro/v2/util/http" mnet "github.com/micro/go-micro/v2/util/net" signalutil "github.com/micro/go-micro/v2/util/signal" @@ -421,6 +422,13 @@ func (s *service) Init(opts ...Option) error { } func (s *service) Run() error { + // generate an auth account + srvID := s.opts.Service.Server().Options().Id + srvName := s.opts.Service.Name() + if err := authutil.Generate(srvID, srvName, s.opts.Service.Options().Auth); err != nil { + return err + } + if err := s.start(); err != nil { return err }