portable mode: add WebClient

Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
Nicola Murino
2023-08-10 19:02:55 +02:00
parent 25450d9efc
commit 6c482a248d
7 changed files with 153 additions and 57 deletions

View File

@@ -27,6 +27,7 @@ import (
"github.com/drakkan/sftpgo/v2/internal/config"
"github.com/drakkan/sftpgo/v2/internal/dataprovider"
"github.com/drakkan/sftpgo/v2/internal/ftpd"
"github.com/drakkan/sftpgo/v2/internal/httpd"
"github.com/drakkan/sftpgo/v2/internal/kms"
"github.com/drakkan/sftpgo/v2/internal/logger"
"github.com/drakkan/sftpgo/v2/internal/sftpd"
@@ -36,8 +37,8 @@ import (
)
// StartPortableMode starts the service in portable mode
func (s *Service) StartPortableMode(sftpdPort, ftpPort, webdavPort int, enabledSSHCommands []string,
ftpsCert, ftpsKey, webDavCert, webDavKey string) error {
func (s *Service) StartPortableMode(sftpdPort, ftpPort, webdavPort, httpPort int, enabledSSHCommands []string,
ftpsCert, ftpsKey, webDavCert, webDavKey, httpsCert, httpsKey string) error {
if s.PortableMode != 1 {
return fmt.Errorf("service is not configured for portable mode")
}
@@ -56,71 +57,50 @@ func (s *Service) StartPortableMode(sftpdPort, ftpPort, webdavPort int, enabledS
dataProviderConf.Name = ""
config.SetProviderConf(dataProviderConf)
httpdConf := config.GetHTTPDConfig()
httpdConf.Bindings = nil
for idx := range httpdConf.Bindings {
httpdConf.Bindings[idx].Port = 0
}
config.SetHTTPDConfig(httpdConf)
telemetryConf := config.GetTelemetryConfig()
telemetryConf.BindPort = 0
config.SetTelemetryConfig(telemetryConf)
sftpdConf := config.GetSFTPDConfig()
sftpdConf.MaxAuthTries = 12
sftpdConf.Bindings = []sftpd.Binding{
{
Port: sftpdPort,
},
}
if sftpdPort >= 0 {
if sftpdPort > 0 {
sftpdConf.Bindings[0].Port = sftpdPort
} else {
// dynamic ports starts from 49152
sftpdConf.Bindings[0].Port = 49152 + rand.Intn(15000)
}
if util.Contains(enabledSSHCommands, "*") {
sftpdConf.EnabledSSHCommands = sftpd.GetSupportedSSHCommands()
} else {
sftpdConf.EnabledSSHCommands = enabledSSHCommands
}
configurePortableSFTPService(sftpdPort, enabledSSHCommands)
}
config.SetSFTPDConfig(sftpdConf)
if ftpPort >= 0 {
ftpConf := config.GetFTPDConfig()
binding := ftpd.Binding{}
if ftpPort > 0 {
binding.Port = ftpPort
} else {
binding.Port = 49152 + rand.Intn(15000)
}
ftpConf.Bindings = []ftpd.Binding{binding}
ftpConf.Banner = fmt.Sprintf("SFTPGo portable %v ready", version.Get().Version)
ftpConf.CertificateFile = ftpsCert
ftpConf.CertificateKeyFile = ftpsKey
config.SetFTPDConfig(ftpConf)
configurePortableFTPService(ftpPort, ftpsCert, ftpsKey)
}
if webdavPort >= 0 {
webDavConf := config.GetWebDAVDConfig()
binding := webdavd.Binding{}
if webdavPort > 0 {
binding.Port = webdavPort
} else {
binding.Port = 49152 + rand.Intn(15000)
}
webDavConf.Bindings = []webdavd.Binding{binding}
webDavConf.CertificateFile = webDavCert
webDavConf.CertificateKeyFile = webDavKey
config.SetWebDAVDConfig(webDavConf)
configurePortableWebDAVService(webdavPort, webDavCert, webDavKey)
}
if httpPort >= 0 {
configurePortableHTTPService(httpPort, httpsCert, httpsKey)
}
err = s.Start(true)
if err != nil {
return err
}
if httpPort >= 0 {
admin := &dataprovider.Admin{
Username: util.GenerateUniqueID(),
Password: util.GenerateUniqueID(),
Status: 0,
Permissions: []string{dataprovider.PermAdminAny},
}
if err := dataprovider.AddAdmin(admin, dataprovider.ActionExecutorSystem, "", ""); err != nil {
return err
}
}
logger.InfoToConsole("Portable mode ready, user: %q, password: %q, public keys: %v, directory: %q, "+
"permissions: %+v, enabled ssh commands: %v file patterns filters: %+v %v", s.PortableUser.Username,
"permissions: %+v, file patterns filters: %+v %v", s.PortableUser.Username,
printablePassword, s.PortableUser.PublicKeys, s.getPortableDirToServe(), s.PortableUser.Permissions,
sftpdConf.EnabledSSHCommands, s.PortableUser.Filters.FilePatterns, s.getServiceOptionalInfoString())
s.PortableUser.Filters.FilePatterns, s.getServiceOptionalInfoString())
return nil
}
@@ -137,7 +117,14 @@ func (s *Service) getServiceOptionalInfoString() string {
if config.GetWebDAVDConfig().CertificateFile != "" && config.GetWebDAVDConfig().CertificateKeyFile != "" {
scheme = "https"
}
info.WriteString(fmt.Sprintf("WebDAV URL: %v://<your IP>:%v/", scheme, config.GetWebDAVDConfig().Bindings[0].Port))
info.WriteString(fmt.Sprintf("WebDAV URL: %v://<your IP>:%v/ ", scheme, config.GetWebDAVDConfig().Bindings[0].Port))
}
if config.GetHTTPDConfig().Bindings[0].IsValid() {
scheme := "http"
if config.GetHTTPDConfig().CertificateFile != "" && config.GetHTTPDConfig().CertificateKeyFile != "" {
scheme = "https"
}
info.WriteString(fmt.Sprintf("WebClient URL: %v://<your IP>:%v/ ", scheme, config.GetHTTPDConfig().Bindings[0].Port))
}
return info.String()
}
@@ -170,12 +157,16 @@ func (s *Service) configurePortableUser() string {
}
if len(s.PortableUser.PublicKeys) == 0 && s.PortableUser.Password == "" {
var b strings.Builder
for i := 0; i < 8; i++ {
for i := 0; i < 16; i++ {
b.WriteRune(chars[rand.Intn(len(chars))])
}
s.PortableUser.Password = b.String()
printablePassword = s.PortableUser.Password
}
s.PortableUser.Filters.WebClient = []string{sdk.WebClientSharesDisabled, sdk.WebClientInfoChangeDisabled,
sdk.WebClientPubKeyChangeDisabled, sdk.WebClientPasswordChangeDisabled, sdk.WebClientAPIKeyAuthChangeDisabled,
sdk.WebClientMFADisabled,
}
s.configurePortableSecrets()
return printablePassword
}
@@ -218,3 +209,76 @@ func getSecretFromString(payload string) *kms.Secret {
}
return kms.NewEmptySecret()
}
func configurePortableSFTPService(port int, enabledSSHCommands []string) {
sftpdConf := config.GetSFTPDConfig()
if len(sftpdConf.Bindings) == 0 {
sftpdConf.Bindings = append(sftpdConf.Bindings, sftpd.Binding{})
}
if port > 0 {
sftpdConf.Bindings[0].Port = port
} else {
// dynamic ports starts from 49152
sftpdConf.Bindings[0].Port = 49152 + rand.Intn(15000)
}
if util.Contains(enabledSSHCommands, "*") {
sftpdConf.EnabledSSHCommands = sftpd.GetSupportedSSHCommands()
} else {
sftpdConf.EnabledSSHCommands = enabledSSHCommands
}
config.SetSFTPDConfig(sftpdConf)
}
func configurePortableFTPService(port int, cert, key string) {
ftpConf := config.GetFTPDConfig()
if len(ftpConf.Bindings) == 0 {
ftpConf.Bindings = append(ftpConf.Bindings, ftpd.Binding{})
}
if port > 0 {
ftpConf.Bindings[0].Port = port
} else {
ftpConf.Bindings[0].Port = 49152 + rand.Intn(15000)
}
if ftpConf.Banner == "" {
ftpConf.Banner = fmt.Sprintf("SFTPGo portable %v ready", version.Get().Version)
}
ftpConf.Bindings[0].CertificateFile = cert
ftpConf.Bindings[0].CertificateKeyFile = key
config.SetFTPDConfig(ftpConf)
}
func configurePortableWebDAVService(port int, cert, key string) {
webDavConf := config.GetWebDAVDConfig()
if len(webDavConf.Bindings) == 0 {
webDavConf.Bindings = append(webDavConf.Bindings, webdavd.Binding{})
}
if port > 0 {
webDavConf.Bindings[0].Port = port
} else {
webDavConf.Bindings[0].Port = 49152 + rand.Intn(15000)
}
webDavConf.Bindings[0].CertificateFile = cert
webDavConf.Bindings[0].CertificateKeyFile = key
webDavConf.Bindings[0].EnableHTTPS = true
config.SetWebDAVDConfig(webDavConf)
}
func configurePortableHTTPService(port int, cert, key string) {
httpdConf := config.GetHTTPDConfig()
if len(httpdConf.Bindings) == 0 {
httpdConf.Bindings = append(httpdConf.Bindings, httpd.Binding{})
}
if port > 0 {
httpdConf.Bindings[0].Port = port
} else {
httpdConf.Bindings[0].Port = 49152 + rand.Intn(15000)
}
httpdConf.Bindings[0].CertificateFile = cert
httpdConf.Bindings[0].CertificateKeyFile = key
httpdConf.Bindings[0].EnableHTTPS = true
httpdConf.Bindings[0].EnableWebAdmin = false
httpdConf.Bindings[0].EnableWebClient = true
httpdConf.Bindings[0].EnableRESTAPI = false
httpdConf.Bindings[0].RenderOpenAPI = false
config.SetHTTPDConfig(httpdConf)
}