From 69ae5f2aaf6f73884e3ba270e3a8fc64149aa13b Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 27 Jan 2025 19:20:10 +0000 Subject: [PATCH] serve: fix auth proxy using stale config parameters when making a backend Before this change, if the auth proxy script returned updated config parameters for a backend (eg the api_key changed for the backend) rclone would continue to re-use the old backend with the old config parameters out of the fscache. This fixes the problem by adding a short config hash to the fs names created by the auth proxy. They used to be `proxy-user` (where user was as supplied to the auth proxy) and they will now be `proxy-user-hash` where hash is a base64 encoded partial md5 hash of the config. These new config names will be visible in the logs so this is a user visible change. --- cmd/serve/proxy/proxy.go | 9 ++++++++- cmd/serve/proxy/proxy_test.go | 13 +++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/cmd/serve/proxy/proxy.go b/cmd/serve/proxy/proxy.go index 08ffa8b53..9164a4f49 100644 --- a/cmd/serve/proxy/proxy.go +++ b/cmd/serve/proxy/proxy.go @@ -4,8 +4,10 @@ package proxy import ( "bytes" "context" + "crypto/md5" "crypto/sha256" "crypto/subtle" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -217,8 +219,13 @@ func (p *Proxy) call(user, auth string, isPublicKey bool) (value interface{}, er return nil, fmt.Errorf("proxy: couldn't find backend for %q: %w", fsName, err) } + // Add a config hash to ensure configs with different values have different names. + // 5 characters length is 5*6 = 30 bits of base64 + md5sumBinary := md5.Sum([]byte(config.String())) + configHash := base64.RawURLEncoding.EncodeToString(md5sumBinary[:])[:5] + // base name of config on user name. This may appear in logs - name := "proxy-" + user + name := "proxy-" + user + "-" + configHash fsString := name + ":" + root // Look for fs in the VFS cache diff --git a/cmd/serve/proxy/proxy_test.go b/cmd/serve/proxy/proxy_test.go index 539468d44..fd335e41c 100644 --- a/cmd/serve/proxy/proxy_test.go +++ b/cmd/serve/proxy/proxy_test.go @@ -90,7 +90,8 @@ func TestRun(t *testing.T) { require.NotNil(t, entry.vfs) f := entry.vfs.Fs() require.NotNil(t, f) - assert.Equal(t, "proxy-"+testUser, f.Name()) + assert.True(t, strings.HasPrefix(f.Name(), "proxy-"+testUser+"-")) + assert.Equal(t, len("proxy-"+testUser+"-")+5, len(f.Name())) assert.True(t, strings.HasPrefix(f.String(), "Local file system")) // check it is in the cache @@ -108,7 +109,7 @@ func TestRun(t *testing.T) { vfs, vfsKey, err := p.Call(testUser, testPass, false) require.NoError(t, err) require.NotNil(t, vfs) - assert.Equal(t, "proxy-"+testUser, vfs.Fs().Name()) + assert.True(t, strings.HasPrefix(vfs.Fs().Name(), "proxy-"+testUser+"-")) assert.Equal(t, testUser, vfsKey) // check it is in the cache @@ -129,7 +130,7 @@ func TestRun(t *testing.T) { vfs, vfsKey, err = p.Call(testUser, testPass, false) require.NoError(t, err) require.NotNil(t, vfs) - assert.Equal(t, "proxy-"+testUser, vfs.Fs().Name()) + assert.True(t, strings.HasPrefix(vfs.Fs().Name(), "proxy-"+testUser+"-")) assert.Equal(t, testUser, vfsKey) // check cache is at the same level @@ -173,7 +174,7 @@ func TestRun(t *testing.T) { require.NotNil(t, entry.vfs) f := entry.vfs.Fs() require.NotNil(t, f) - assert.Equal(t, "proxy-"+testUser, f.Name()) + assert.True(t, strings.HasPrefix(f.Name(), "proxy-"+testUser+"-")) assert.True(t, strings.HasPrefix(f.String(), "Local file system")) // check it is in the cache @@ -195,7 +196,7 @@ func TestRun(t *testing.T) { ) require.NoError(t, err) require.NotNil(t, vfs) - assert.Equal(t, "proxy-"+testUser, vfs.Fs().Name()) + assert.True(t, strings.HasPrefix(vfs.Fs().Name(), "proxy-"+testUser+"-")) assert.Equal(t, testUser, vfsKey) // check it is in the cache @@ -216,7 +217,7 @@ func TestRun(t *testing.T) { vfs, vfsKey, err = p.Call(testUser, publicKeyString, true) require.NoError(t, err) require.NotNil(t, vfs) - assert.Equal(t, "proxy-"+testUser, vfs.Fs().Name()) + assert.True(t, strings.HasPrefix(vfs.Fs().Name(), "proxy-"+testUser+"-")) assert.Equal(t, testUser, vfsKey) // check cache is at the same level