forked from TrueCloudLab/rclone
serve http/webdav: add --user --pass authentication #1802
This commit is contained in:
parent
221a8a9c5d
commit
cc9d7156e4
1 changed files with 45 additions and 12 deletions
|
@ -14,13 +14,19 @@ import (
|
||||||
// Globals
|
// Globals
|
||||||
var (
|
var (
|
||||||
bindAddress = "localhost:8080"
|
bindAddress = "localhost:8080"
|
||||||
htPasswdFile string
|
htPasswdFile = ""
|
||||||
|
realm = "rclone"
|
||||||
|
basicUser = ""
|
||||||
|
basicPass = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddFlags adds the http server specific flags
|
// AddFlags adds the http server specific flags
|
||||||
func AddFlags(flagSet *pflag.FlagSet) {
|
func AddFlags(flagSet *pflag.FlagSet) {
|
||||||
flagSet.StringVarP(&bindAddress, "addr", "", bindAddress, "IPaddress:Port to bind server to.")
|
flagSet.StringVarP(&bindAddress, "addr", "", bindAddress, "IPaddress:Port to bind server to.")
|
||||||
flagSet.StringVarP(&htPasswdFile, "htpasswd", "", htPasswdFile, "File to use for htpasswd authentication.")
|
flagSet.StringVarP(&htPasswdFile, "htpasswd", "", htPasswdFile, "File to use for htpasswd authentication.")
|
||||||
|
flagSet.StringVarP(&realm, "realm", "", realm, "Realm name for authentication.")
|
||||||
|
flagSet.StringVarP(&basicUser, "user", "", basicUser, "User name for authentication.")
|
||||||
|
flagSet.StringVarP(&basicPass, "pass", "", basicPass, "Password for authentication.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Help contains text describing the http server to add to the command
|
// Help contains text describing the http server to add to the command
|
||||||
|
@ -32,6 +38,13 @@ Use --addr to specify which IP address and port the server should
|
||||||
listen on, eg --addr 1.2.3.4:8000 or --addr :8080 to listen to all
|
listen on, eg --addr 1.2.3.4:8000 or --addr :8080 to listen to all
|
||||||
IPs. By default it only listens on localhost.
|
IPs. By default it only listens on localhost.
|
||||||
|
|
||||||
|
#### Authentication
|
||||||
|
|
||||||
|
By default this will serve files without needing a login.
|
||||||
|
|
||||||
|
You can either use an htpasswd file which can take lots of users, or
|
||||||
|
set a single username and password with the --user and --pass flags.
|
||||||
|
|
||||||
Use --htpasswd /path/to/htpasswd to provide an htpasswd file. This is
|
Use --htpasswd /path/to/htpasswd to provide an htpasswd file. This is
|
||||||
in standard apache format and supports MD5, SHA1 and BCrypt for basic
|
in standard apache format and supports MD5, SHA1 and BCrypt for basic
|
||||||
authentication. Bcrypt is recommended.
|
authentication. Bcrypt is recommended.
|
||||||
|
@ -41,27 +54,47 @@ To create an htpasswd file:
|
||||||
touch htpasswd
|
touch htpasswd
|
||||||
htpasswd -B htpasswd user
|
htpasswd -B htpasswd user
|
||||||
htpasswd -B htpasswd anotherUser
|
htpasswd -B htpasswd anotherUser
|
||||||
`
|
|
||||||
|
Use --realm to set the authentication realm.`
|
||||||
|
|
||||||
// Server contains info about the running http server
|
// Server contains info about the running http server
|
||||||
type Server struct {
|
type Server struct {
|
||||||
bindAddress string
|
bindAddress string
|
||||||
httpServer *http.Server
|
httpServer *http.Server
|
||||||
|
basicUser string
|
||||||
|
basicPassHashed string
|
||||||
|
}
|
||||||
|
|
||||||
|
// singleUserProvider provides the encrypted password for a single user
|
||||||
|
func (s *Server) singleUserProvider(user, realm string) string {
|
||||||
|
if user == s.basicUser {
|
||||||
|
return s.basicPassHashed
|
||||||
|
}
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewServer creates an http server
|
// NewServer creates an http server
|
||||||
func NewServer(handler http.Handler) *Server {
|
func NewServer(handler http.Handler) *Server {
|
||||||
// Use htpasswd if required on everything
|
|
||||||
if htPasswdFile != "" {
|
|
||||||
fs.Infof(nil, "Using %q as htpasswd storage", htPasswdFile)
|
|
||||||
secretProvider := auth.HtpasswdFileProvider(htPasswdFile)
|
|
||||||
authenticator := auth.NewBasicAuthenticator("rclone", secretProvider)
|
|
||||||
handler = auth.JustCheck(authenticator, handler.ServeHTTP)
|
|
||||||
}
|
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
bindAddress: bindAddress,
|
bindAddress: bindAddress,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use htpasswd if required on everything
|
||||||
|
if htPasswdFile != "" || basicUser != "" {
|
||||||
|
var secretProvider auth.SecretProvider
|
||||||
|
if htPasswdFile != "" {
|
||||||
|
fs.Infof(nil, "Using %q as htpasswd storage", htPasswdFile)
|
||||||
|
secretProvider = auth.HtpasswdFileProvider(htPasswdFile)
|
||||||
|
} else {
|
||||||
|
fs.Infof(nil, "Using --user %s --pass XXXX as authenticated user", basicUser)
|
||||||
|
s.basicUser = basicUser
|
||||||
|
s.basicPassHashed = string(auth.MD5Crypt([]byte(basicPass), []byte("dlPL2MqE"), []byte("$1$")))
|
||||||
|
secretProvider = s.singleUserProvider
|
||||||
|
}
|
||||||
|
authenticator := auth.NewBasicAuthenticator(realm, secretProvider)
|
||||||
|
handler = auth.JustCheck(authenticator, handler.ServeHTTP)
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME make a transport?
|
// FIXME make a transport?
|
||||||
s.httpServer = &http.Server{
|
s.httpServer = &http.Server{
|
||||||
Addr: s.bindAddress,
|
Addr: s.bindAddress,
|
||||||
|
|
Loading…
Reference in a new issue