Use InitOptions for all plugins, fix plugins/router/jwt header forwarding
continuous-integration/drone/tag Build is passing Details

main v0.3.0
René Jochum 2 years ago
parent 64e65bff8d
commit 317cb0befd
Signed by: jochum
GPG Key ID: F7D906F5E51E8E5E

@ -237,7 +237,7 @@ func main() {
os.Exit(0)
}
if err := auth2ClientReg.Init(c, srv); err != nil {
if err := auth2ClientReg.Init(auth2.CliContext(c), auth2.Service(srv), auth2.Logrus(ilogger.Logrus())); err != nil {
ilogger.Logrus().Fatal(err)
}

@ -80,12 +80,13 @@ require (
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.0.0-20220920203100-d0c6ba3f52d9 // indirect
golang.org/x/net v0.0.0-20220921203646-d300de134e69 // indirect
golang.org/x/sync v0.0.0-20220907140024-f12130a52804 // indirect
golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 // indirect
golang.org/x/tools v0.1.12 // indirect
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006 // indirect
google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 // indirect
google.golang.org/grpc v1.49.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect

@ -1259,7 +1259,6 @@ go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
@ -1421,8 +1420,8 @@ golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220920203100-d0c6ba3f52d9 h1:asZqf0wXastQr+DudYagQS8uBO8bHKeYD1vbAvGmFL8=
golang.org/x/net v0.0.0-20220920203100-d0c6ba3f52d9/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.0.0-20220921203646-d300de134e69 h1:hUJpGDpnfwdJW8iNypFjmSY0sCBEL+spFTZ2eO+Sfps=
golang.org/x/net v0.0.0-20220921203646-d300de134e69/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1609,8 +1608,9 @@ golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65 h1:M73Iuj3xbbb9Uk1DYhzydthsj6oOd6l9bpuFcNoUvTs=
golang.org/x/time v0.0.0-20220224211638-0e9765cccd65/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9 h1:ftMN5LMiBFjbzleLqtoBZk7KdJwhuybIU+FckUHgoyQ=
golang.org/x/time v0.0.0-20220722155302-e5dcc9cfc0b9/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -1816,8 +1816,8 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220111164026-67b88f271998/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006 h1:mmbq5q8M1t7dhkLw320YK4PsOXm6jdnUAkErImaIqOg=
google.golang.org/genproto v0.0.0-20220920201722-2b89144ce006/go.mod h1:ht8XFiar2npT/g4vkk7O0WYS1sHOHbdujxbEp7CJWbw=
google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 h1:K1zaaMdYBXRyX+cwFnxj7M6zwDyumLQMZ5xqwGvjreQ=
google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737/go.mod h1:2r/26NEF3bFmT3eC3aZreahSal0C3Shl8Gi6vyDYqOQ=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=

@ -6,7 +6,6 @@ import (
"github.com/google/uuid"
"github.com/urfave/cli/v2"
"go-micro.dev/v4"
"go-micro.dev/v4/server"
)
@ -29,7 +28,7 @@ func (p *noopClientPlugin) MergeFlags(flags []cli.Flag) []cli.Flag {
return flags
}
func (p *noopClientPlugin) Init(cli *cli.Context, service micro.Service) error {
func (p *noopClientPlugin) Init(opts ...InitOption) error {
return nil
}
@ -70,7 +69,7 @@ func (p *noopRouterPlugin) MergeFlags(flags []cli.Flag) []cli.Flag {
return flags
}
func (p *noopRouterPlugin) Init(cli *cli.Context, service micro.Service) error {
func (p *noopRouterPlugin) Init(opts ...InitOption) error {
return nil
}

@ -0,0 +1,48 @@
package auth2
import (
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
"go-micro.dev/v4"
"go-micro.dev/v4/errors"
)
type InitOptions struct {
CliContext *cli.Context
Service micro.Service
Logrus *logrus.Logger
}
type InitOption func(o *InitOptions)
func CliContext(n *cli.Context) InitOption {
return func(o *InitOptions) {
o.CliContext = n
}
}
func Service(n micro.Service) InitOption {
return func(o *InitOptions) {
o.Service = n
}
}
func Logrus(n *logrus.Logger) InitOption {
return func(o *InitOptions) {
o.Logrus = n
}
}
func NewInitOptions(opts ...InitOption) (InitOptions, error) {
options := InitOptions{}
for _, o := range opts {
o(&options)
}
// Make CliContext() required
if options.CliContext == nil {
return options, errors.InternalServerError("auth2.NewInitOptions:no cli.Context", "no cli.Context hase been given")
}
return options, nil
}

@ -5,7 +5,6 @@ import (
"net/http"
"github.com/urfave/cli/v2"
"go-micro.dev/v4"
"go-micro.dev/v4/server"
)
@ -17,7 +16,7 @@ type registryFuncs interface {
MergeFlags(flags []cli.Flag) []cli.Flag
// Init should be executed in micro.Init
Init(cli *cli.Context, service micro.Service) error
Init(opts ...InitOption) error
// Stop should be executed after service.Run()
Stop() error

@ -11,7 +11,6 @@ import (
"github.com/golang-jwt/jwt/v4"
"github.com/urfave/cli/v2"
"go-micro.dev/v4"
"go-micro.dev/v4/metadata"
"go-micro.dev/v4/server"
"jochum.dev/jo-micro/auth2"
@ -61,21 +60,26 @@ func (p *jwtPlugin) MergeFlags(flags []cli.Flag) []cli.Flag {
)
}
func (p *jwtPlugin) Init(cli *cli.Context, service micro.Service) error {
if len(cli.String("auth2_jwt_pub_key")) < 1 || len(cli.String("auth2_jwt_priv_key")) < 1 {
func (p *jwtPlugin) Init(opts ...auth2.InitOption) error {
options, err := auth2.NewInitOptions(opts...)
if err != nil {
return err
}
if len(options.CliContext.String("auth2_jwt_pub_key")) < 1 || len(options.CliContext.String("auth2_jwt_priv_key")) < 1 {
return errors.New("you must provide auth2_jwt_(priv|pub)_key")
}
if cli.StringSlice("auth2_jwt_audience") == nil {
if options.CliContext.StringSlice("auth2_jwt_audience") == nil {
return errors.New("MICRO_AUTH2_JWT_AUDIENCES must be given")
}
pub, priv, err := sjwt.DecodeKeyPair(cli.String("auth2_jwt_pub_key"), cli.String("auth2_jwt_priv_key"))
pub, priv, err := sjwt.DecodeKeyPair(options.CliContext.String("auth2_jwt_pub_key"), options.CliContext.String("auth2_jwt_priv_key"))
if err != nil {
return err
}
p.audiences = cli.StringSlice("auth2_jwt_audience")
p.audiences = options.CliContext.StringSlice("auth2_jwt_audience")
p.pubKey = pub
p.privKey = priv

@ -5,15 +5,16 @@ import (
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"net/http"
"strings"
"github.com/golang-jwt/jwt/v4"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
"go-micro.dev/v4"
"go-micro.dev/v4/errors"
"go-micro.dev/v4/metadata"
"jochum.dev/jo-micro/auth2"
auth "jochum.dev/jo-micro/auth2"
"jochum.dev/jo-micro/auth2/shared/sjwt"
"jochum.dev/jo-micro/auth2/shared/sutil"
@ -28,7 +29,16 @@ func newJWTPlugin() auth.RouterPlugin {
}
type jwtPlugin struct {
pubKey any
pubKey any
options auth2.InitOptions
}
func (p *jwtPlugin) logrus() *logrus.Logger {
if p.options.Logrus == nil {
return logrus.StandardLogger()
}
return p.options.Logrus
}
func (p *jwtPlugin) String() string {
@ -43,18 +53,23 @@ func (p *jwtPlugin) MergeFlags(flags []cli.Flag) []cli.Flag {
})
}
func (p *jwtPlugin) Init(cli *cli.Context, service micro.Service) error {
if len(cli.String("auth2_jwt_pub_key")) < 1 {
return errors.New("you must provide auth2_jwt_pub_key")
func (p *jwtPlugin) Init(opts ...auth2.InitOption) error {
options, err := auth2.NewInitOptions(opts...)
if err != nil {
return err
}
if len(options.CliContext.String("auth2_jwt_pub_key")) < 1 {
return errors.InternalServerError("auth2/plugins/router/jwt.Init:No auth2_jwt_pub_key", "you must provide auth2_jwt_pub_key")
}
aPub, err := base64.StdEncoding.DecodeString(cli.String("auth2_jwt_pub_key"))
aPub, err := base64.StdEncoding.DecodeString(options.CliContext.String("auth2_jwt_pub_key"))
if err != nil {
return err
}
block, _ := pem.Decode(aPub)
if block == nil {
return errors.New("failed to parse PEM block containing the key")
return errors.InternalServerError("auth2/plugins/router/jwt.Init:PEM parsing", "failed to parse PEM block containing the key")
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
@ -76,11 +91,12 @@ func (p *jwtPlugin) Health(ctx context.Context) (string, error) {
}
func (p *jwtPlugin) Inspect(r *http.Request) (*auth.User, error) {
if h := r.Header.Get("Authorization"); len(h) > 0 {
return nil, errors.New("failed to get Authorization header from context")
if _, ok := r.Header["Authorization"]; !ok {
p.logrus().WithField("headers", r.Header).Debug("empty or no Authorization header in request")
return nil, errors.InternalServerError("auth2/plugins/router/jwt.Inspect", "empty or no Authorization header in request")
}
aTokenString, _, err := sutil.ExtractToken(r.Header.Get("Authorization"))
aTokenString, _, err := sutil.ExtractToken(r.Header["Authorization"][0])
if err != nil {
return nil, err
}
@ -105,7 +121,7 @@ func (p *jwtPlugin) Inspect(r *http.Request) (*auth.User, error) {
}
func (p *jwtPlugin) ForwardContext(r *http.Request, ctx context.Context) (context.Context, error) {
_, err := p.Inspect(r)
u, err := p.Inspect(r)
if err != nil {
return ctx, err
}
@ -118,5 +134,7 @@ func (p *jwtPlugin) ForwardContext(r *http.Request, ctx context.Context) (contex
md["X-Fowarded-For"] = v
}
p.logrus().WithField("username", u.Metadata["Subject"]).Trace("Forwarding user")
return metadata.MergeContext(ctx, md, true), nil
}

@ -11,21 +11,24 @@ import (
)
type EndpointRolesVerifier struct {
rules map[string]Rule
options Options
rules map[string]Rule
endpointnames []string
options Options
}
func NewVerifier(opts ...Option) *EndpointRolesVerifier {
options := NewOptions(opts...)
return &EndpointRolesVerifier{
rules: make(map[string]Rule, 0),
options: options,
rules: make(map[string]Rule, 0),
endpointnames: []string{},
options: options,
}
}
func (v *EndpointRolesVerifier) AddRules(rules ...Rule) {
for _, rule := range rules {
v.endpointnames = append(v.endpointnames, rule.Endpoint)
v.rules[rule.Endpoint] = rule
}
}
@ -51,16 +54,16 @@ func (v *EndpointRolesVerifier) Verify(ctx context.Context, u *auth2.User, req s
}
if v.options.DefaultDeny {
v.logrus().WithField("endpoint", req.Endpoint()).Debug("DefaultDeny: not in RolesAllow/Deny")
return errors.Unauthorized("auth2/plugins/verifier/endpointroles/EndpointRolesVerifier.Verify|No matching Role", "Unauthorized")
v.logrus().WithField("endpoint", req.Endpoint()).WithField("user_roles", u.Roles).WithField("roles_allow", ep.RolesAllow).Debug("DefaultDeny: No matching role")
return errors.Unauthorized("auth2/plugins/verifier/endpointroles/EndpointRolesVerifier.Verify|No matching role", "Unauthorized")
}
}
if !v.options.DefaultDeny {
v.logrus().WithField("endpoint", req.Endpoint()).Trace("DefaultAllow: no rule")
v.logrus().WithField("endpoint", req.Endpoint()).WithField("endpoints", v.endpointnames).Trace("DefaultAllow: No rule")
return nil
}
v.logrus().WithField("endpoint", req.Endpoint()).Debug("DefaultDeny: no rule")
return errors.Unauthorized("auth2/plugins/verifier/endpointroles/EndpointRolesVerifier.Verify|No rule for EP", "Unauthorized")
v.logrus().WithField("endpoint", req.Endpoint()).WithField("endpoints", v.endpointnames).Debug("DefaultDeny: no rule")
return errors.Unauthorized("auth2/plugins/verifier/endpointroles/EndpointRolesVerifier.Verify|No rule", "Unauthorized")
}

@ -6,7 +6,6 @@ import (
"strings"
"github.com/urfave/cli/v2"
"go-micro.dev/v4"
"go-micro.dev/v4/errors"
"go-micro.dev/v4/server"
"jochum.dev/jo-micro/auth2/shared/sutil"
@ -76,9 +75,14 @@ func (r *AuthRegistry[T]) Plugin() T {
}
// Init should be executed in micro.Init
func (r *AuthRegistry[T]) Init(cli *cli.Context, service micro.Service) error {
func (r *AuthRegistry[T]) Init(opts ...InitOption) error {
options, err := NewInitOptions(opts...)
if err != nil {
return err
}
if r.forcedPlugin == "" {
plugin := cli.String(fmt.Sprintf("auth2_%s", r.kind))
plugin := options.CliContext.String(fmt.Sprintf("auth2_%s", r.kind))
m, ok := r.plugins[plugin]
if !ok {
return fmt.Errorf("unknown MICRO_AUTH2_%s plugin '%s'", strings.ToUpper(r.kind), plugin)
@ -88,7 +92,7 @@ func (r *AuthRegistry[T]) Init(cli *cli.Context, service micro.Service) error {
}
m2, _ := any(r.plugin).(registryFuncs)
return m2.Init(cli, service)
return m2.Init(opts...)
}
// Stop should be executed after service.Run()

Loading…
Cancel
Save