aboutsummaryrefslogtreecommitdiff
path: root/weed/s3api/s3api_put_object_helper_test.go
blob: 774741a0dfe7dd540b7941ea4561495aacabf3df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package s3api

import (
	"net/http"
	"strings"
	"testing"

	"github.com/seaweedfs/seaweedfs/weed/s3api/s3err"
)

func TestGetRequestDataReader_ChunkedEncodingWithoutIAM(t *testing.T) {
	// Create an S3ApiServer with IAM disabled
	s3a := &S3ApiServer{
		iam: NewIdentityAccessManagement(&S3ApiServerOption{}),
	}
	// Ensure IAM is disabled for this test
	s3a.iam.isAuthEnabled = false

	tests := []struct {
		name          string
		contentSha256 string
		expectedError s3err.ErrorCode
		shouldProcess bool
		description   string
	}{
		{
			name:          "RegularRequest",
			contentSha256: "",
			expectedError: s3err.ErrNone,
			shouldProcess: false,
			description:   "Regular requests without chunked encoding should pass through unchanged",
		},
		{
			name:          "StreamingSignedWithoutIAM",
			contentSha256: "STREAMING-AWS4-HMAC-SHA256-PAYLOAD",
			expectedError: s3err.ErrAuthNotSetup,
			shouldProcess: false,
			description:   "Streaming signed requests should fail when IAM is disabled",
		},
		{
			name:          "StreamingUnsignedWithoutIAM",
			contentSha256: "STREAMING-UNSIGNED-PAYLOAD-TRAILER",
			expectedError: s3err.ErrNone,
			shouldProcess: true,
			description:   "Streaming unsigned requests should be processed even when IAM is disabled",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			body := strings.NewReader("test data")
			req, _ := http.NewRequest("PUT", "/bucket/key", body)

			if tt.contentSha256 != "" {
				req.Header.Set("x-amz-content-sha256", tt.contentSha256)
			}

			dataReader, errCode := getRequestDataReader(s3a, req)

			// Check error code
			if errCode != tt.expectedError {
				t.Errorf("Expected error code %v, got %v", tt.expectedError, errCode)
			}

			// For successful cases, check if processing occurred
			if errCode == s3err.ErrNone {
				if tt.shouldProcess {
					// For chunked requests, the reader should be different from the original body
					if dataReader == req.Body {
						t.Error("Expected dataReader to be processed by newChunkedReader, but got raw request body")
					}
				} else {
					// For regular requests, the reader should be the same as the original body
					if dataReader != req.Body {
						t.Error("Expected dataReader to be the same as request body for regular requests")
					}
				}
			}

			t.Logf("Test case: %s - %s", tt.name, tt.description)
		})
	}
}

func TestGetRequestDataReader_AuthTypeDetection(t *testing.T) {
	// Create an S3ApiServer with IAM disabled
	s3a := &S3ApiServer{
		iam: NewIdentityAccessManagement(&S3ApiServerOption{}),
	}
	s3a.iam.isAuthEnabled = false

	// Test the specific case mentioned in the issue where chunked data
	// with checksum headers would be stored incorrectly
	t.Run("ChunkedDataWithChecksum", func(t *testing.T) {
		// Simulate a request with chunked data and checksum trailer
		body := strings.NewReader("test content")
		req, _ := http.NewRequest("PUT", "/bucket/key", body)
		req.Header.Set("x-amz-content-sha256", "STREAMING-UNSIGNED-PAYLOAD-TRAILER")
		req.Header.Set("x-amz-trailer", "x-amz-checksum-crc32")

		// Verify the auth type is detected correctly
		authType := getRequestAuthType(req)
		if authType != authTypeStreamingUnsigned {
			t.Errorf("Expected authTypeStreamingUnsigned, got %v", authType)
		}

		// Verify the request is processed correctly
		dataReader, errCode := getRequestDataReader(s3a, req)
		if errCode != s3err.ErrNone {
			t.Errorf("Expected no error, got %v", errCode)
		}

		// The dataReader should be processed by newChunkedReader
		if dataReader == req.Body {
			t.Error("Expected dataReader to be processed by newChunkedReader to handle chunked encoding")
		}
	})
}

func TestGetRequestDataReader_IAMEnabled(t *testing.T) {
	// Create an S3ApiServer with IAM enabled
	s3a := &S3ApiServer{
		iam: NewIdentityAccessManagement(&S3ApiServerOption{}),
	}
	s3a.iam.isAuthEnabled = true

	t.Run("StreamingUnsignedWithIAMEnabled", func(t *testing.T) {
		body := strings.NewReader("test data")
		req, _ := http.NewRequest("PUT", "/bucket/key", body)
		req.Header.Set("x-amz-content-sha256", "STREAMING-UNSIGNED-PAYLOAD-TRAILER")

		dataReader, errCode := getRequestDataReader(s3a, req)

		// Should succeed and be processed
		if errCode != s3err.ErrNone {
			t.Errorf("Expected no error, got %v", errCode)
		}

		// Should be processed by newChunkedReader
		if dataReader == req.Body {
			t.Error("Expected dataReader to be processed by newChunkedReader")
		}
	})
}

// Test helper to verify auth type detection works correctly
func TestAuthTypeDetection(t *testing.T) {
	tests := []struct {
		name         string
		headers      map[string]string
		expectedType authType
	}{
		{
			name:         "StreamingUnsigned",
			headers:      map[string]string{"x-amz-content-sha256": "STREAMING-UNSIGNED-PAYLOAD-TRAILER"},
			expectedType: authTypeStreamingUnsigned,
		},
		{
			name:         "StreamingSigned",
			headers:      map[string]string{"x-amz-content-sha256": "STREAMING-AWS4-HMAC-SHA256-PAYLOAD"},
			expectedType: authTypeStreamingSigned,
		},
		{
			name:         "Regular",
			headers:      map[string]string{},
			expectedType: authTypeAnonymous,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			req, _ := http.NewRequest("PUT", "/bucket/key", strings.NewReader("test"))
			for key, value := range tt.headers {
				req.Header.Set(key, value)
			}

			authType := getRequestAuthType(req)
			if authType != tt.expectedType {
				t.Errorf("Expected auth type %v, got %v", tt.expectedType, authType)
			}
		})
	}
}