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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
|
package s3api
import (
"bytes"
"crypto/md5"
"encoding/base64"
"io"
"net/http"
"net/http/httptest"
"testing"
"github.com/gorilla/mux"
"github.com/seaweedfs/seaweedfs/weed/kms"
"github.com/seaweedfs/seaweedfs/weed/kms/local"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
)
// TestKeyPair represents a test SSE-C key pair
type TestKeyPair struct {
Key []byte
KeyB64 string
KeyMD5 string
}
// TestSSEKMSKey represents a test SSE-KMS key
type TestSSEKMSKey struct {
KeyID string
Cleanup func()
}
// GenerateTestSSECKey creates a test SSE-C key pair
func GenerateTestSSECKey(seed byte) *TestKeyPair {
key := make([]byte, 32) // 256-bit key
for i := range key {
key[i] = seed + byte(i)
}
keyB64 := base64.StdEncoding.EncodeToString(key)
md5sum := md5.Sum(key)
keyMD5 := base64.StdEncoding.EncodeToString(md5sum[:])
return &TestKeyPair{
Key: key,
KeyB64: keyB64,
KeyMD5: keyMD5,
}
}
// SetupTestSSECHeaders sets SSE-C headers on an HTTP request
func SetupTestSSECHeaders(req *http.Request, keyPair *TestKeyPair) {
req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerAlgorithm, "AES256")
req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerKey, keyPair.KeyB64)
req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerKeyMD5, keyPair.KeyMD5)
}
// SetupTestSSECCopyHeaders sets SSE-C copy source headers on an HTTP request
func SetupTestSSECCopyHeaders(req *http.Request, keyPair *TestKeyPair) {
req.Header.Set(s3_constants.AmzCopySourceServerSideEncryptionCustomerAlgorithm, "AES256")
req.Header.Set(s3_constants.AmzCopySourceServerSideEncryptionCustomerKey, keyPair.KeyB64)
req.Header.Set(s3_constants.AmzCopySourceServerSideEncryptionCustomerKeyMD5, keyPair.KeyMD5)
}
// SetupTestKMS initializes a local KMS provider for testing
func SetupTestKMS(t *testing.T) *TestSSEKMSKey {
// Initialize local KMS provider directly
provider, err := local.NewLocalKMSProvider(nil)
if err != nil {
t.Fatalf("Failed to create local KMS provider: %v", err)
}
// Set it as the global provider
kms.SetGlobalKMSProvider(provider)
// Create a test key
localProvider := provider.(*local.LocalKMSProvider)
testKey, err := localProvider.CreateKey("Test key for SSE-KMS", []string{"test-key"})
if err != nil {
t.Fatalf("Failed to create test key: %v", err)
}
// Cleanup function
cleanup := func() {
kms.SetGlobalKMSProvider(nil) // Clear global KMS
if err := provider.Close(); err != nil {
t.Logf("Warning: Failed to close KMS provider: %v", err)
}
}
return &TestSSEKMSKey{
KeyID: testKey.KeyID,
Cleanup: cleanup,
}
}
// SetupTestSSEKMSHeaders sets SSE-KMS headers on an HTTP request
func SetupTestSSEKMSHeaders(req *http.Request, keyID string) {
req.Header.Set(s3_constants.AmzServerSideEncryption, "aws:kms")
if keyID != "" {
req.Header.Set(s3_constants.AmzServerSideEncryptionAwsKmsKeyId, keyID)
}
}
// CreateTestMetadata creates test metadata with SSE information
func CreateTestMetadata() map[string][]byte {
return make(map[string][]byte)
}
// CreateTestMetadataWithSSEC creates test metadata containing SSE-C information
func CreateTestMetadataWithSSEC(keyPair *TestKeyPair) map[string][]byte {
metadata := CreateTestMetadata()
metadata[s3_constants.AmzServerSideEncryptionCustomerAlgorithm] = []byte("AES256")
metadata[s3_constants.AmzServerSideEncryptionCustomerKeyMD5] = []byte(keyPair.KeyMD5)
// Add encryption IV and other encrypted data that would be stored
iv := make([]byte, 16)
for i := range iv {
iv[i] = byte(i)
}
StoreSSECIVInMetadata(metadata, iv)
return metadata
}
// CreateTestMetadataWithSSEKMS creates test metadata containing SSE-KMS information
func CreateTestMetadataWithSSEKMS(sseKey *SSEKMSKey) map[string][]byte {
metadata := CreateTestMetadata()
metadata[s3_constants.AmzServerSideEncryption] = []byte("aws:kms")
if sseKey != nil {
serialized, _ := SerializeSSEKMSMetadata(sseKey)
metadata[s3_constants.AmzEncryptedDataKey] = sseKey.EncryptedDataKey
metadata[s3_constants.AmzEncryptionContextMeta] = serialized
}
return metadata
}
// CreateTestHTTPRequest creates a test HTTP request with optional SSE headers
func CreateTestHTTPRequest(method, path string, body []byte) *http.Request {
var bodyReader io.Reader
if body != nil {
bodyReader = bytes.NewReader(body)
}
req := httptest.NewRequest(method, path, bodyReader)
return req
}
// CreateTestHTTPResponse creates a test HTTP response recorder
func CreateTestHTTPResponse() *httptest.ResponseRecorder {
return httptest.NewRecorder()
}
// SetupTestMuxVars sets up mux variables for testing
func SetupTestMuxVars(req *http.Request, vars map[string]string) {
mux.SetURLVars(req, vars)
}
// AssertSSECHeaders verifies that SSE-C response headers are set correctly
func AssertSSECHeaders(t *testing.T, w *httptest.ResponseRecorder, keyPair *TestKeyPair) {
algorithm := w.Header().Get(s3_constants.AmzServerSideEncryptionCustomerAlgorithm)
if algorithm != "AES256" {
t.Errorf("Expected algorithm AES256, got %s", algorithm)
}
keyMD5 := w.Header().Get(s3_constants.AmzServerSideEncryptionCustomerKeyMD5)
if keyMD5 != keyPair.KeyMD5 {
t.Errorf("Expected key MD5 %s, got %s", keyPair.KeyMD5, keyMD5)
}
}
// AssertSSEKMSHeaders verifies that SSE-KMS response headers are set correctly
func AssertSSEKMSHeaders(t *testing.T, w *httptest.ResponseRecorder, keyID string) {
algorithm := w.Header().Get(s3_constants.AmzServerSideEncryption)
if algorithm != "aws:kms" {
t.Errorf("Expected algorithm aws:kms, got %s", algorithm)
}
if keyID != "" {
responseKeyID := w.Header().Get(s3_constants.AmzServerSideEncryptionAwsKmsKeyId)
if responseKeyID != keyID {
t.Errorf("Expected key ID %s, got %s", keyID, responseKeyID)
}
}
}
// CreateCorruptedSSECMetadata creates intentionally corrupted SSE-C metadata for testing
func CreateCorruptedSSECMetadata() map[string][]byte {
metadata := CreateTestMetadata()
// Missing algorithm
metadata[s3_constants.AmzServerSideEncryptionCustomerKeyMD5] = []byte("invalid-md5")
return metadata
}
// CreateCorruptedSSEKMSMetadata creates intentionally corrupted SSE-KMS metadata for testing
func CreateCorruptedSSEKMSMetadata() map[string][]byte {
metadata := CreateTestMetadata()
metadata[s3_constants.AmzServerSideEncryption] = []byte("aws:kms")
// Invalid encrypted data key
metadata[s3_constants.AmzEncryptedDataKey] = []byte("invalid-base64!")
return metadata
}
// TestDataSizes provides various data sizes for testing
var TestDataSizes = []int{
0, // Empty
1, // Single byte
15, // Less than AES block size
16, // Exactly AES block size
17, // More than AES block size
1024, // 1KB
65536, // 64KB
1048576, // 1MB
}
// GenerateTestData creates test data of specified size
func GenerateTestData(size int) []byte {
data := make([]byte, size)
for i := range data {
data[i] = byte(i % 256)
}
return data
}
|