add authenticate the specified route

This commit is contained in:
lixianlin01 2023-05-17 17:35:10 +08:00
parent 9690eb2cd6
commit b2d87e8e29
4 changed files with 76 additions and 0 deletions

View File

@ -78,6 +78,8 @@ type OAuthProxy struct {
SignInPath string
enableAuthRouters bool
authRouters []allowedRoute
allowedRoutes []allowedRoute
apiRoutes []apiRoute
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
}
authRouters, err := buildProxyRoutersList(opts)
if err != nil {
return nil, err
}
apiRoutes, err := buildAPIRoutes(opts)
if err != nil {
return nil, err
@ -230,6 +237,8 @@ func NewOAuthProxy(opts *options.Options, validator func(string) bool) (*OAuthPr
upstreamProxy: upstreamProxy,
redirectValidator: redirectValidator,
appDirector: appDirector,
authRouters: authRouters,
enableAuthRouters: opts.EnableAuthRouters,
}
p.buildServeMux(opts.ProxyPrefix)
@ -485,6 +494,34 @@ func buildRoutesAllowlist(opts *options.Options) ([]allowedRoute, error) {
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
func buildAPIRoutes(opts *options.Options) ([]apiRoute, error) {
routes := make([]apiRoute, 0, len(opts.APIRoutes))
@ -573,6 +610,16 @@ func (p *OAuthProxy) isAllowedRoute(req *http.Request) bool {
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 {
for _, route := range p.apiRoutes {
if route.pathRegex.MatchString(req.URL.Path) {
@ -1045,6 +1092,10 @@ func (p *OAuthProxy) getAuthenticatedSession(rw http.ResponseWriter, req *http.R
return session, nil
}
if p.enableAuthRouters && !p.isProxyRoute(req) {
return session, nil
}
if session == nil {
return nil, ErrNeedsLogin
}

View File

@ -60,6 +60,8 @@ type Options struct {
SSLInsecureSkipVerify bool `flag:"ssl-insecure-skip-verify" cfg:"ssl_insecure_skip_verify"`
SkipAuthPreflight bool `flag:"skip-auth-preflight" cfg:"skip_auth_preflight"`
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"`
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("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("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.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)")

View File

@ -67,6 +67,25 @@ func validateAPIRoutes(o *options.Options) []string {
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
func validateRegexes(regexes []string) []string {
msgs := []string{}

View File

@ -100,6 +100,8 @@ func Validate(o *options.Options) error {
// Do this after ReverseProxy validation for TrustedIP coordinated checks
msgs = append(msgs, validateAllowlists(o)...)
msgs = append(msgs, validateAuthRoutes1(o)...)
if len(msgs) != 0 {
return fmt.Errorf("invalid configuration:\n %s",
strings.Join(msgs, "\n "))