mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-06-13 23:36:45 +03:00
83b7ea5e7b
* fix(s3): keep server-side copy data in the bucket collection UploadPartCopy and SSE-C CopyObject assigned destination volumes against r.URL.Path, the S3 request URI. The filer derives a bucket's collection only when the assign path sits under its buckets folder, so an S3 URI routed copied bytes to the default collection instead of the destination bucket's. Assign against the destination's real filer path. * refactor(s3): centralize copy-part path and thread dstPath into SSE-C copy Extract copyPartLocation so the fast path and writeEmptyCopyPart share one definition of the .uploads/<id>/<n>_copy.part location. Pass the destination filer path into copyChunksWithSSEC instead of re-deriving it from the request, and thread it through key rotation so re-encrypt copies also assign in the destination bucket's collection.
46 lines
2.0 KiB
Go
46 lines
2.0 KiB
Go
package s3api
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/filer"
|
|
"github.com/seaweedfs/seaweedfs/weed/util"
|
|
)
|
|
|
|
// TestCopyDestinationPathResolvesBucketCollection guards against server-side
|
|
// copies routing data into the default collection.
|
|
//
|
|
// The filer maps a write to a bucket's collection only when the AssignVolume
|
|
// Path sits under its buckets folder (/buckets/<bucket>/...). UploadPartCopy
|
|
// and SSE-C CopyObject used to assign destination volumes against r.URL.Path,
|
|
// the S3 request URI (e.g. /bucket/key), which never has that prefix; the
|
|
// copied bytes therefore landed in the default collection instead of the
|
|
// destination bucket's. The handlers must assign against the real filer path
|
|
// of the destination.
|
|
func TestCopyDestinationPathResolvesBucketCollection(t *testing.T) {
|
|
const bucket = "docker-registry"
|
|
s3a := &S3ApiServer{option: &S3ApiServerOption{BucketsPath: "/buckets"}}
|
|
f := &filer.Filer{DirBucketsPath: "/buckets"}
|
|
|
|
// The S3 request URI is not a filer path: the filer cannot derive the
|
|
// destination bucket from it. This is the shape that caused the leak.
|
|
if got := f.DetectBucket(util.FullPath("/" + bucket + "/blobs/data")); got != "" {
|
|
t.Fatalf("S3 request URI unexpectedly mapped to collection %q; the test no longer reproduces the bug", got)
|
|
}
|
|
|
|
// UploadPartCopy assigns against the destination part path under .uploads.
|
|
uploadDir, partName := s3a.copyPartLocation(bucket, "uploadid", 1)
|
|
partPath := uploadDir + "/" + partName
|
|
if got := f.DetectBucket(util.FullPath(partPath)); got != bucket {
|
|
t.Fatalf("UploadPartCopy dst path %q resolved to collection %q, want %q", partPath, got, bucket)
|
|
}
|
|
|
|
// CopyObject (including the SSE-C paths) assigns against the destination
|
|
// object path.
|
|
objPath := fmt.Sprintf("%s/%s", s3a.bucketDir(bucket), "blobs/data")
|
|
if got := f.DetectBucket(util.FullPath(objPath)); got != bucket {
|
|
t.Fatalf("CopyObject dst path %q resolved to collection %q, want %q", objPath, got, bucket)
|
|
}
|
|
}
|