s3_sse_bucket_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. package s3api
  2. import (
  3. "fmt"
  4. "strings"
  5. "testing"
  6. "github.com/seaweedfs/seaweedfs/weed/pb/s3_pb"
  7. )
  8. // TestBucketDefaultSSEKMSEnforcement tests bucket default encryption enforcement
  9. func TestBucketDefaultSSEKMSEnforcement(t *testing.T) {
  10. kmsKey := SetupTestKMS(t)
  11. defer kmsKey.Cleanup()
  12. // Create bucket encryption configuration
  13. config := &s3_pb.EncryptionConfiguration{
  14. SseAlgorithm: "aws:kms",
  15. KmsKeyId: kmsKey.KeyID,
  16. BucketKeyEnabled: false,
  17. }
  18. t.Run("Bucket with SSE-KMS default encryption", func(t *testing.T) {
  19. // Test that default encryption config is properly stored and retrieved
  20. if config.SseAlgorithm != "aws:kms" {
  21. t.Errorf("Expected SSE algorithm aws:kms, got %s", config.SseAlgorithm)
  22. }
  23. if config.KmsKeyId != kmsKey.KeyID {
  24. t.Errorf("Expected KMS key ID %s, got %s", kmsKey.KeyID, config.KmsKeyId)
  25. }
  26. })
  27. t.Run("Default encryption headers generation", func(t *testing.T) {
  28. // Test generating default encryption headers for objects
  29. headers := GetDefaultEncryptionHeaders(config)
  30. if headers == nil {
  31. t.Fatal("Expected default headers, got nil")
  32. }
  33. expectedAlgorithm := headers["X-Amz-Server-Side-Encryption"]
  34. if expectedAlgorithm != "aws:kms" {
  35. t.Errorf("Expected X-Amz-Server-Side-Encryption header aws:kms, got %s", expectedAlgorithm)
  36. }
  37. expectedKeyID := headers["X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id"]
  38. if expectedKeyID != kmsKey.KeyID {
  39. t.Errorf("Expected X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id header %s, got %s", kmsKey.KeyID, expectedKeyID)
  40. }
  41. })
  42. t.Run("Default encryption detection", func(t *testing.T) {
  43. // Test IsDefaultEncryptionEnabled
  44. enabled := IsDefaultEncryptionEnabled(config)
  45. if !enabled {
  46. t.Error("Should detect default encryption as enabled")
  47. }
  48. // Test with nil config
  49. enabled = IsDefaultEncryptionEnabled(nil)
  50. if enabled {
  51. t.Error("Should detect default encryption as disabled for nil config")
  52. }
  53. // Test with empty config
  54. emptyConfig := &s3_pb.EncryptionConfiguration{}
  55. enabled = IsDefaultEncryptionEnabled(emptyConfig)
  56. if enabled {
  57. t.Error("Should detect default encryption as disabled for empty config")
  58. }
  59. })
  60. }
  61. // TestBucketEncryptionConfigValidation tests XML validation of bucket encryption configurations
  62. func TestBucketEncryptionConfigValidation(t *testing.T) {
  63. testCases := []struct {
  64. name string
  65. xml string
  66. expectError bool
  67. description string
  68. }{
  69. {
  70. name: "Valid SSE-S3 configuration",
  71. xml: `<ServerSideEncryptionConfiguration>
  72. <Rule>
  73. <ApplyServerSideEncryptionByDefault>
  74. <SSEAlgorithm>AES256</SSEAlgorithm>
  75. </ApplyServerSideEncryptionByDefault>
  76. </Rule>
  77. </ServerSideEncryptionConfiguration>`,
  78. expectError: false,
  79. description: "Basic SSE-S3 configuration should be valid",
  80. },
  81. {
  82. name: "Valid SSE-KMS configuration",
  83. xml: `<ServerSideEncryptionConfiguration>
  84. <Rule>
  85. <ApplyServerSideEncryptionByDefault>
  86. <SSEAlgorithm>aws:kms</SSEAlgorithm>
  87. <KMSMasterKeyID>test-key-id</KMSMasterKeyID>
  88. </ApplyServerSideEncryptionByDefault>
  89. </Rule>
  90. </ServerSideEncryptionConfiguration>`,
  91. expectError: false,
  92. description: "SSE-KMS configuration with key ID should be valid",
  93. },
  94. {
  95. name: "Valid SSE-KMS without key ID",
  96. xml: `<ServerSideEncryptionConfiguration>
  97. <Rule>
  98. <ApplyServerSideEncryptionByDefault>
  99. <SSEAlgorithm>aws:kms</SSEAlgorithm>
  100. </ApplyServerSideEncryptionByDefault>
  101. </Rule>
  102. </ServerSideEncryptionConfiguration>`,
  103. expectError: false,
  104. description: "SSE-KMS without key ID should use default key",
  105. },
  106. {
  107. name: "Invalid XML structure",
  108. xml: `<ServerSideEncryptionConfiguration>
  109. <InvalidRule>
  110. <SSEAlgorithm>AES256</SSEAlgorithm>
  111. </InvalidRule>
  112. </ServerSideEncryptionConfiguration>`,
  113. expectError: true,
  114. description: "Invalid XML structure should be rejected",
  115. },
  116. {
  117. name: "Empty configuration",
  118. xml: `<ServerSideEncryptionConfiguration>
  119. </ServerSideEncryptionConfiguration>`,
  120. expectError: true,
  121. description: "Empty configuration should be rejected",
  122. },
  123. {
  124. name: "Invalid algorithm",
  125. xml: `<ServerSideEncryptionConfiguration>
  126. <Rule>
  127. <ApplyServerSideEncryptionByDefault>
  128. <SSEAlgorithm>INVALID</SSEAlgorithm>
  129. </ApplyServerSideEncryptionByDefault>
  130. </Rule>
  131. </ServerSideEncryptionConfiguration>`,
  132. expectError: true,
  133. description: "Invalid algorithm should be rejected",
  134. },
  135. }
  136. for _, tc := range testCases {
  137. t.Run(tc.name, func(t *testing.T) {
  138. config, err := encryptionConfigFromXMLBytes([]byte(tc.xml))
  139. if tc.expectError && err == nil {
  140. t.Errorf("Expected error for %s, but got none. %s", tc.name, tc.description)
  141. }
  142. if !tc.expectError && err != nil {
  143. t.Errorf("Expected no error for %s, but got: %v. %s", tc.name, err, tc.description)
  144. }
  145. if !tc.expectError && config != nil {
  146. // Validate the parsed configuration
  147. t.Logf("Successfully parsed config: Algorithm=%s, KeyID=%s",
  148. config.SseAlgorithm, config.KmsKeyId)
  149. }
  150. })
  151. }
  152. }
  153. // TestBucketEncryptionAPIOperations tests the bucket encryption API operations
  154. func TestBucketEncryptionAPIOperations(t *testing.T) {
  155. // Note: These tests would normally require a full S3 API server setup
  156. // For now, we test the individual components
  157. t.Run("PUT bucket encryption", func(t *testing.T) {
  158. xml := `<ServerSideEncryptionConfiguration>
  159. <Rule>
  160. <ApplyServerSideEncryptionByDefault>
  161. <SSEAlgorithm>aws:kms</SSEAlgorithm>
  162. <KMSMasterKeyID>test-key-id</KMSMasterKeyID>
  163. </ApplyServerSideEncryptionByDefault>
  164. </Rule>
  165. </ServerSideEncryptionConfiguration>`
  166. // Parse the XML to protobuf
  167. config, err := encryptionConfigFromXMLBytes([]byte(xml))
  168. if err != nil {
  169. t.Fatalf("Failed to parse encryption config: %v", err)
  170. }
  171. // Verify the parsed configuration
  172. if config.SseAlgorithm != "aws:kms" {
  173. t.Errorf("Expected algorithm aws:kms, got %s", config.SseAlgorithm)
  174. }
  175. if config.KmsKeyId != "test-key-id" {
  176. t.Errorf("Expected key ID test-key-id, got %s", config.KmsKeyId)
  177. }
  178. // Convert back to XML
  179. xmlBytes, err := encryptionConfigToXMLBytes(config)
  180. if err != nil {
  181. t.Fatalf("Failed to convert config to XML: %v", err)
  182. }
  183. // Verify round-trip
  184. if len(xmlBytes) == 0 {
  185. t.Error("Generated XML should not be empty")
  186. }
  187. // Parse again to verify
  188. roundTripConfig, err := encryptionConfigFromXMLBytes(xmlBytes)
  189. if err != nil {
  190. t.Fatalf("Failed to parse round-trip XML: %v", err)
  191. }
  192. if roundTripConfig.SseAlgorithm != config.SseAlgorithm {
  193. t.Error("Round-trip algorithm doesn't match")
  194. }
  195. if roundTripConfig.KmsKeyId != config.KmsKeyId {
  196. t.Error("Round-trip key ID doesn't match")
  197. }
  198. })
  199. t.Run("GET bucket encryption", func(t *testing.T) {
  200. // Test getting encryption configuration
  201. config := &s3_pb.EncryptionConfiguration{
  202. SseAlgorithm: "AES256",
  203. KmsKeyId: "",
  204. BucketKeyEnabled: false,
  205. }
  206. // Convert to XML for GET response
  207. xmlBytes, err := encryptionConfigToXMLBytes(config)
  208. if err != nil {
  209. t.Fatalf("Failed to convert config to XML: %v", err)
  210. }
  211. if len(xmlBytes) == 0 {
  212. t.Error("Generated XML should not be empty")
  213. }
  214. // Verify XML contains expected elements
  215. xmlStr := string(xmlBytes)
  216. if !strings.Contains(xmlStr, "AES256") {
  217. t.Error("XML should contain AES256 algorithm")
  218. }
  219. })
  220. t.Run("DELETE bucket encryption", func(t *testing.T) {
  221. // Test deleting encryption configuration
  222. // This would typically involve removing the configuration from metadata
  223. // Simulate checking if encryption is enabled after deletion
  224. enabled := IsDefaultEncryptionEnabled(nil)
  225. if enabled {
  226. t.Error("Encryption should be disabled after deletion")
  227. }
  228. })
  229. }
  230. // TestBucketEncryptionEdgeCases tests edge cases in bucket encryption
  231. func TestBucketEncryptionEdgeCases(t *testing.T) {
  232. t.Run("Large XML configuration", func(t *testing.T) {
  233. // Test with a large but valid XML
  234. largeXML := `<ServerSideEncryptionConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  235. <Rule>
  236. <ApplyServerSideEncryptionByDefault>
  237. <SSEAlgorithm>aws:kms</SSEAlgorithm>
  238. <KMSMasterKeyID>arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012</KMSMasterKeyID>
  239. </ApplyServerSideEncryptionByDefault>
  240. <BucketKeyEnabled>true</BucketKeyEnabled>
  241. </Rule>
  242. </ServerSideEncryptionConfiguration>`
  243. config, err := encryptionConfigFromXMLBytes([]byte(largeXML))
  244. if err != nil {
  245. t.Fatalf("Failed to parse large XML: %v", err)
  246. }
  247. if config.SseAlgorithm != "aws:kms" {
  248. t.Error("Should parse large XML correctly")
  249. }
  250. })
  251. t.Run("XML with namespaces", func(t *testing.T) {
  252. // Test XML with namespaces
  253. namespacedXML := `<ServerSideEncryptionConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
  254. <Rule>
  255. <ApplyServerSideEncryptionByDefault>
  256. <SSEAlgorithm>AES256</SSEAlgorithm>
  257. </ApplyServerSideEncryptionByDefault>
  258. </Rule>
  259. </ServerSideEncryptionConfiguration>`
  260. config, err := encryptionConfigFromXMLBytes([]byte(namespacedXML))
  261. if err != nil {
  262. t.Fatalf("Failed to parse namespaced XML: %v", err)
  263. }
  264. if config.SseAlgorithm != "AES256" {
  265. t.Error("Should parse namespaced XML correctly")
  266. }
  267. })
  268. t.Run("Malformed XML", func(t *testing.T) {
  269. malformedXMLs := []string{
  270. `<ServerSideEncryptionConfiguration><Rule><SSEAlgorithm>AES256</Rule>`, // Unclosed tags
  271. `<ServerSideEncryptionConfiguration><Rule></Rule></ServerSideEncryptionConfiguration>`, // Empty rule
  272. `not-xml-at-all`, // Not XML
  273. `<ServerSideEncryptionConfiguration xmlns="invalid-namespace"><Rule><ApplyServerSideEncryptionByDefault><SSEAlgorithm>AES256</SSEAlgorithm></ApplyServerSideEncryptionByDefault></Rule></ServerSideEncryptionConfiguration>`, // Invalid namespace
  274. }
  275. for i, malformedXML := range malformedXMLs {
  276. t.Run(fmt.Sprintf("Malformed XML %d", i), func(t *testing.T) {
  277. _, err := encryptionConfigFromXMLBytes([]byte(malformedXML))
  278. if err == nil {
  279. t.Errorf("Expected error for malformed XML %d, but got none", i)
  280. }
  281. })
  282. }
  283. })
  284. }
  285. // TestGetDefaultEncryptionHeaders tests generation of default encryption headers
  286. func TestGetDefaultEncryptionHeaders(t *testing.T) {
  287. testCases := []struct {
  288. name string
  289. config *s3_pb.EncryptionConfiguration
  290. expectedHeaders map[string]string
  291. }{
  292. {
  293. name: "Nil configuration",
  294. config: nil,
  295. expectedHeaders: nil,
  296. },
  297. {
  298. name: "SSE-S3 configuration",
  299. config: &s3_pb.EncryptionConfiguration{
  300. SseAlgorithm: "AES256",
  301. },
  302. expectedHeaders: map[string]string{
  303. "X-Amz-Server-Side-Encryption": "AES256",
  304. },
  305. },
  306. {
  307. name: "SSE-KMS configuration with key",
  308. config: &s3_pb.EncryptionConfiguration{
  309. SseAlgorithm: "aws:kms",
  310. KmsKeyId: "test-key-id",
  311. },
  312. expectedHeaders: map[string]string{
  313. "X-Amz-Server-Side-Encryption": "aws:kms",
  314. "X-Amz-Server-Side-Encryption-Aws-Kms-Key-Id": "test-key-id",
  315. },
  316. },
  317. {
  318. name: "SSE-KMS configuration without key",
  319. config: &s3_pb.EncryptionConfiguration{
  320. SseAlgorithm: "aws:kms",
  321. },
  322. expectedHeaders: map[string]string{
  323. "X-Amz-Server-Side-Encryption": "aws:kms",
  324. },
  325. },
  326. }
  327. for _, tc := range testCases {
  328. t.Run(tc.name, func(t *testing.T) {
  329. headers := GetDefaultEncryptionHeaders(tc.config)
  330. if tc.expectedHeaders == nil && headers != nil {
  331. t.Error("Expected nil headers but got some")
  332. }
  333. if tc.expectedHeaders != nil && headers == nil {
  334. t.Error("Expected headers but got nil")
  335. }
  336. if tc.expectedHeaders != nil && headers != nil {
  337. for key, expectedValue := range tc.expectedHeaders {
  338. if actualValue, exists := headers[key]; !exists {
  339. t.Errorf("Expected header %s not found", key)
  340. } else if actualValue != expectedValue {
  341. t.Errorf("Header %s: expected %s, got %s", key, expectedValue, actualValue)
  342. }
  343. }
  344. // Check for unexpected headers
  345. for key := range headers {
  346. if _, expected := tc.expectedHeaders[key]; !expected {
  347. t.Errorf("Unexpected header found: %s", key)
  348. }
  349. }
  350. }
  351. })
  352. }
  353. }