mirror of
https://github.com/drakkan/sftpgo.git
synced 2024-11-22 07:30:25 +00:00
portable mode: add WebDAV support
This commit is contained in:
parent
f3228713bc
commit
bbc8c091e6
5 changed files with 62 additions and 9 deletions
|
@ -53,6 +53,9 @@ var (
|
||||||
portableFTPDPort int
|
portableFTPDPort int
|
||||||
portableFTPSCert string
|
portableFTPSCert string
|
||||||
portableFTPSKey string
|
portableFTPSKey string
|
||||||
|
portableWebDAVPort int
|
||||||
|
portableWebDAVCert string
|
||||||
|
portableWebDAVKey string
|
||||||
portableCmd = &cobra.Command{
|
portableCmd = &cobra.Command{
|
||||||
Use: "portable",
|
Use: "portable",
|
||||||
Short: "Serve a single directory",
|
Short: "Serve a single directory",
|
||||||
|
@ -100,6 +103,14 @@ Please take a look at the usage below to customize the serving parameters`,
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if portableWebDAVPort > 0 && len(portableWebDAVCert) > 0 && len(portableWebDAVKey) > 0 {
|
||||||
|
_, err := common.NewCertManager(portableWebDAVCert, portableWebDAVKey, "WebDAV portable")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Unable to load WebDAV key pair, cert file %#v key file %#v error: %v\n",
|
||||||
|
portableWebDAVCert, portableWebDAVKey, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
service := service.Service{
|
service := service.Service{
|
||||||
ConfigDir: filepath.Clean(defaultConfigDir),
|
ConfigDir: filepath.Clean(defaultConfigDir),
|
||||||
ConfigFile: defaultConfigName,
|
ConfigFile: defaultConfigName,
|
||||||
|
@ -145,8 +156,8 @@ Please take a look at the usage below to customize the serving parameters`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if err := service.StartPortableMode(portableSFTPDPort, portableFTPDPort, portableSSHCommands, portableAdvertiseService,
|
if err := service.StartPortableMode(portableSFTPDPort, portableFTPDPort, portableWebDAVPort, portableSSHCommands, portableAdvertiseService,
|
||||||
portableAdvertiseCredentials, portableFTPSCert, portableFTPSKey); err == nil {
|
portableAdvertiseCredentials, portableFTPSCert, portableFTPSKey, portableWebDAVCert, portableWebDAVKey); err == nil {
|
||||||
service.Wait()
|
service.Wait()
|
||||||
if service.Error == nil {
|
if service.Error == nil {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
@ -166,6 +177,8 @@ relative to the current directory
|
||||||
`)
|
`)
|
||||||
portableCmd.Flags().IntVarP(&portableSFTPDPort, "sftpd-port", "s", 0, "0 means a random unprivileged port")
|
portableCmd.Flags().IntVarP(&portableSFTPDPort, "sftpd-port", "s", 0, "0 means a random unprivileged port")
|
||||||
portableCmd.Flags().IntVar(&portableFTPDPort, "ftpd-port", -1, `0 means a random unprivileged port,
|
portableCmd.Flags().IntVar(&portableFTPDPort, "ftpd-port", -1, `0 means a random unprivileged port,
|
||||||
|
< 0 disabled`)
|
||||||
|
portableCmd.Flags().IntVar(&portableWebDAVPort, "webdav-port", -1, `0 means a random unprivileged port,
|
||||||
< 0 disabled`)
|
< 0 disabled`)
|
||||||
portableCmd.Flags().StringSliceVarP(&portableSSHCommands, "ssh-commands", "c", sftpd.GetDefaultSSHCommands(),
|
portableCmd.Flags().StringSliceVarP(&portableSSHCommands, "ssh-commands", "c", sftpd.GetDefaultSSHCommands(),
|
||||||
`SSH commands to enable.
|
`SSH commands to enable.
|
||||||
|
@ -228,6 +241,10 @@ a JSON credentials file, 1 automatic
|
||||||
`)
|
`)
|
||||||
portableCmd.Flags().StringVar(&portableFTPSCert, "ftpd-cert", "", "Path to the certificate file for FTPS")
|
portableCmd.Flags().StringVar(&portableFTPSCert, "ftpd-cert", "", "Path to the certificate file for FTPS")
|
||||||
portableCmd.Flags().StringVar(&portableFTPSKey, "ftpd-key", "", "Path to the key file for FTPS")
|
portableCmd.Flags().StringVar(&portableFTPSKey, "ftpd-key", "", "Path to the key file for FTPS")
|
||||||
|
portableCmd.Flags().StringVar(&portableWebDAVCert, "webdav-cert", "", `Path to the certificate file for WebDAV
|
||||||
|
over HTTPS`)
|
||||||
|
portableCmd.Flags().StringVar(&portableWebDAVKey, "webdav-key", "", `Path to the key file for WebDAV over
|
||||||
|
HTTPS`)
|
||||||
rootCmd.AddCommand(portableCmd)
|
rootCmd.AddCommand(portableCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,12 @@ Flags:
|
||||||
(default [md5sum,sha1sum,cd,pwd,scp])
|
(default [md5sum,sha1sum,cd,pwd,scp])
|
||||||
-u, --username string Leave empty to use an auto generated
|
-u, --username string Leave empty to use an auto generated
|
||||||
value
|
value
|
||||||
|
--webdav-cert string Path to the certificate file for WebDAV
|
||||||
|
over HTTPS
|
||||||
|
--webdav-key string Path to the key file for WebDAV over
|
||||||
|
HTTPS
|
||||||
|
--webdav-port int 0 means a random unprivileged port,
|
||||||
|
< 0 disabled (default -1)
|
||||||
```
|
```
|
||||||
|
|
||||||
In portable mode, SFTPGo can advertise the SFTP/FTP services and, optionally, the credentials via multicast DNS, so there is a standard way to discover the service and to automatically connect to it.
|
In portable mode, SFTPGo can advertise the SFTP/FTP services and, optionally, the credentials via multicast DNS, so there is a standard way to discover the service and to automatically connect to it.
|
||||||
|
|
|
@ -355,8 +355,10 @@ func TestAddUserInvalidFilters(t *testing.T) {
|
||||||
u.Filters.FileExtensions = nil
|
u.Filters.FileExtensions = nil
|
||||||
u.Filters.DeniedProtocols = []string{"invalid"}
|
u.Filters.DeniedProtocols = []string{"invalid"}
|
||||||
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
||||||
|
assert.NoError(t, err)
|
||||||
u.Filters.DeniedProtocols = dataprovider.ValidProtocols
|
u.Filters.DeniedProtocols = dataprovider.ValidProtocols
|
||||||
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
||||||
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddUserInvalidFsConfig(t *testing.T) {
|
func TestAddUserInvalidFsConfig(t *testing.T) {
|
||||||
|
|
|
@ -23,8 +23,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// StartPortableMode starts the service in portable mode
|
// StartPortableMode starts the service in portable mode
|
||||||
func (s *Service) StartPortableMode(sftpdPort, ftpPort int, enabledSSHCommands []string, advertiseService, advertiseCredentials bool,
|
func (s *Service) StartPortableMode(sftpdPort, ftpPort, webdavPort int, enabledSSHCommands []string, advertiseService, advertiseCredentials bool,
|
||||||
ftpsCert, ftpsKey string) error {
|
ftpsCert, ftpsKey, webDavCert, webDavKey string) error {
|
||||||
if s.PortableMode != 1 {
|
if s.PortableMode != 1 {
|
||||||
return fmt.Errorf("service is not configured for portable mode")
|
return fmt.Errorf("service is not configured for portable mode")
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,18 @@ func (s *Service) StartPortableMode(sftpdPort, ftpPort int, enabledSSHCommands [
|
||||||
config.SetFTPDConfig(ftpConf)
|
config.SetFTPDConfig(ftpConf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if webdavPort > 0 {
|
||||||
|
webDavConf := config.GetWebDAVDConfig()
|
||||||
|
if webdavPort > 0 {
|
||||||
|
webDavConf.BindPort = webdavPort
|
||||||
|
} else {
|
||||||
|
webDavConf.BindPort = 49152 + rand.Intn(15000)
|
||||||
|
}
|
||||||
|
webDavConf.CertificateFile = webDavCert
|
||||||
|
webDavConf.CertificateKeyFile = webDavKey
|
||||||
|
config.SetWebDAVDConfig(webDavConf)
|
||||||
|
}
|
||||||
|
|
||||||
err = s.Start()
|
err = s.Start()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -88,17 +100,32 @@ func (s *Service) StartPortableMode(sftpdPort, ftpPort int, enabledSSHCommands [
|
||||||
|
|
||||||
s.advertiseServices(advertiseService, advertiseCredentials)
|
s.advertiseServices(advertiseService, advertiseCredentials)
|
||||||
|
|
||||||
var ftpInfo string
|
|
||||||
if config.GetFTPDConfig().BindPort > 0 {
|
|
||||||
ftpInfo = fmt.Sprintf("FTP port: %v", config.GetFTPDConfig().BindPort)
|
|
||||||
}
|
|
||||||
logger.InfoToConsole("Portable mode ready, SFTP port: %v, user: %#v, password: %#v, public keys: %v, directory: %#v, "+
|
logger.InfoToConsole("Portable mode ready, SFTP port: %v, user: %#v, password: %#v, public keys: %v, directory: %#v, "+
|
||||||
"permissions: %+v, enabled ssh commands: %v file extensions filters: %+v %v", sftpdConf.BindPort, s.PortableUser.Username,
|
"permissions: %+v, enabled ssh commands: %v file extensions filters: %+v %v", sftpdConf.BindPort, s.PortableUser.Username,
|
||||||
printablePassword, s.PortableUser.PublicKeys, s.getPortableDirToServe(), s.PortableUser.Permissions,
|
printablePassword, s.PortableUser.PublicKeys, s.getPortableDirToServe(), s.PortableUser.Permissions,
|
||||||
sftpdConf.EnabledSSHCommands, s.PortableUser.Filters.FileExtensions, ftpInfo)
|
sftpdConf.EnabledSSHCommands, s.PortableUser.Filters.FileExtensions, s.getServiceOptionalInfoString())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) getServiceOptionalInfoString() string {
|
||||||
|
var info strings.Builder
|
||||||
|
if config.GetFTPDConfig().BindPort > 0 {
|
||||||
|
info.WriteString(fmt.Sprintf("FTP port: %v ", config.GetFTPDConfig().BindPort))
|
||||||
|
}
|
||||||
|
if config.GetWebDAVDConfig().BindPort > 0 {
|
||||||
|
if info.Len() == 0 {
|
||||||
|
info.WriteString(" ")
|
||||||
|
}
|
||||||
|
scheme := "http"
|
||||||
|
if len(config.GetWebDAVDConfig().CertificateFile) > 0 && len(config.GetWebDAVDConfig().CertificateKeyFile) > 0 {
|
||||||
|
scheme = "https"
|
||||||
|
}
|
||||||
|
info.WriteString(fmt.Sprintf("WebDAV URL: %v://<your IP>:%v/%v",
|
||||||
|
scheme, config.GetWebDAVDConfig().BindPort, s.PortableUser.Username))
|
||||||
|
}
|
||||||
|
return info.String()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) advertiseServices(advertiseService, advertiseCredentials bool) {
|
func (s *Service) advertiseServices(advertiseService, advertiseCredentials bool) {
|
||||||
var mDNSServiceSFTP *zeroconf.Server
|
var mDNSServiceSFTP *zeroconf.Server
|
||||||
var mDNSServiceFTP *zeroconf.Server
|
var mDNSServiceFTP *zeroconf.Server
|
||||||
|
|
|
@ -576,6 +576,7 @@ func TestDeniedProtocols(t *testing.T) {
|
||||||
|
|
||||||
user.Filters.DeniedProtocols = []string{common.ProtocolSSH, common.ProtocolFTP}
|
user.Filters.DeniedProtocols = []string{common.ProtocolSSH, common.ProtocolFTP}
|
||||||
user, _, err = httpd.UpdateUser(user, http.StatusOK)
|
user, _, err = httpd.UpdateUser(user, http.StatusOK)
|
||||||
|
assert.NoError(t, err)
|
||||||
client = getWebDavClient(user)
|
client = getWebDavClient(user)
|
||||||
assert.NoError(t, checkBasicFunc(client))
|
assert.NoError(t, checkBasicFunc(client))
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue