s3_sse_c_range_test.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package s3api
  2. import (
  3. "bytes"
  4. "crypto/md5"
  5. "encoding/base64"
  6. "io"
  7. "net/http"
  8. "net/http/httptest"
  9. "testing"
  10. "github.com/gorilla/mux"
  11. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
  12. )
  13. // ResponseRecorder that also implements http.Flusher
  14. type recorderFlusher struct{ *httptest.ResponseRecorder }
  15. func (r recorderFlusher) Flush() {}
  16. // TestSSECRangeRequestsSupported verifies that HTTP Range requests are now supported
  17. // for SSE-C encrypted objects since the IV is stored in metadata and CTR mode allows seeking
  18. func TestSSECRangeRequestsSupported(t *testing.T) {
  19. // Create a request with Range header and valid SSE-C headers
  20. req := httptest.NewRequest(http.MethodGet, "/b/o", nil)
  21. req.Header.Set("Range", "bytes=10-20")
  22. req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerAlgorithm, "AES256")
  23. key := make([]byte, 32)
  24. for i := range key {
  25. key[i] = byte(i)
  26. }
  27. s := md5.Sum(key)
  28. keyMD5 := base64.StdEncoding.EncodeToString(s[:])
  29. req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerKey, base64.StdEncoding.EncodeToString(key))
  30. req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerKeyMD5, keyMD5)
  31. // Attach mux vars to avoid panic in error writer
  32. req = mux.SetURLVars(req, map[string]string{"bucket": "b", "object": "o"})
  33. // Create a mock HTTP response that simulates SSE-C encrypted object metadata
  34. proxyResponse := &http.Response{
  35. StatusCode: 200,
  36. Header: make(http.Header),
  37. Body: io.NopCloser(bytes.NewReader([]byte("mock encrypted data"))),
  38. }
  39. proxyResponse.Header.Set(s3_constants.AmzServerSideEncryptionCustomerAlgorithm, "AES256")
  40. proxyResponse.Header.Set(s3_constants.AmzServerSideEncryptionCustomerKeyMD5, keyMD5)
  41. // Call the function under test - should no longer reject range requests
  42. s3a := &S3ApiServer{
  43. option: &S3ApiServerOption{
  44. BucketsPath: "/buckets",
  45. },
  46. }
  47. rec := httptest.NewRecorder()
  48. w := recorderFlusher{rec}
  49. statusCode, _ := s3a.handleSSECResponse(req, proxyResponse, w)
  50. // Range requests should now be allowed to proceed (will be handled by filer layer)
  51. // The exact status code depends on the object existence and filer response
  52. if statusCode == http.StatusRequestedRangeNotSatisfiable {
  53. t.Fatalf("Range requests should no longer be rejected for SSE-C objects, got status %d", statusCode)
  54. }
  55. }