updates and auth on a obj

License: MIT
Signed-off-by: Henrique Dias <hacdias@gmail.com>
This commit is contained in:
Henrique Dias 2018-08-08 11:20:23 +01:00
parent 201838ae59
commit d60c600967
5 changed files with 41 additions and 42 deletions

View File

@ -38,9 +38,8 @@ var (
port int port int
auth struct { auth struct {
method string method string
loginHeader string header string
} }
noAuth bool
allowCommands bool allowCommands bool
allowEdit bool allowEdit bool
allowNew bool allowNew bool
@ -76,9 +75,8 @@ func init() {
flag.StringVar(&recaptchasecret, "recaptcha.secret", "", "ReCaptcha secret") flag.StringVar(&recaptchasecret, "recaptcha.secret", "", "ReCaptcha secret")
// Auth settings // Auth settings
flag.BoolVar(&noAuth, "noAuth", false, "Disables authentication") flag.StringVar(&auth.method, "auth.method", "default", "Switch between 'none', 'default' and 'proxy' authentication")
flag.StringVar(&auth.method, "auth.method", "default", "Switch between 'none', 'default' and 'proxy' authentication.") flag.StringVar(&auth.header, "auth.header", "X-Forwarded-User", "The header name used for proxy authentication")
flag.StringVar(&auth.loginHeader, "auth.loginHeader", "X-Forwarded-User", "The header name used for proxy authentication.")
} }
func setupViper() { func setupViper() {
@ -89,7 +87,6 @@ func setupViper() {
viper.SetDefault("BaseURL", "") viper.SetDefault("BaseURL", "")
viper.SetDefault("PrefixURL", "") viper.SetDefault("PrefixURL", "")
viper.SetDefault("StaticGen", "") viper.SetDefault("StaticGen", "")
viper.SetDefault("NoAuth", false)
viper.BindPFlag("Port", flag.Lookup("port")) viper.BindPFlag("Port", flag.Lookup("port"))
viper.BindPFlag("Address", flag.Lookup("address")) viper.BindPFlag("Address", flag.Lookup("address"))
@ -98,7 +95,6 @@ func setupViper() {
viper.BindPFlag("BaseURL", flag.Lookup("baseurl")) viper.BindPFlag("BaseURL", flag.Lookup("baseurl"))
viper.BindPFlag("PrefixURL", flag.Lookup("prefixurl")) viper.BindPFlag("PrefixURL", flag.Lookup("prefixurl"))
viper.BindPFlag("StaticGen", flag.Lookup("staticgen")) viper.BindPFlag("StaticGen", flag.Lookup("staticgen"))
viper.BindPFlag("NoAuth", flag.Lookup("no-auth"))
// User default values // User default values
viper.SetDefault("Defaults.Scope", ".") viper.SetDefault("Defaults.Scope", ".")
@ -129,11 +125,11 @@ func setupViper() {
viper.BindPFlag("Recaptcha.Secret", flag.Lookup("recaptcha.secret")) viper.BindPFlag("Recaptcha.Secret", flag.Lookup("recaptcha.secret"))
// Auth settings // Auth settings
viper.SetDefault("AuthMethod", "default") viper.SetDefault("Auth.Method", "default")
viper.SetDefault("LoginHeader", "X-Fowarded-User") viper.SetDefault("Auth.Header", "X-Fowarded-User")
viper.BindPFlag("AuthMethod", flag.Lookup("auth.method")) viper.BindPFlag("Auth.Method", flag.Lookup("auth.method"))
viper.BindPFlag("LoginHeader", flag.Lookup("auth.loginHeader")) viper.BindPFlag("Auth.Header", flag.Lookup("auth.header"))
viper.SetConfigName("filebrowser") viper.SetConfigName("filebrowser")
viper.AddConfigPath(".") viper.AddConfigPath(".")
@ -192,13 +188,13 @@ func main() {
} }
// Validate the provided config before moving forward // Validate the provided config before moving forward
if viper.GetString("AuthMethod") != "none" && viper.GetString("AuthMethod") != "default" && viper.GetString("AuthMethod") != "proxy" { if viper.GetString("Auth.Method") != "none" && viper.GetString("Auth.Method") != "default" && viper.GetString("Auth.Method") != "proxy" {
log.Fatal("The property 'auth.method' needs to be set to 'default' or 'proxy'.") log.Fatal("The property 'auth.method' needs to be set to 'default' or 'proxy'.")
} }
if viper.GetString("AuthMethod") == "proxy" { if viper.GetString("Auth.Method") == "proxy" {
if viper.GetString("LoginHeader") == "" { if viper.GetString("Auth.Header") == "" {
log.Fatal("The 'loginHeader' needs to be specified when 'proxy' authentication is used.") log.Fatal("The 'auth.header' needs to be specified when 'proxy' authentication is used.")
} }
log.Println("[WARN] Filebrowser authentication is configured to 'proxy' authentication. This can cause a huge security issue if the infrastructure is not configured correctly.") log.Println("[WARN] Filebrowser authentication is configured to 'proxy' authentication. This can cause a huge security issue if the infrastructure is not configured correctly.")
} }
@ -231,11 +227,10 @@ func handler() http.Handler {
} }
fm := &filebrowser.FileBrowser{ fm := &filebrowser.FileBrowser{
AuthMethod: viper.GetString("AuthMethod"), Auth: &filebrowser.Auth{
LoginHeader: viper.GetString("LoginHeader"), Method: viper.GetString("Auth.Method"),
NoAuth: viper.GetBool("NoAuth"), Header: viper.GetString("Auth.Header"),
BaseURL: viper.GetString("BaseURL"), },
PrefixURL: viper.GetString("PrefixURL"),
ReCaptcha: &filebrowser.ReCaptcha{ ReCaptcha: &filebrowser.ReCaptcha{
Host: recaptchaHost, Host: recaptchaHost,
Key: viper.GetString("Recaptcha.Key"), Key: viper.GetString("Recaptcha.Key"),
@ -264,6 +259,9 @@ func handler() http.Handler {
}, },
} }
fm.SetBaseURL(viper.GetString("BaseURL"))
fm.SetPrefixURL(viper.GetString("PrefixURL"))
err = fm.Setup() err = fm.Setup()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)

View File

@ -48,6 +48,18 @@ type ReCaptcha struct {
Secret string Secret string
} }
// Auth settings.
type Auth struct {
// Define if which of the following authentication mechansims should be used:
// - 'default', which requires a user and a password.
// - 'proxy', which requires a valid user and the user name has to be provided through an
// http header.
// - 'none', which allows anyone to access the filebrowser instance.
Method string
// If 'Method' is set to 'proxy' the header configured below is used to identify the user.
Header string
}
// FileBrowser is a file manager instance. It should be creating using the // FileBrowser is a file manager instance. It should be creating using the
// 'New' function and not directly. // 'New' function and not directly.
type FileBrowser struct { type FileBrowser struct {
@ -74,19 +86,8 @@ type FileBrowser struct {
// edited directly. Use SetBaseURL. // edited directly. Use SetBaseURL.
BaseURL string BaseURL string
// NoAuth disables the authentication. When the authentication is disabled, // Authentication configuration.
// there will only exist one user, called "admin". Auth *Auth
NoAuth bool
// Define if which of the following authentication mechansims should be used:
// - 'default', which requires a user and a password.
// - 'proxy', which requires a valid user and the user name has to be provided through an
// http header.
// - 'none', which allows anyone to access the filebrowser instance.
AuthMethod string
// When 'AuthMethod' is set to 'proxy' the header configured below is used to identify the user.
LoginHeader string
// ReCaptcha host, key and secret. // ReCaptcha host, key and secret.
ReCaptcha *ReCaptcha ReCaptcha *ReCaptcha

View File

@ -51,14 +51,14 @@ func reCaptcha(host, secret, response string) (bool, error) {
// authHandler processes the authentication for the user. // authHandler processes the authentication for the user.
func authHandler(c *fb.Context, w http.ResponseWriter, r *http.Request) (int, error) { func authHandler(c *fb.Context, w http.ResponseWriter, r *http.Request) (int, error) {
if c.NoAuth { if c.Auth.Method == "none" {
// NoAuth instances shouldn't call this method. // NoAuth instances shouldn't call this method.
return 0, nil return 0, nil
} }
if c.AuthMethod == "proxy" { if c.Auth.Method == "proxy" {
// Receive the Username from the Header and check if it exists. // Receive the Username from the Header and check if it exists.
u, err := c.Store.Users.GetByUsername(r.Header.Get(c.LoginHeader), c.NewFS) u, err := c.Store.Users.GetByUsername(r.Header.Get(c.Auth.Header), c.NewFS)
if err != nil { if err != nil {
return http.StatusForbidden, nil return http.StatusForbidden, nil
} }
@ -178,14 +178,14 @@ func (e extractor) ExtractToken(r *http.Request) (string, error) {
// validateAuth is used to validate the authentication and returns the // validateAuth is used to validate the authentication and returns the
// User if it is valid. // User if it is valid.
func validateAuth(c *fb.Context, r *http.Request) (bool, *fb.User) { func validateAuth(c *fb.Context, r *http.Request) (bool, *fb.User) {
if c.NoAuth { if c.Auth.Method == "none" {
c.User = c.DefaultUser c.User = c.DefaultUser
return true, c.User return true, c.User
} }
// If proxy auth is used do not verify the JWT token if the header is provided. // If proxy auth is used do not verify the JWT token if the header is provided.
if c.AuthMethod == "proxy" { if c.Auth.Method == "proxy" {
u, err := c.Store.Users.GetByUsername(r.Header.Get(c.LoginHeader), c.NewFS) u, err := c.Store.Users.GetByUsername(r.Header.Get(c.Auth.Header), c.NewFS)
if err != nil { if err != nil {
return false, nil return false, nil
} }

View File

@ -228,7 +228,7 @@ func renderFile(c *fb.Context, w http.ResponseWriter, file string) (int, error)
data := map[string]interface{}{ data := map[string]interface{}{
"BaseURL": c.RootURL(), "BaseURL": c.RootURL(),
"NoAuth": c.NoAuth, "NoAuth": c.Auth.Method == "none",
"Version": fb.Version, "Version": fb.Version,
"CSS": template.CSS(c.CSS), "CSS": template.CSS(c.CSS),
"ReCaptcha": c.ReCaptcha.Key != "" && c.ReCaptcha.Secret != "", "ReCaptcha": c.ReCaptcha.Key != "" && c.ReCaptcha.Secret != "",

View File

@ -276,7 +276,7 @@ func usersPutHandler(c *fb.Context, w http.ResponseWriter, r *http.Request) (int
// If we're updating the default user. Only for NoAuth // If we're updating the default user. Only for NoAuth
// implementations. Used to change the viewMode. // implementations. Used to change the viewMode.
if id == 0 && c.NoAuth { if id == 0 && c.Auth.Method == "none" {
c.DefaultUser.ViewMode = u.ViewMode c.DefaultUser.ViewMode = u.ViewMode
return http.StatusOK, nil return http.StatusOK, nil
} }