s3api_put_object_helper_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package s3api
  2. import (
  3. "net/http"
  4. "strings"
  5. "testing"
  6. "github.com/seaweedfs/seaweedfs/weed/credential"
  7. _ "github.com/seaweedfs/seaweedfs/weed/credential/memory"
  8. "github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
  9. )
  10. func TestGetRequestDataReader_ChunkedEncodingWithoutIAM(t *testing.T) {
  11. // Create an S3ApiServer with IAM disabled
  12. s3a := &S3ApiServer{
  13. iam: NewIdentityAccessManagementWithStore(&S3ApiServerOption{}, string(credential.StoreTypeMemory)),
  14. }
  15. // Ensure IAM is disabled for this test
  16. s3a.iam.isAuthEnabled = false
  17. tests := []struct {
  18. name string
  19. contentSha256 string
  20. expectedError s3err.ErrorCode
  21. shouldProcess bool
  22. description string
  23. }{
  24. {
  25. name: "RegularRequest",
  26. contentSha256: "",
  27. expectedError: s3err.ErrNone,
  28. shouldProcess: false,
  29. description: "Regular requests without chunked encoding should pass through unchanged",
  30. },
  31. {
  32. name: "StreamingSignedWithoutIAM",
  33. contentSha256: "STREAMING-AWS4-HMAC-SHA256-PAYLOAD",
  34. expectedError: s3err.ErrAuthNotSetup,
  35. shouldProcess: false,
  36. description: "Streaming signed requests should fail when IAM is disabled",
  37. },
  38. {
  39. name: "StreamingUnsignedWithoutIAM",
  40. contentSha256: "STREAMING-UNSIGNED-PAYLOAD-TRAILER",
  41. expectedError: s3err.ErrNone,
  42. shouldProcess: true,
  43. description: "Streaming unsigned requests should be processed even when IAM is disabled",
  44. },
  45. }
  46. for _, tt := range tests {
  47. t.Run(tt.name, func(t *testing.T) {
  48. body := strings.NewReader("test data")
  49. req, _ := http.NewRequest("PUT", "/bucket/key", body)
  50. if tt.contentSha256 != "" {
  51. req.Header.Set("x-amz-content-sha256", tt.contentSha256)
  52. }
  53. dataReader, errCode := getRequestDataReader(s3a, req)
  54. // Check error code
  55. if errCode != tt.expectedError {
  56. t.Errorf("Expected error code %v, got %v", tt.expectedError, errCode)
  57. }
  58. // For successful cases, check if processing occurred
  59. if errCode == s3err.ErrNone {
  60. if tt.shouldProcess {
  61. // For chunked requests, the reader should be different from the original body
  62. if dataReader == req.Body {
  63. t.Error("Expected dataReader to be processed by newChunkedReader, but got raw request body")
  64. }
  65. } else {
  66. // For regular requests, the reader should be the same as the original body
  67. if dataReader != req.Body {
  68. t.Error("Expected dataReader to be the same as request body for regular requests")
  69. }
  70. }
  71. }
  72. t.Logf("Test case: %s - %s", tt.name, tt.description)
  73. })
  74. }
  75. }
  76. func TestGetRequestDataReader_AuthTypeDetection(t *testing.T) {
  77. // Create an S3ApiServer with IAM disabled
  78. s3a := &S3ApiServer{
  79. iam: NewIdentityAccessManagementWithStore(&S3ApiServerOption{}, string(credential.StoreTypeMemory)),
  80. }
  81. s3a.iam.isAuthEnabled = false
  82. // Test the specific case mentioned in the issue where chunked data
  83. // with checksum headers would be stored incorrectly
  84. t.Run("ChunkedDataWithChecksum", func(t *testing.T) {
  85. // Simulate a request with chunked data and checksum trailer
  86. body := strings.NewReader("test content")
  87. req, _ := http.NewRequest("PUT", "/bucket/key", body)
  88. req.Header.Set("x-amz-content-sha256", "STREAMING-UNSIGNED-PAYLOAD-TRAILER")
  89. req.Header.Set("x-amz-trailer", "x-amz-checksum-crc32")
  90. // Verify the auth type is detected correctly
  91. authType := getRequestAuthType(req)
  92. if authType != authTypeStreamingUnsigned {
  93. t.Errorf("Expected authTypeStreamingUnsigned, got %v", authType)
  94. }
  95. // Verify the request is processed correctly
  96. dataReader, errCode := getRequestDataReader(s3a, req)
  97. if errCode != s3err.ErrNone {
  98. t.Errorf("Expected no error, got %v", errCode)
  99. }
  100. // The dataReader should be processed by newChunkedReader
  101. if dataReader == req.Body {
  102. t.Error("Expected dataReader to be processed by newChunkedReader to handle chunked encoding")
  103. }
  104. })
  105. }
  106. func TestGetRequestDataReader_IAMEnabled(t *testing.T) {
  107. // Create an S3ApiServer with IAM enabled
  108. s3a := &S3ApiServer{
  109. iam: NewIdentityAccessManagementWithStore(&S3ApiServerOption{}, string(credential.StoreTypeMemory)),
  110. }
  111. s3a.iam.isAuthEnabled = true
  112. t.Run("StreamingUnsignedWithIAMEnabled", func(t *testing.T) {
  113. body := strings.NewReader("test data")
  114. req, _ := http.NewRequest("PUT", "/bucket/key", body)
  115. req.Header.Set("x-amz-content-sha256", "STREAMING-UNSIGNED-PAYLOAD-TRAILER")
  116. dataReader, errCode := getRequestDataReader(s3a, req)
  117. // Should succeed and be processed
  118. if errCode != s3err.ErrNone {
  119. t.Errorf("Expected no error, got %v", errCode)
  120. }
  121. // Should be processed by newChunkedReader
  122. if dataReader == req.Body {
  123. t.Error("Expected dataReader to be processed by newChunkedReader")
  124. }
  125. })
  126. }
  127. // Test helper to verify auth type detection works correctly
  128. func TestAuthTypeDetection(t *testing.T) {
  129. tests := []struct {
  130. name string
  131. headers map[string]string
  132. expectedType authType
  133. }{
  134. {
  135. name: "StreamingUnsigned",
  136. headers: map[string]string{"x-amz-content-sha256": "STREAMING-UNSIGNED-PAYLOAD-TRAILER"},
  137. expectedType: authTypeStreamingUnsigned,
  138. },
  139. {
  140. name: "StreamingSigned",
  141. headers: map[string]string{"x-amz-content-sha256": "STREAMING-AWS4-HMAC-SHA256-PAYLOAD"},
  142. expectedType: authTypeStreamingSigned,
  143. },
  144. {
  145. name: "Regular",
  146. headers: map[string]string{},
  147. expectedType: authTypeAnonymous,
  148. },
  149. }
  150. for _, tt := range tests {
  151. t.Run(tt.name, func(t *testing.T) {
  152. req, _ := http.NewRequest("PUT", "/bucket/key", strings.NewReader("test"))
  153. for key, value := range tt.headers {
  154. req.Header.Set(key, value)
  155. }
  156. authType := getRequestAuthType(req)
  157. if authType != tt.expectedType {
  158. t.Errorf("Expected auth type %v, got %v", tt.expectedType, authType)
  159. }
  160. })
  161. }
  162. }