add authenticate the specified route
This commit is contained in:
parent
9690eb2cd6
commit
b2d87e8e29
|
|
@ -78,6 +78,8 @@ type OAuthProxy struct {
|
||||||
|
|
||||||
SignInPath string
|
SignInPath string
|
||||||
|
|
||||||
|
enableAuthRouters bool
|
||||||
|
authRouters []allowedRoute
|
||||||
allowedRoutes []allowedRoute
|
allowedRoutes []allowedRoute
|
||||||
apiRoutes []apiRoute
|
apiRoutes []apiRoute
|
||||||
redirectURL *url.URL // the url to receive requests at
|
redirectURL *url.URL // the url to receive requests at
|
||||||
|
|
@ -180,6 +182,11 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authRouters, err := buildProxyRoutersList(opts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
apiRoutes, err := buildAPIRoutes(opts)
|
apiRoutes, err := buildAPIRoutes(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -230,6 +237,8 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
|
||||||
upstreamProxy: upstreamProxy,
|
upstreamProxy: upstreamProxy,
|
||||||
redirectValidator: redirectValidator,
|
redirectValidator: redirectValidator,
|
||||||
appDirector: appDirector,
|
appDirector: appDirector,
|
||||||
|
authRouters: authRouters,
|
||||||
|
enableAuthRouters: opts.EnableAuthRouters,
|
||||||
}
|
}
|
||||||
p.buildServeMux(opts.ProxyPrefix)
|
p.buildServeMux(opts.ProxyPrefix)
|
||||||
|
|
||||||
|
|
@ -485,6 +494,34 @@ func buildRoutesAllowlist(opts *options.Options) ([]allowedRoute, error) {
|
||||||
return routes, nil
|
return routes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildProxyRoutersList(opts *options.Options) ([]allowedRoute, error) {
|
||||||
|
routes := make([]allowedRoute, 0, len(opts.AuthRouters))
|
||||||
|
|
||||||
|
for _, mPath := range opts.AuthRouters {
|
||||||
|
method, path := "", ""
|
||||||
|
|
||||||
|
ps := strings.SplitN(mPath, "=", 2)
|
||||||
|
if len(ps) == 1 {
|
||||||
|
path = ps[0]
|
||||||
|
} else {
|
||||||
|
method = strings.ToUpper(ps[0])
|
||||||
|
path = ps[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
compiledRegex, err := regexp.Compile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
routes = append(routes, allowedRoute{
|
||||||
|
method: method,
|
||||||
|
pathRegex: compiledRegex,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes, nil
|
||||||
|
}
|
||||||
|
|
||||||
// buildAPIRoutes builds an []apiRoute from ApiRoutes option
|
// buildAPIRoutes builds an []apiRoute from ApiRoutes option
|
||||||
func buildAPIRoutes(opts *options.Options) ([]apiRoute, error) {
|
func buildAPIRoutes(opts *options.Options) ([]apiRoute, error) {
|
||||||
routes := make([]apiRoute, 0, len(opts.APIRoutes))
|
routes := make([]apiRoute, 0, len(opts.APIRoutes))
|
||||||
|
|
@ -573,6 +610,16 @@ func (p *OAuthProxy) isAllowedRoute(req *http.Request) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *OAuthProxy) isProxyRoute(req *http.Request) bool {
|
||||||
|
for _, route := range p.authRouters {
|
||||||
|
if (route.method == "" || req.Method == route.method) && route.pathRegex.MatchString(req.URL.Path) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (p *OAuthProxy) isAPIPath(req *http.Request) bool {
|
func (p *OAuthProxy) isAPIPath(req *http.Request) bool {
|
||||||
for _, route := range p.apiRoutes {
|
for _, route := range p.apiRoutes {
|
||||||
if route.pathRegex.MatchString(req.URL.Path) {
|
if route.pathRegex.MatchString(req.URL.Path) {
|
||||||
|
|
@ -1045,6 +1092,10 @@ func (p *OAuthProxy) getAuthenticatedSession(rw http.ResponseWriter, req *http.R
|
||||||
return session, nil
|
return session, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.enableAuthRouters && !p.isProxyRoute(req) {
|
||||||
|
return session, nil
|
||||||
|
}
|
||||||
|
|
||||||
if session == nil {
|
if session == nil {
|
||||||
return nil, ErrNeedsLogin
|
return nil, ErrNeedsLogin
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -60,6 +60,8 @@ type Options struct {
|
||||||
SSLInsecureSkipVerify bool `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify"`
|
SSLInsecureSkipVerify bool `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify"`
|
||||||
SkipAuthPreflight bool `flag:"skip-auth-preflight" cfg:"skip_auth_preflight"`
|
SkipAuthPreflight bool `flag:"skip-auth-preflight" cfg:"skip_auth_preflight"`
|
||||||
ForceJSONErrors bool `flag:"force-json-errors" cfg:"force_json_errors"`
|
ForceJSONErrors bool `flag:"force-json-errors" cfg:"force_json_errors"`
|
||||||
|
EnableAuthRouters bool `flag:"enable-auth-routers" cfg:"enable_auth_routers"`
|
||||||
|
AuthRouters []string `flag:"auth-routers" cfg:"auth_routers"`
|
||||||
|
|
||||||
SignatureKey string `flag:"signature-key" cfg:"signature_key"`
|
SignatureKey string `flag:"signature-key" cfg:"signature_key"`
|
||||||
GCPHealthChecks bool `flag:"gcp-healthchecks" cfg:"gcp_healthchecks"`
|
GCPHealthChecks bool `flag:"gcp-healthchecks" cfg:"gcp_healthchecks"`
|
||||||
|
|
@ -124,6 +126,8 @@ func NewFlagSet() *pflag.FlagSet {
|
||||||
flagSet.Bool("skip-auth-preflight", false, "will skip authentication for OPTIONS requests")
|
flagSet.Bool("skip-auth-preflight", false, "will skip authentication for OPTIONS requests")
|
||||||
flagSet.Bool("ssl-insecure-skip-verify", false, "skip validation of certificates presented when using HTTPS providers")
|
flagSet.Bool("ssl-insecure-skip-verify", false, "skip validation of certificates presented when using HTTPS providers")
|
||||||
flagSet.Bool("skip-jwt-bearer-tokens", false, "will skip requests that have verified JWT bearer tokens (default false)")
|
flagSet.Bool("skip-jwt-bearer-tokens", false, "will skip requests that have verified JWT bearer tokens (default false)")
|
||||||
|
flagSet.Bool("enable-auth-routers", false, "will proxy only routes configured by authrouters")
|
||||||
|
flagSet.StringSlice("auth-routers", []string{}, "authentication for requests that match the method & path. Format: method=path_regex OR path_regex alone for all methods.")
|
||||||
flagSet.Bool("force-json-errors", false, "will force JSON errors instead of HTTP error pages or redirects")
|
flagSet.Bool("force-json-errors", false, "will force JSON errors instead of HTTP error pages or redirects")
|
||||||
flagSet.StringSlice("extra-jwt-issuers", []string{}, "if skip-jwt-bearer-tokens is set, a list of extra JWT issuer=audience pairs (where the issuer URL has a .well-known/openid-configuration or a .well-known/jwks.json)")
|
flagSet.StringSlice("extra-jwt-issuers", []string{}, "if skip-jwt-bearer-tokens is set, a list of extra JWT issuer=audience pairs (where the issuer URL has a .well-known/openid-configuration or a .well-known/jwks.json)")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,25 @@ func validateAPIRoutes(o *options.Options) []string {
|
||||||
return validateRegexes(o.APIRoutes)
|
return validateRegexes(o.APIRoutes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validateAuthRoutes validates method=path routes passed with options.AuthRouters
|
||||||
|
func validateAuthRoutes1(o *options.Options) []string {
|
||||||
|
msgs := []string{}
|
||||||
|
for _, route := range o.AuthRouters {
|
||||||
|
var regex string
|
||||||
|
parts := strings.SplitN(route, "=", 2)
|
||||||
|
if len(parts) == 1 {
|
||||||
|
regex = parts[0]
|
||||||
|
} else {
|
||||||
|
regex = parts[1]
|
||||||
|
}
|
||||||
|
_, err := regexp.Compile(regex)
|
||||||
|
if err != nil {
|
||||||
|
msgs = append(msgs, fmt.Sprintf("error compiling regex /%s/: %v", regex, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msgs
|
||||||
|
}
|
||||||
|
|
||||||
// validateRegexes validates all regexes and returns a list of messages in case of error
|
// validateRegexes validates all regexes and returns a list of messages in case of error
|
||||||
func validateRegexes(regexes []string) []string {
|
func validateRegexes(regexes []string) []string {
|
||||||
msgs := []string{}
|
msgs := []string{}
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,8 @@ func Validate(o *options.Options) error {
|
||||||
// Do this after ReverseProxy validation for TrustedIP coordinated checks
|
// Do this after ReverseProxy validation for TrustedIP coordinated checks
|
||||||
msgs = append(msgs, validateAllowlists(o)...)
|
msgs = append(msgs, validateAllowlists(o)...)
|
||||||
|
|
||||||
|
msgs = append(msgs, validateAuthRoutes1(o)...)
|
||||||
|
|
||||||
if len(msgs) != 0 {
|
if len(msgs) != 0 {
|
||||||
return fmt.Errorf("invalid configuration:\n %s",
|
return fmt.Errorf("invalid configuration:\n %s",
|
||||||
strings.Join(msgs, "\n "))
|
strings.Join(msgs, "\n "))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue