s3_sse_error_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. package s3api
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "strings"
  8. "testing"
  9. "github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
  10. )
  11. // TestSSECWrongKeyDecryption tests decryption with wrong SSE-C key
  12. func TestSSECWrongKeyDecryption(t *testing.T) {
  13. // Setup original key and encrypt data
  14. originalKey := GenerateTestSSECKey(1)
  15. testData := "Hello, SSE-C world!"
  16. encryptedReader, iv, err := CreateSSECEncryptedReader(strings.NewReader(testData), &SSECustomerKey{
  17. Algorithm: "AES256",
  18. Key: originalKey.Key,
  19. KeyMD5: originalKey.KeyMD5,
  20. })
  21. if err != nil {
  22. t.Fatalf("Failed to create encrypted reader: %v", err)
  23. }
  24. // Read encrypted data
  25. encryptedData, err := io.ReadAll(encryptedReader)
  26. if err != nil {
  27. t.Fatalf("Failed to read encrypted data: %v", err)
  28. }
  29. // Try to decrypt with wrong key
  30. wrongKey := GenerateTestSSECKey(2) // Different seed = different key
  31. decryptedReader, err := CreateSSECDecryptedReader(bytes.NewReader(encryptedData), &SSECustomerKey{
  32. Algorithm: "AES256",
  33. Key: wrongKey.Key,
  34. KeyMD5: wrongKey.KeyMD5,
  35. }, iv)
  36. if err != nil {
  37. t.Fatalf("Failed to create decrypted reader: %v", err)
  38. }
  39. // Read decrypted data - should be garbage/different from original
  40. decryptedData, err := io.ReadAll(decryptedReader)
  41. if err != nil {
  42. t.Fatalf("Failed to read decrypted data: %v", err)
  43. }
  44. // Verify the decrypted data is NOT the same as original (wrong key used)
  45. if string(decryptedData) == testData {
  46. t.Error("Decryption with wrong key should not produce original data")
  47. }
  48. }
  49. // TestSSEKMSKeyNotFound tests handling of missing KMS key
  50. func TestSSEKMSKeyNotFound(t *testing.T) {
  51. // Note: The local KMS provider creates keys on-demand by design.
  52. // This test validates that when on-demand creation fails or is disabled,
  53. // appropriate errors are returned.
  54. // Test with an invalid key ID that would fail even on-demand creation
  55. invalidKeyID := "" // Empty key ID should fail
  56. encryptionContext := BuildEncryptionContext("test-bucket", "test-object", false)
  57. _, _, err := CreateSSEKMSEncryptedReader(strings.NewReader("test data"), invalidKeyID, encryptionContext)
  58. // Should get an error for invalid/empty key
  59. if err == nil {
  60. t.Error("Expected error for empty KMS key ID, got none")
  61. }
  62. // For local KMS with on-demand creation, we test what we can realistically test
  63. if err != nil {
  64. t.Logf("Got expected error for empty key ID: %v", err)
  65. }
  66. }
  67. // TestSSEHeadersWithoutEncryption tests inconsistent state where headers are present but no encryption
  68. func TestSSEHeadersWithoutEncryption(t *testing.T) {
  69. testCases := []struct {
  70. name string
  71. setupReq func() *http.Request
  72. }{
  73. {
  74. name: "SSE-C algorithm without key",
  75. setupReq: func() *http.Request {
  76. req := CreateTestHTTPRequest("PUT", "/bucket/object", nil)
  77. req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerAlgorithm, "AES256")
  78. // Missing key and MD5
  79. return req
  80. },
  81. },
  82. {
  83. name: "SSE-C key without algorithm",
  84. setupReq: func() *http.Request {
  85. req := CreateTestHTTPRequest("PUT", "/bucket/object", nil)
  86. keyPair := GenerateTestSSECKey(1)
  87. req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerKey, keyPair.KeyB64)
  88. // Missing algorithm
  89. return req
  90. },
  91. },
  92. {
  93. name: "SSE-KMS key ID without algorithm",
  94. setupReq: func() *http.Request {
  95. req := CreateTestHTTPRequest("PUT", "/bucket/object", nil)
  96. req.Header.Set(s3_constants.AmzServerSideEncryptionAwsKmsKeyId, "test-key-id")
  97. // Missing algorithm
  98. return req
  99. },
  100. },
  101. }
  102. for _, tc := range testCases {
  103. t.Run(tc.name, func(t *testing.T) {
  104. req := tc.setupReq()
  105. // Validate headers - should catch incomplete configurations
  106. if strings.Contains(tc.name, "SSE-C") {
  107. err := ValidateSSECHeaders(req)
  108. if err == nil {
  109. t.Error("Expected validation error for incomplete SSE-C headers")
  110. }
  111. }
  112. })
  113. }
  114. }
  115. // TestSSECInvalidKeyFormats tests various invalid SSE-C key formats
  116. func TestSSECInvalidKeyFormats(t *testing.T) {
  117. testCases := []struct {
  118. name string
  119. algorithm string
  120. key string
  121. keyMD5 string
  122. expectErr bool
  123. }{
  124. {
  125. name: "Invalid algorithm",
  126. algorithm: "AES128",
  127. key: "dGVzdGtleXRlc3RrZXl0ZXN0a2V5dGVzdGtleXRlc3RrZXk=", // 32 bytes base64
  128. keyMD5: "valid-md5-hash",
  129. expectErr: true,
  130. },
  131. {
  132. name: "Invalid key length (too short)",
  133. algorithm: "AES256",
  134. key: "c2hvcnRrZXk=", // "shortkey" base64 - too short
  135. keyMD5: "valid-md5-hash",
  136. expectErr: true,
  137. },
  138. {
  139. name: "Invalid key length (too long)",
  140. algorithm: "AES256",
  141. key: "dGVzdGtleXRlc3RrZXl0ZXN0a2V5dGVzdGtleXRlc3RrZXl0ZXN0a2V5dGVzdGtleQ==", // too long
  142. keyMD5: "valid-md5-hash",
  143. expectErr: true,
  144. },
  145. {
  146. name: "Invalid base64 key",
  147. algorithm: "AES256",
  148. key: "invalid-base64!",
  149. keyMD5: "valid-md5-hash",
  150. expectErr: true,
  151. },
  152. {
  153. name: "Invalid base64 MD5",
  154. algorithm: "AES256",
  155. key: "dGVzdGtleXRlc3RrZXl0ZXN0a2V5dGVzdGtleXRlc3RrZXk=",
  156. keyMD5: "invalid-base64!",
  157. expectErr: true,
  158. },
  159. {
  160. name: "Mismatched MD5",
  161. algorithm: "AES256",
  162. key: "dGVzdGtleXRlc3RrZXl0ZXN0a2V5dGVzdGtleXRlc3RrZXk=",
  163. keyMD5: "d29uZy1tZDUtaGFzaA==", // "wrong-md5-hash" base64
  164. expectErr: true,
  165. },
  166. }
  167. for _, tc := range testCases {
  168. t.Run(tc.name, func(t *testing.T) {
  169. req := CreateTestHTTPRequest("PUT", "/bucket/object", nil)
  170. req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerAlgorithm, tc.algorithm)
  171. req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerKey, tc.key)
  172. req.Header.Set(s3_constants.AmzServerSideEncryptionCustomerKeyMD5, tc.keyMD5)
  173. err := ValidateSSECHeaders(req)
  174. if tc.expectErr && err == nil {
  175. t.Errorf("Expected error for %s, but got none", tc.name)
  176. }
  177. if !tc.expectErr && err != nil {
  178. t.Errorf("Expected no error for %s, but got: %v", tc.name, err)
  179. }
  180. })
  181. }
  182. }
  183. // TestSSEKMSInvalidConfigurations tests various invalid SSE-KMS configurations
  184. func TestSSEKMSInvalidConfigurations(t *testing.T) {
  185. testCases := []struct {
  186. name string
  187. setupRequest func() *http.Request
  188. expectError bool
  189. }{
  190. {
  191. name: "Invalid algorithm",
  192. setupRequest: func() *http.Request {
  193. req := CreateTestHTTPRequest("PUT", "/bucket/object", nil)
  194. req.Header.Set(s3_constants.AmzServerSideEncryption, "invalid-algorithm")
  195. return req
  196. },
  197. expectError: true,
  198. },
  199. {
  200. name: "Empty key ID",
  201. setupRequest: func() *http.Request {
  202. req := CreateTestHTTPRequest("PUT", "/bucket/object", nil)
  203. req.Header.Set(s3_constants.AmzServerSideEncryption, "aws:kms")
  204. req.Header.Set(s3_constants.AmzServerSideEncryptionAwsKmsKeyId, "")
  205. return req
  206. },
  207. expectError: false, // Empty key ID might be valid (use default)
  208. },
  209. {
  210. name: "Invalid key ID format",
  211. setupRequest: func() *http.Request {
  212. req := CreateTestHTTPRequest("PUT", "/bucket/object", nil)
  213. req.Header.Set(s3_constants.AmzServerSideEncryption, "aws:kms")
  214. req.Header.Set(s3_constants.AmzServerSideEncryptionAwsKmsKeyId, "invalid key id with spaces")
  215. return req
  216. },
  217. expectError: true,
  218. },
  219. }
  220. for _, tc := range testCases {
  221. t.Run(tc.name, func(t *testing.T) {
  222. req := tc.setupRequest()
  223. _, err := ParseSSEKMSHeaders(req)
  224. if tc.expectError && err == nil {
  225. t.Errorf("Expected error for %s, but got none", tc.name)
  226. }
  227. if !tc.expectError && err != nil {
  228. t.Errorf("Expected no error for %s, but got: %v", tc.name, err)
  229. }
  230. })
  231. }
  232. }
  233. // TestSSEEmptyDataHandling tests handling of empty data with SSE
  234. func TestSSEEmptyDataHandling(t *testing.T) {
  235. t.Run("SSE-C with empty data", func(t *testing.T) {
  236. keyPair := GenerateTestSSECKey(1)
  237. customerKey := &SSECustomerKey{
  238. Algorithm: "AES256",
  239. Key: keyPair.Key,
  240. KeyMD5: keyPair.KeyMD5,
  241. }
  242. // Encrypt empty data
  243. encryptedReader, iv, err := CreateSSECEncryptedReader(strings.NewReader(""), customerKey)
  244. if err != nil {
  245. t.Fatalf("Failed to create encrypted reader for empty data: %v", err)
  246. }
  247. encryptedData, err := io.ReadAll(encryptedReader)
  248. if err != nil {
  249. t.Fatalf("Failed to read encrypted empty data: %v", err)
  250. }
  251. // Should have IV for empty data
  252. if len(iv) != s3_constants.AESBlockSize {
  253. t.Error("IV should be present even for empty data")
  254. }
  255. // Decrypt and verify
  256. decryptedReader, err := CreateSSECDecryptedReader(bytes.NewReader(encryptedData), customerKey, iv)
  257. if err != nil {
  258. t.Fatalf("Failed to create decrypted reader for empty data: %v", err)
  259. }
  260. decryptedData, err := io.ReadAll(decryptedReader)
  261. if err != nil {
  262. t.Fatalf("Failed to read decrypted empty data: %v", err)
  263. }
  264. if len(decryptedData) != 0 {
  265. t.Errorf("Expected empty decrypted data, got %d bytes", len(decryptedData))
  266. }
  267. })
  268. t.Run("SSE-KMS with empty data", func(t *testing.T) {
  269. kmsKey := SetupTestKMS(t)
  270. defer kmsKey.Cleanup()
  271. encryptionContext := BuildEncryptionContext("test-bucket", "test-object", false)
  272. // Encrypt empty data
  273. encryptedReader, sseKey, err := CreateSSEKMSEncryptedReader(strings.NewReader(""), kmsKey.KeyID, encryptionContext)
  274. if err != nil {
  275. t.Fatalf("Failed to create encrypted reader for empty data: %v", err)
  276. }
  277. encryptedData, err := io.ReadAll(encryptedReader)
  278. if err != nil {
  279. t.Fatalf("Failed to read encrypted empty data: %v", err)
  280. }
  281. // Empty data should produce empty encrypted data (IV is stored in metadata)
  282. if len(encryptedData) != 0 {
  283. t.Errorf("Encrypted empty data should be empty, got %d bytes", len(encryptedData))
  284. }
  285. // Decrypt and verify
  286. decryptedReader, err := CreateSSEKMSDecryptedReader(bytes.NewReader(encryptedData), sseKey)
  287. if err != nil {
  288. t.Fatalf("Failed to create decrypted reader for empty data: %v", err)
  289. }
  290. decryptedData, err := io.ReadAll(decryptedReader)
  291. if err != nil {
  292. t.Fatalf("Failed to read decrypted empty data: %v", err)
  293. }
  294. if len(decryptedData) != 0 {
  295. t.Errorf("Expected empty decrypted data, got %d bytes", len(decryptedData))
  296. }
  297. })
  298. }
  299. // TestSSEConcurrentAccess tests SSE operations under concurrent access
  300. func TestSSEConcurrentAccess(t *testing.T) {
  301. keyPair := GenerateTestSSECKey(1)
  302. customerKey := &SSECustomerKey{
  303. Algorithm: "AES256",
  304. Key: keyPair.Key,
  305. KeyMD5: keyPair.KeyMD5,
  306. }
  307. const numGoroutines = 10
  308. done := make(chan bool, numGoroutines)
  309. errors := make(chan error, numGoroutines)
  310. // Run multiple encryption/decryption operations concurrently
  311. for i := 0; i < numGoroutines; i++ {
  312. go func(id int) {
  313. defer func() { done <- true }()
  314. testData := fmt.Sprintf("test data %d", id)
  315. // Encrypt
  316. encryptedReader, iv, err := CreateSSECEncryptedReader(strings.NewReader(testData), customerKey)
  317. if err != nil {
  318. errors <- fmt.Errorf("goroutine %d encrypt error: %v", id, err)
  319. return
  320. }
  321. encryptedData, err := io.ReadAll(encryptedReader)
  322. if err != nil {
  323. errors <- fmt.Errorf("goroutine %d read encrypted error: %v", id, err)
  324. return
  325. }
  326. // Decrypt
  327. decryptedReader, err := CreateSSECDecryptedReader(bytes.NewReader(encryptedData), customerKey, iv)
  328. if err != nil {
  329. errors <- fmt.Errorf("goroutine %d decrypt error: %v", id, err)
  330. return
  331. }
  332. decryptedData, err := io.ReadAll(decryptedReader)
  333. if err != nil {
  334. errors <- fmt.Errorf("goroutine %d read decrypted error: %v", id, err)
  335. return
  336. }
  337. if string(decryptedData) != testData {
  338. errors <- fmt.Errorf("goroutine %d data mismatch: expected %s, got %s", id, testData, string(decryptedData))
  339. return
  340. }
  341. }(i)
  342. }
  343. // Wait for all goroutines to complete
  344. for i := 0; i < numGoroutines; i++ {
  345. <-done
  346. }
  347. // Check for errors
  348. close(errors)
  349. for err := range errors {
  350. t.Error(err)
  351. }
  352. }