From d1e6e2f925f2688b5d19b9f8a83d1233fdcc91c8 Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Mon, 24 Aug 2026 09:37:26 +0100 Subject: [PATCH] serve s3: fix each server accepting the --auth-key credentials of all the others gofakes3 kept the keys given with --auth-key in a store global to the process, so when more than one serve s3 was running in one rclone (eg started via the rc) each accepted the others' credentials and a client with the key for one server could read and write the backend of another. This updates gofakes3 to v0.0.9 which keeps auth keys per instance and adds a test that two servers only accept their own keys. --- cmd/serve/s3/s3_test.go | 34 ++++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/cmd/serve/s3/s3_test.go b/cmd/serve/s3/s3_test.go index 1eea39916..f789fc6e4 100644 --- a/cmd/serve/s3/s3_test.go +++ b/cmd/serve/s3/s3_test.go @@ -8,6 +8,7 @@ import ( "context" "fmt" "io" + "net/http" "net/url" "path" "path/filepath" @@ -15,6 +16,8 @@ import ( "testing" "time" + "github.com/aws/aws-sdk-go-v2/aws" + v4 "github.com/aws/aws-sdk-go-v2/aws/signer/v4" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" _ "github.com/rclone/rclone/backend/local" @@ -336,6 +339,37 @@ func TestNewServerPerServerAuthProxy(t *testing.T) { assert.Nil(t, w.provider.VFS(), "expected no fixed VFS when auth proxy is in use") } +// TestAuthKeyPerServer checks that two servers in the same process +// with different --auth-key pairs only accept their own credentials. +func TestAuthKeyPerServer(t *testing.T) { + fstest.Initialise() + f, err := fs.NewFs(context.Background(), "testdata") + require.NoError(t, err) + + urlA, keyA, secA, sA := serveS3(t, f) + defer func() { assert.NoError(t, sA.server.Shutdown()) }() + urlB, keyB, secB, sB := serveS3(t, f) + defer func() { assert.NoError(t, sB.server.Shutdown()) }() + + signedGet := func(url, accessKeyID, secret string) int { + req, err := http.NewRequest("GET", url+"/", nil) + require.NoError(t, err) + req.Header.Set("X-Amz-Content-Sha256", "UNSIGNED-PAYLOAD") + err = v4.NewSigner().SignHTTP(context.Background(), aws.Credentials{AccessKeyID: accessKeyID, SecretAccessKey: secret}, req, "UNSIGNED-PAYLOAD", "s3", "us-east-1", time.Now()) + require.NoError(t, err) + resp, err := http.DefaultClient.Do(req) + require.NoError(t, err) + _, _ = io.ReadAll(resp.Body) + _ = resp.Body.Close() + return resp.StatusCode + } + + assert.Equal(t, http.StatusOK, signedGet(urlA, keyA, secA), "A with A's key") + assert.Equal(t, http.StatusOK, signedGet(urlB, keyB, secB), "B with B's key") + assert.Equal(t, http.StatusForbidden, signedGet(urlA, keyB, secB), "A with B's key") + assert.Equal(t, http.StatusForbidden, signedGet(urlB, keyA, secA), "B with A's key") +} + func TestRc(t *testing.T) { servetest.TestRc(t, rc.Params{ "type": "s3", diff --git a/go.mod b/go.mod index c1457f615..443a53ec0 100644 --- a/go.mod +++ b/go.mod @@ -74,7 +74,7 @@ require ( github.com/quasilyte/go-ruleguard/dsl v0.3.23 github.com/rclone/Proton-API-Bridge v1.0.5 github.com/rclone/go-proton-api v1.0.4 - github.com/rclone/gofakes3 v0.0.8 + github.com/rclone/gofakes3 v0.0.9 github.com/rfjakob/eme v1.2.0 github.com/rivo/uniseg v0.4.7 github.com/rogpeppe/go-internal v1.15.0 diff --git a/go.sum b/go.sum index 3f025d480..42d02d090 100644 --- a/go.sum +++ b/go.sum @@ -496,8 +496,8 @@ github.com/rclone/Proton-API-Bridge v1.0.5 h1:K1++Qtk3PvgkiCCiv6Pahju1TMOzKY6VSw github.com/rclone/Proton-API-Bridge v1.0.5/go.mod h1:vCeOPhlXzevN0AFojgh1zsjhetiShy/ArvJ/xkFUDWk= github.com/rclone/go-proton-api v1.0.4 h1:AJW0e9pB4j0hVK4WqyGErFwaI+5MUQWPCtj5FYYxtPg= github.com/rclone/go-proton-api v1.0.4/go.mod h1:QAlkFfswzrBuxvCORWV8rZdddg52hahMN98CFWoFW1E= -github.com/rclone/gofakes3 v0.0.8 h1:UKlrvEEVs/V5zs35n35avpN8zGkei/YsX14gNZr1MlA= -github.com/rclone/gofakes3 v0.0.8/go.mod h1:0udb2hmIO9mHXDAgcdycCzSPPASAGIz410t+m0LKmnE= +github.com/rclone/gofakes3 v0.0.9 h1:1EzeGoSefXmk/DrmmJvJ6B9HR9uUMih4YB2fkQk88Wg= +github.com/rclone/gofakes3 v0.0.9/go.mod h1:0udb2hmIO9mHXDAgcdycCzSPPASAGIz410t+m0LKmnE= github.com/relvacode/iso8601 v1.7.0 h1:BXy+V60stMP6cpswc+a93Mq3e65PfXCgDFfhvNNGrdo= github.com/relvacode/iso8601 v1.7.0/go.mod h1:FlNp+jz+TXpyRqgmM7tnzHHzBnz776kmAH2h3sZCn0I= github.com/rfjakob/eme v1.2.0 h1:8dAHL+WVAw06+7DkRKnRiFp1JL3QjcJEZFqDnndUaSI=