Extend bypass middleware with support of wildcard paths (#1628)

---------

Co-authored-by: Viktor Liu <viktor@netbird.io>
This commit is contained in:
Yury Gargay
2024-02-26 17:54:58 +01:00
committed by GitHub
parent e1c50248d9
commit d8ce08d898
3 changed files with 72 additions and 6 deletions

View File

@@ -1,8 +1,12 @@
package bypass
import (
"fmt"
"net/http"
"path"
"sync"
log "github.com/sirupsen/logrus"
)
var byPassMutex sync.RWMutex
@@ -11,10 +15,16 @@ var byPassMutex sync.RWMutex
var bypassPaths = make(map[string]struct{})
// AddBypassPath adds an exact path to the list of paths that bypass middleware.
func AddBypassPath(path string) {
// Paths can include wildcards, such as /api/*. Paths are matched using path.Match.
// Returns an error if the path has invalid pattern.
func AddBypassPath(path string) error {
byPassMutex.Lock()
defer byPassMutex.Unlock()
if err := validatePath(path); err != nil {
return fmt.Errorf("validate: %w", err)
}
bypassPaths[path] = struct{}{}
return nil
}
// RemovePath removes a path from the list of paths that bypass middleware.
@@ -24,16 +34,41 @@ func RemovePath(path string) {
delete(bypassPaths, path)
}
// GetList returns a list of all bypass paths.
func GetList() []string {
byPassMutex.RLock()
defer byPassMutex.RUnlock()
list := make([]string, 0, len(bypassPaths))
for k := range bypassPaths {
list = append(list, k)
}
return list
}
// ShouldBypass checks if the request path is one of the auth bypass paths and returns true if the middleware should be bypassed.
// This can be used to bypass authz/authn middlewares for certain paths, such as webhooks that implement their own authentication.
func ShouldBypass(requestPath string, h http.Handler, w http.ResponseWriter, r *http.Request) bool {
byPassMutex.RLock()
defer byPassMutex.RUnlock()
if _, ok := bypassPaths[requestPath]; ok {
h.ServeHTTP(w, r)
return true
for bypassPath := range bypassPaths {
matched, err := path.Match(bypassPath, requestPath)
if err != nil {
log.Errorf("Error matching path %s with %s from %s: %v", bypassPath, requestPath, GetList(), err)
continue
}
if matched {
h.ServeHTTP(w, r)
return true
}
}
return false
}
func validatePath(p string) error {
_, err := path.Match(p, "")
return err
}