Переглянути джерело

webdav: add prefix support

Nicola Murino 4 роки тому
батько
коміт
4c658bb6f0
9 змінених файлів з 25 додано та 3 видалено
  1. 2 0
      README.md
  2. 7 0
      config/config.go
  3. 5 0
      config/config_test.go
  4. 1 0
      docs/full-configuration.md
  5. 1 1
      docs/rest-api.md
  6. 3 1
      docs/webdav.md
  7. 2 1
      sftpgo.json
  8. 1 0
      webdavd/server.go
  9. 3 0
      webdavd/webdavd.go

+ 2 - 0
README.md

@@ -165,6 +165,8 @@ After starting SFTPGo you can manage users and folders using:
 
 To support embedded data providers like `bolt` and `SQLite` we can't have a CLI that directly write users and folders to the data provider, we always have to use the REST API.
 
+Full details for users, folders, admins and other resources are documented in the [OpenAPI](/httpd/schema/openapi.yaml) schema. If you want to render the schema without importing it manually, you can explore it on [Stoplight](https://sftpgo.stoplight.io/docs/sftpgo/openapi.yaml).
+
 ## Tutorials
 
 Some step-to-step tutorials can be found inside the source tree [howto](./docs/howto "How-to") directory.

+ 7 - 0
config/config.go

@@ -59,6 +59,7 @@ var (
 		EnableHTTPS:     false,
 		ClientAuthType:  0,
 		TLSCipherSuites: nil,
+		Prefix:          "",
 	}
 	defaultHTTPDBinding = httpd.Binding{
 		Address:         "127.0.0.1",
@@ -675,6 +676,12 @@ func getWebDAVDBindingFromEnv(idx int) {
 		isSet = true
 	}
 
+	prefix, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_WEBDAVD__BINDINGS__%v__PREFIX", idx))
+	if ok {
+		binding.Prefix = prefix
+		isSet = true
+	}
+
 	if isSet {
 		if len(globalConf.WebDAVD.Bindings) > idx {
 			globalConf.WebDAVD.Bindings[idx] = binding

+ 5 - 0
config/config_test.go

@@ -523,6 +523,7 @@ func TestWebDAVBindingsFromEnv(t *testing.T) {
 	os.Setenv("SFTPGO_WEBDAVD__BINDINGS__2__PORT", "9000")
 	os.Setenv("SFTPGO_WEBDAVD__BINDINGS__2__ENABLE_HTTPS", "1")
 	os.Setenv("SFTPGO_WEBDAVD__BINDINGS__2__CLIENT_AUTH_TYPE", "1")
+	os.Setenv("SFTPGO_WEBDAVD__BINDINGS__2__PREFIX", "/dav2")
 	t.Cleanup(func() {
 		os.Unsetenv("SFTPGO_WEBDAVD__BINDINGS__1__ADDRESS")
 		os.Unsetenv("SFTPGO_WEBDAVD__BINDINGS__1__PORT")
@@ -532,6 +533,7 @@ func TestWebDAVBindingsFromEnv(t *testing.T) {
 		os.Unsetenv("SFTPGO_WEBDAVD__BINDINGS__2__PORT")
 		os.Unsetenv("SFTPGO_WEBDAVD__BINDINGS__2__ENABLE_HTTPS")
 		os.Unsetenv("SFTPGO_WEBDAVD__BINDINGS__2__CLIENT_AUTH_TYPE")
+		os.Unsetenv("SFTPGO_WEBDAVD__BINDINGS__2__PREFIX")
 	})
 
 	configDir := ".."
@@ -543,17 +545,20 @@ func TestWebDAVBindingsFromEnv(t *testing.T) {
 	require.Empty(t, bindings[0].Address)
 	require.False(t, bindings[0].EnableHTTPS)
 	require.Len(t, bindings[0].TLSCipherSuites, 0)
+	require.Empty(t, bindings[0].Prefix)
 	require.Equal(t, 8000, bindings[1].Port)
 	require.Equal(t, "127.0.0.1", bindings[1].Address)
 	require.False(t, bindings[1].EnableHTTPS)
 	require.Equal(t, 0, bindings[1].ClientAuthType)
 	require.Len(t, bindings[1].TLSCipherSuites, 1)
 	require.Equal(t, "TLS_RSA_WITH_AES_128_CBC_SHA", bindings[1].TLSCipherSuites[0])
+	require.Empty(t, bindings[1].Prefix)
 	require.Equal(t, 9000, bindings[2].Port)
 	require.Equal(t, "127.0.1.1", bindings[2].Address)
 	require.True(t, bindings[2].EnableHTTPS)
 	require.Equal(t, 1, bindings[2].ClientAuthType)
 	require.Nil(t, bindings[2].TLSCipherSuites)
+	require.Equal(t, "/dav2", bindings[2].Prefix)
 }
 
 func TestHTTPDBindingsFromEnv(t *testing.T) {

+ 1 - 0
docs/full-configuration.md

@@ -134,6 +134,7 @@ The configuration file contains the following sections:
     - `enable_https`, boolean. Set to `true` and provide both a certificate and a key file to enable HTTPS connection for this binding. Default `false`.
     - `client_auth_type`, integer. Set to `1` to require a client certificate and verify it. Set to `2` to request a client certificate during the TLS handshake and verify it if given, in this mode the client is allowed not to send a certificate. At least one certification authority must be defined in order to verify client certificates. If no certification authority is defined, this setting is ignored. Default: 0.
     - `tls_cipher_suites`, list of strings. List of supported cipher suites for TLS version 1.2. If empty, a default list of secure cipher suites is used, with a preference order based on hardware performance. Note that TLS 1.3 ciphersuites are not configurable. The supported ciphersuites names are defined [here](https://github.com/golang/go/blob/master/src/crypto/tls/cipher_suites.go#L52). Any invalid name will be silently ignored. The order matters, the ciphers listed first will be the preferred ones. Default: empty.
+    - `prefix`, string. Prefix for WebDAV resources, if empty WebDAV resources will be available at the `/` URI. If defined it must be an absolute URI, for example `/dav`. Default: "".
   - `bind_port`, integer. Deprecated, please use `bindings`.
   - `bind_address`, string. Deprecated, please use `bindings`.
   - `certificate_file`, string. Certificate for WebDAV over HTTPS. This can be an absolute path or a path relative to the config dir.

+ 1 - 1
docs/rest-api.md

@@ -40,7 +40,7 @@ You can create other administrator and assign them the following permissions:
 
 You can also restrict administrator access based on the source IP address. If you are running SFTPGo behind a reverse proxy you need to allow both the proxy IP address and the real client IP.
 
-The OpenAPI 3 schema for the exposed API can be found inside the source tree: [openapi.yaml](../httpd/schema/openapi.yaml "OpenAPI 3 specs").
+The OpenAPI 3 schema for the exposed API can be found inside the source tree: [openapi.yaml](../httpd/schema/openapi.yaml "OpenAPI 3 specs"). If you want to render the schema without importing it manually, you can explore it on [Stoplight](https://sftpgo.stoplight.io/docs/sftpgo/openapi.yaml).
 
 You can generate your own REST client in your preferred programming language, or even bash scripts, using an OpenAPI generator such as [swagger-codegen](https://github.com/swagger-api/swagger-codegen) or [OpenAPI Generator](https://openapi-generator.tech/).
 

+ 3 - 1
docs/webdav.md

@@ -2,7 +2,7 @@
 
 The `WebDAV` support can be enabled by configuring one or more `bindings` inside the `webdavd` configuration section.
 
-Each user can access their home directory using the path `http/s://<SFTPGo ip>:<WevDAVPORT>/`.
+Each user can access their home directory using the path `http/s://<SFTPGo ip>:<WevDAVPORT>/<prefix>`. By default `prefix` is empty. If you define a prefix it must be an abosulte URI, for example `/dav`.
 
 WebDAV is quite a different protocol than SCP/FTP, there is no session concept, each command is a separate HTTP request and must be authenticated, to improve performance SFTPGo caches authenticated users. This way SFTPGo don't need to do a dataprovider query and a password check for each request.
 
@@ -19,6 +19,8 @@ The MIME types caching configurations allows to set the maximum number of MIME t
 
 WebDAV should work as expected for most use cases but there are some minor issues and some missing features.
 
+If you use WebDAV behind a reverse proxy ensure to preserve the `Host` header or `COPY`/`MOVE` operations will fail. For example for apache you have to set `ProxyPreserveHost On`.
+
 Know issues:
 
 - removing a directory tree on Cloud Storage backends could generate a `not found` error when removing the last (virtual) directory. This happens if the client cycles the directories tree itself and removes files and directories one by one instead of issuing a single remove command

+ 2 - 1
sftpgo.json

@@ -86,7 +86,8 @@
         "address": "",
         "enable_https": false,
         "client_auth_type": 0,
-        "tls_cipher_suites": []
+        "tls_cipher_suites": [],
+        "prefix": ""
       }
     ],
     "certificate_file": "",

+ 1 - 0
webdavd/server.go

@@ -203,6 +203,7 @@ func (s *webDavServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	}
 
 	handler := webdav.Handler{
+		Prefix:     s.binding.Prefix,
 		FileSystem: connection,
 		LockSystem: lockSystem,
 		Logger:     writeLog,

+ 3 - 0
webdavd/webdavd.go

@@ -86,6 +86,9 @@ type Binding struct {
 	// any invalid name will be silently ignored.
 	// The order matters, the ciphers listed first will be the preferred ones.
 	TLSCipherSuites []string `json:"tls_cipher_suites" mapstructure:"tls_cipher_suites"`
+	// Prefix for WebDAV resources, if empty WebDAV resources will be available at the
+	// root ("/") URI. If defined it must be an absolute URI.
+	Prefix string `json:"prefix" mapstructure:"prefix"`
 }
 
 func (b *Binding) isMutualTLSEnabled() bool {