mirror of
https://github.com/rclone/rclone.git
synced 2024-11-21 23:29:57 +08:00
lib/http: disable automatic authentication skipping for unix sockets
Disabling the authentication for unix sockets makes it impossible to use `rclone serve` behind a proxy that that communicates with rclone via a unix socket. Re-enabling the authentication should not have any effect on most users of unix sockets as they do not set authentication up with a unix socket anyway.
This commit is contained in:
parent
175aa07cdd
commit
29fd894189
|
@ -36,12 +36,6 @@ func IsAuthenticated(r *http.Request) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// IsUnixSocket checks if the request was received on a unix socket, used to skip auth & CORS
|
||||
func IsUnixSocket(r *http.Request) bool {
|
||||
v, _ := r.Context().Value(ctxKeyUnixSock).(bool)
|
||||
return v
|
||||
}
|
||||
|
||||
// PublicURL returns the URL defined in NewBaseContext, used for logging & CORS
|
||||
func PublicURL(r *http.Request) string {
|
||||
v, _ := r.Context().Value(ctxKeyPublicURL).(string)
|
||||
|
|
|
@ -57,11 +57,6 @@ func NewLoggedBasicAuthenticator(realm string, secrets goauth.SecretProvider) *L
|
|||
func basicAuth(authenticator *LoggedBasicAuth) func(next http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// skip auth for unix socket
|
||||
if IsUnixSocket(r) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
// skip auth for CORS preflight
|
||||
if r.Method == "OPTIONS" {
|
||||
next.ServeHTTP(w, r)
|
||||
|
@ -123,11 +118,6 @@ func MiddlewareAuthBasic(user, pass, realm, salt string) Middleware {
|
|||
func MiddlewareAuthCustom(fn CustomAuthFn, realm string, userFromContext bool) Middleware {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// skip auth for unix socket
|
||||
if IsUnixSocket(r) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
// skip auth for CORS preflight
|
||||
if r.Method == "OPTIONS" {
|
||||
next.ServeHTTP(w, r)
|
||||
|
@ -175,11 +165,6 @@ func MiddlewareCORS(allowOrigin string) Middleware {
|
|||
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// skip cors for unix sockets
|
||||
if IsUnixSocket(r) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
if allowOrigin != "" {
|
||||
w.Header().Add("Access-Control-Allow-Origin", allowOrigin)
|
||||
|
|
|
@ -39,8 +39,7 @@ If you set ` + "`--{{ .Prefix }}addr`" + ` to listen on a public or LAN accessib
|
|||
then using Authentication is advised - see the next section for info.
|
||||
|
||||
You can use a unix socket by setting the url to ` + "`unix:///path/to/socket`" + `
|
||||
or just by using an absolute path name. Note that unix sockets bypass the
|
||||
authentication - this is expected to be done with file system permissions.
|
||||
or just by using an absolute path name.
|
||||
|
||||
` + "`--{{ .Prefix }}addr`" + ` may be repeated to listen on multiple IPs/ports/sockets.
|
||||
Socket activation, described further below, can also be used to accomplish the same.
|
||||
|
|
|
@ -3,6 +3,7 @@ package http
|
|||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -63,46 +64,96 @@ func testReadTestdataFile(t *testing.T, path string) []byte {
|
|||
}
|
||||
|
||||
func TestNewServerUnix(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
tempDir := t.TempDir()
|
||||
path := filepath.Join(tempDir, "rclone.sock")
|
||||
|
||||
cfg := DefaultCfg()
|
||||
cfg.ListenAddr = []string{path}
|
||||
|
||||
auth := AuthConfig{
|
||||
BasicUser: "test",
|
||||
BasicPass: "test",
|
||||
servers := []struct {
|
||||
name string
|
||||
status int
|
||||
result string
|
||||
cfg Config
|
||||
auth AuthConfig
|
||||
user string
|
||||
pass string
|
||||
}{
|
||||
{
|
||||
name: "ServerWithoutAuth/NoCreds",
|
||||
status: http.StatusOK,
|
||||
result: "hello world",
|
||||
cfg: Config{
|
||||
ListenAddr: []string{path},
|
||||
},
|
||||
}, {
|
||||
name: "ServerWithAuth/NoCreds",
|
||||
status: http.StatusUnauthorized,
|
||||
cfg: Config{
|
||||
ListenAddr: []string{path},
|
||||
},
|
||||
auth: AuthConfig{
|
||||
BasicUser: "test",
|
||||
BasicPass: "test",
|
||||
},
|
||||
}, {
|
||||
name: "ServerWithAuth/GoodCreds",
|
||||
status: http.StatusOK,
|
||||
result: "hello world",
|
||||
cfg: Config{
|
||||
ListenAddr: []string{path},
|
||||
},
|
||||
auth: AuthConfig{
|
||||
BasicUser: "test",
|
||||
BasicPass: "test",
|
||||
},
|
||||
user: "test",
|
||||
pass: "test",
|
||||
}, {
|
||||
name: "ServerWithAuth/BadCreds",
|
||||
status: http.StatusUnauthorized,
|
||||
cfg: Config{
|
||||
ListenAddr: []string{path},
|
||||
},
|
||||
auth: AuthConfig{
|
||||
BasicUser: "test",
|
||||
BasicPass: "test",
|
||||
},
|
||||
user: "testBAD",
|
||||
pass: "testBAD",
|
||||
},
|
||||
}
|
||||
|
||||
s, err := NewServer(ctx, WithConfig(cfg), WithAuth(auth))
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
require.NoError(t, s.Shutdown())
|
||||
_, err := os.Stat(path)
|
||||
require.ErrorIs(t, err, os.ErrNotExist, "shutdown should remove socket")
|
||||
}()
|
||||
for _, ss := range servers {
|
||||
t.Run(ss.name, func(t *testing.T) {
|
||||
s, err := NewServer(context.Background(), WithConfig(ss.cfg), WithAuth(ss.auth))
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
require.NoError(t, s.Shutdown())
|
||||
_, err := os.Stat(path)
|
||||
require.ErrorIs(t, err, os.ErrNotExist, "shutdown should remove socket")
|
||||
}()
|
||||
|
||||
require.Empty(t, s.URLs(), "unix socket should not appear in URLs")
|
||||
require.Empty(t, s.URLs(), "unix socket should not appear in URLs")
|
||||
|
||||
expected := []byte("hello world")
|
||||
s.Router().Mount("/", testEchoHandler(expected))
|
||||
s.Serve()
|
||||
s.Router().Mount("/", testEchoHandler([]byte(ss.result)))
|
||||
s.Serve()
|
||||
|
||||
client := testNewHTTPClientUnix(path)
|
||||
req, err := http.NewRequest("GET", "http://unix", nil)
|
||||
require.NoError(t, err)
|
||||
client := testNewHTTPClientUnix(path)
|
||||
req, err := http.NewRequest("GET", "http://unix", nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
req.SetBasicAuth(ss.user, ss.pass)
|
||||
|
||||
testExpectRespBody(t, resp, expected)
|
||||
resp, err := client.Do(req)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode, "unix sockets should ignore auth")
|
||||
require.Equal(t, ss.status, resp.StatusCode, fmt.Sprintf("should return status %d", ss.status))
|
||||
|
||||
for _, key := range _testCORSHeaderKeys {
|
||||
require.NotContains(t, resp.Header, key, "unix sockets should not be sent CORS headers")
|
||||
if ss.result != "" {
|
||||
testExpectRespBody(t, resp, []byte(ss.result))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user