diff --git a/README.md b/README.md index 6447b97..cd9acee 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ http-auth-pass | pass for basic http auth on upload http-auth-htpasswd | htpasswd file path for basic http auth on upload | | HTTP_AUTH_HTPASSWD | ip-whitelist | comma separated list of ips allowed to connect to the service | | IP_WHITELIST | ip-blacklist | comma separated list of ips not allowed to connect to the service | | IP_BLACKLIST | +ip-filterlist-bypass-http-auth | whether http auth for upload request should be bypassed by rule of the ips filter lists | | IP_FILTERLIST_BYPASS_HTTP_AUTH | temp-path | path to temp folder | system temp | TEMP_PATH | web-path | path to static web files (for development or custom front end) | | WEB_PATH | proxy-path | path prefix when service is run behind a proxy | | PROXY_PATH | diff --git a/cmd/cmd.go b/cmd/cmd.go index b7fe149..382747d 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -288,6 +288,11 @@ var globalFlags = []cli.Flag{ Value: "", EnvVar: "IP_BLACKLIST", }, + cli.BoolFlag{ + Name: "ip-filterlist-bypass-http-auth", + Usage: "whether http auth for upload request should be bypassed by rule of the ips filter lists", + EnvVar: "IP_FILTERLIST_BYPASS_HTTP_AUTH", + }, cli.StringFlag{ Name: "cors-domains", Usage: "comma separated list of domains allowed for CORS requests", @@ -450,6 +455,10 @@ func New() *Cmd { options = append(options, server.HTTPAuthHtpasswd(httpAuthHtpasswd)) } + if ipFilterListBypassHTTPAuth := c.Bool("ip-filterlist-bypass-http-auth"); ipFilterListBypassHTTPAuth { + options = append(options, server.HTTPAuthBypassedByIPFilterList(ipFilterListBypassHTTPAuth)) + } + applyIPFilter := false ipFilterOptions := server.IPFilterOptions{} if ipWhitelist := c.String("ip-whitelist"); ipWhitelist != "" { diff --git a/flake.nix b/flake.nix index 94dca5c..d6074e7 100644 --- a/flake.nix +++ b/flake.nix @@ -47,6 +47,7 @@ http-auth-htpasswd = mkOption { type = types.nullOr types.str; description = "htpasswd file path for basic http auth on upload"; }; ip-whitelist = mkOption { type = types.nullOr types.str; description = "comma separated list of ips allowed to connect to the service"; }; ip-blacklist = mkOption { type = types.nullOr types.str; description = "comma separated list of ips not allowed to connect to the service"; }; + ip-filterlist-bypass-http-auth = mkOption { type = types.nullOr types.bool; description = "whether http auth for upload request should be bypassed by rule of the ips filter lists"; }; temp-path = mkOption { type = types.nullOr types.str; description = "path to temp folder"; }; web-path = mkOption { type = types.nullOr types.str; description = "path to static web files (for development or custom front end)"; }; proxy-path = mkOption { type = types.nullOr types.str; description = "path prefix when service is run behind a proxy"; }; diff --git a/server/handlers.go b/server/handlers.go index 119fb0d..9d50f0d 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -1313,20 +1313,20 @@ func ipFilterHandler(h http.Handler, ipFilterOptions *IPFilterOptions) http.Hand if ipFilterOptions == nil { h.ServeHTTP(w, r) } else { - WrapIPFilter(h, *ipFilterOptions).ServeHTTP(w, r) + WrapIPFilter(h, ipFilterOptions).ServeHTTP(w, r) } } } func (s *Server) basicAuthHandler(h http.Handler) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - if s.AuthUser == "" || s.AuthPass == "" || s.AuthHtpasswd == "" { + if s.authUser == "" || s.authPass == "" || s.authHtpasswd == "" { h.ServeHTTP(w, r) return } - if s.htpasswdFile == nil && s.AuthHtpasswd != "" { - htpasswdFile, err := htpasswd.New(s.AuthHtpasswd, htpasswd.DefaultSystems, nil) + if s.htpasswdFile == nil && s.authHtpasswd != "" { + htpasswdFile, err := htpasswd.New(s.authHtpasswd, htpasswd.DefaultSystems, nil) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return @@ -1344,11 +1344,16 @@ func (s *Server) basicAuthHandler(h http.Handler) http.HandlerFunc { } var authorized bool - if username == s.AuthUser && password == s.AuthPass { + // if we entered the basicHandler we already pass by the ip filter + if s.ipFilterlistBypassHTTPAuth { authorized = true } - if s.htpasswdFile != nil && !authorized { + if !authorized && username == s.authUser && password == s.authPass { + authorized = true + } + + if !authorized && s.htpasswdFile != nil { authorized = s.htpasswdFile.Match(username, password) } diff --git a/server/ip_filter.go b/server/ip_filter.go index 1dacf33..cde43cc 100644 --- a/server/ip_filter.go +++ b/server/ip_filter.go @@ -45,7 +45,6 @@ type IPFilterOptions struct { // ipFilter type ipFilter struct { - opts IPFilterOptions //mut protects the below //rw since writes are rare mut sync.RWMutex @@ -60,13 +59,12 @@ type subnet struct { allowed bool } -func newIPFilter(opts IPFilterOptions) *ipFilter { +func newIPFilter(opts *IPFilterOptions) *ipFilter { if opts.Logger == nil { flags := log.LstdFlags opts.Logger = log.New(os.Stdout, "", flags) } f := &ipFilter{ - opts: opts, ips: map[string]bool{}, defaultAllowed: !opts.BlockByDefault, } @@ -189,7 +187,7 @@ func (f *ipFilter) Wrap(next http.Handler) http.Handler { } // WrapIPFilter is equivalent to newIPFilter(opts) then Wrap(next) -func WrapIPFilter(next http.Handler, opts IPFilterOptions) http.Handler { +func WrapIPFilter(next http.Handler, opts *IPFilterOptions) http.Handler { return newIPFilter(opts).Wrap(next) } diff --git a/server/server.go b/server/server.go index 62e4ab6..e0baa9f 100644 --- a/server/server.go +++ b/server/server.go @@ -295,15 +295,22 @@ func TLSConfig(cert, pk string) OptionFn { // HTTPAuthCredentials sets basic http auth credentials func HTTPAuthCredentials(user string, pass string) OptionFn { return func(srvr *Server) { - srvr.AuthUser = user - srvr.AuthPass = pass + srvr.authUser = user + srvr.authPass = pass } } // HTTPAuthHtpasswd sets basic http auth htpasswd file func HTTPAuthHtpasswd(htpasswdPath string) OptionFn { return func(srvr *Server) { - srvr.AuthHtpasswd = htpasswdPath + srvr.authHtpasswd = htpasswdPath + } +} + +// HTTPAuthBypassedByIPFilterList sets basic http auth htpasswd file +func HTTPAuthBypassedByIPFilterList(ipFilterListBypassHTTPAuth bool) OptionFn { + return func(srvr *Server) { + srvr.ipFilterlistBypassHTTPAuth = ipFilterListBypassHTTPAuth } } @@ -324,9 +331,11 @@ func FilterOptions(options IPFilterOptions) OptionFn { // Server is the main application type Server struct { - AuthUser string - AuthPass string - AuthHtpasswd string + authUser string + authPass string + authHtpasswd string + + ipFilterlistBypassHTTPAuth bool htpasswdFile *htpasswd.File