You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							328 lines
						
					
					
						
							8.4 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							328 lines
						
					
					
						
							8.4 KiB
						
					
					
				
								package s3api
							 | 
						|
								
							 | 
						|
								import (
							 | 
						|
									"testing"
							 | 
						|
								
							 | 
						|
									"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
							 | 
						|
								)
							 | 
						|
								
							 | 
						|
								// TestSSECIsEncrypted tests detection of SSE-C encryption from metadata
							 | 
						|
								func TestSSECIsEncrypted(t *testing.T) {
							 | 
						|
									testCases := []struct {
							 | 
						|
										name     string
							 | 
						|
										metadata map[string][]byte
							 | 
						|
										expected bool
							 | 
						|
									}{
							 | 
						|
										{
							 | 
						|
											name:     "Empty metadata",
							 | 
						|
											metadata: CreateTestMetadata(),
							 | 
						|
											expected: false,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:     "Valid SSE-C metadata",
							 | 
						|
											metadata: CreateTestMetadataWithSSEC(GenerateTestSSECKey(1)),
							 | 
						|
											expected: true,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "SSE-C algorithm only",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryptionCustomerAlgorithm: []byte("AES256"),
							 | 
						|
											},
							 | 
						|
											expected: true,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "SSE-C key MD5 only",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryptionCustomerKeyMD5: []byte("somemd5"),
							 | 
						|
											},
							 | 
						|
											expected: true,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "Other encryption type (SSE-KMS)",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
							 | 
						|
											},
							 | 
						|
											expected: false,
							 | 
						|
										},
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for _, tc := range testCases {
							 | 
						|
										t.Run(tc.name, func(t *testing.T) {
							 | 
						|
											result := IsSSECEncrypted(tc.metadata)
							 | 
						|
											if result != tc.expected {
							 | 
						|
												t.Errorf("Expected %v, got %v", tc.expected, result)
							 | 
						|
											}
							 | 
						|
										})
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// TestSSEKMSIsEncrypted tests detection of SSE-KMS encryption from metadata
							 | 
						|
								func TestSSEKMSIsEncrypted(t *testing.T) {
							 | 
						|
									testCases := []struct {
							 | 
						|
										name     string
							 | 
						|
										metadata map[string][]byte
							 | 
						|
										expected bool
							 | 
						|
									}{
							 | 
						|
										{
							 | 
						|
											name:     "Empty metadata",
							 | 
						|
											metadata: CreateTestMetadata(),
							 | 
						|
											expected: false,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "Valid SSE-KMS metadata",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
							 | 
						|
												s3_constants.AmzEncryptedDataKey:     []byte("encrypted-key"),
							 | 
						|
											},
							 | 
						|
											expected: true,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "SSE-KMS algorithm only",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
							 | 
						|
											},
							 | 
						|
											expected: true,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "SSE-KMS encrypted data key only",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzEncryptedDataKey: []byte("encrypted-key"),
							 | 
						|
											},
							 | 
						|
											expected: false, // Only encrypted data key without algorithm header should not be considered SSE-KMS
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "Other encryption type (SSE-C)",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryptionCustomerAlgorithm: []byte("AES256"),
							 | 
						|
											},
							 | 
						|
											expected: false,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "SSE-S3 (AES256)",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryption: []byte("AES256"),
							 | 
						|
											},
							 | 
						|
											expected: false,
							 | 
						|
										},
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for _, tc := range testCases {
							 | 
						|
										t.Run(tc.name, func(t *testing.T) {
							 | 
						|
											result := IsSSEKMSEncrypted(tc.metadata)
							 | 
						|
											if result != tc.expected {
							 | 
						|
												t.Errorf("Expected %v, got %v", tc.expected, result)
							 | 
						|
											}
							 | 
						|
										})
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// TestSSETypeDiscrimination tests that SSE types don't interfere with each other
							 | 
						|
								func TestSSETypeDiscrimination(t *testing.T) {
							 | 
						|
									// Test SSE-C headers don't trigger SSE-KMS detection
							 | 
						|
									t.Run("SSE-C headers don't trigger SSE-KMS", func(t *testing.T) {
							 | 
						|
										req := CreateTestHTTPRequest("PUT", "/bucket/object", nil)
							 | 
						|
										keyPair := GenerateTestSSECKey(1)
							 | 
						|
										SetupTestSSECHeaders(req, keyPair)
							 | 
						|
								
							 | 
						|
										// Should detect SSE-C, not SSE-KMS
							 | 
						|
										if !IsSSECRequest(req) {
							 | 
						|
											t.Error("Should detect SSE-C request")
							 | 
						|
										}
							 | 
						|
										if IsSSEKMSRequest(req) {
							 | 
						|
											t.Error("Should not detect SSE-KMS request for SSE-C headers")
							 | 
						|
										}
							 | 
						|
									})
							 | 
						|
								
							 | 
						|
									// Test SSE-KMS headers don't trigger SSE-C detection
							 | 
						|
									t.Run("SSE-KMS headers don't trigger SSE-C", func(t *testing.T) {
							 | 
						|
										req := CreateTestHTTPRequest("PUT", "/bucket/object", nil)
							 | 
						|
										SetupTestSSEKMSHeaders(req, "test-key-id")
							 | 
						|
								
							 | 
						|
										// Should detect SSE-KMS, not SSE-C
							 | 
						|
										if IsSSECRequest(req) {
							 | 
						|
											t.Error("Should not detect SSE-C request for SSE-KMS headers")
							 | 
						|
										}
							 | 
						|
										if !IsSSEKMSRequest(req) {
							 | 
						|
											t.Error("Should detect SSE-KMS request")
							 | 
						|
										}
							 | 
						|
									})
							 | 
						|
								
							 | 
						|
									// Test metadata discrimination
							 | 
						|
									t.Run("Metadata type discrimination", func(t *testing.T) {
							 | 
						|
										ssecMetadata := CreateTestMetadataWithSSEC(GenerateTestSSECKey(1))
							 | 
						|
								
							 | 
						|
										// Should detect as SSE-C, not SSE-KMS
							 | 
						|
										if !IsSSECEncrypted(ssecMetadata) {
							 | 
						|
											t.Error("Should detect SSE-C encrypted metadata")
							 | 
						|
										}
							 | 
						|
										if IsSSEKMSEncrypted(ssecMetadata) {
							 | 
						|
											t.Error("Should not detect SSE-KMS for SSE-C metadata")
							 | 
						|
										}
							 | 
						|
									})
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// TestSSECParseCorruptedMetadata tests handling of corrupted SSE-C metadata
							 | 
						|
								func TestSSECParseCorruptedMetadata(t *testing.T) {
							 | 
						|
									testCases := []struct {
							 | 
						|
										name         string
							 | 
						|
										metadata     map[string][]byte
							 | 
						|
										expectError  bool
							 | 
						|
										errorMessage string
							 | 
						|
									}{
							 | 
						|
										{
							 | 
						|
											name: "Missing algorithm",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryptionCustomerKeyMD5: []byte("valid-md5"),
							 | 
						|
											},
							 | 
						|
											expectError: false, // Detection should still work with partial metadata
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "Invalid key MD5 format",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryptionCustomerAlgorithm: []byte("AES256"),
							 | 
						|
												s3_constants.AmzServerSideEncryptionCustomerKeyMD5:    []byte("invalid-base64!"),
							 | 
						|
											},
							 | 
						|
											expectError: false, // Detection should work, validation happens later
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "Empty values",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryptionCustomerAlgorithm: []byte(""),
							 | 
						|
												s3_constants.AmzServerSideEncryptionCustomerKeyMD5:    []byte(""),
							 | 
						|
											},
							 | 
						|
											expectError: false,
							 | 
						|
										},
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for _, tc := range testCases {
							 | 
						|
										t.Run(tc.name, func(t *testing.T) {
							 | 
						|
											// Test that detection doesn't panic on corrupted metadata
							 | 
						|
											result := IsSSECEncrypted(tc.metadata)
							 | 
						|
											// The detection should be robust and not crash
							 | 
						|
											t.Logf("Detection result for %s: %v", tc.name, result)
							 | 
						|
										})
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// TestSSEKMSParseCorruptedMetadata tests handling of corrupted SSE-KMS metadata
							 | 
						|
								func TestSSEKMSParseCorruptedMetadata(t *testing.T) {
							 | 
						|
									testCases := []struct {
							 | 
						|
										name     string
							 | 
						|
										metadata map[string][]byte
							 | 
						|
									}{
							 | 
						|
										{
							 | 
						|
											name: "Invalid encrypted data key",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
							 | 
						|
												s3_constants.AmzEncryptedDataKey:     []byte("invalid-base64!"),
							 | 
						|
											},
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "Invalid encryption context",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryption:  []byte("aws:kms"),
							 | 
						|
												s3_constants.AmzEncryptionContextMeta: []byte("invalid-json"),
							 | 
						|
											},
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "Empty values",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryption: []byte(""),
							 | 
						|
												s3_constants.AmzEncryptedDataKey:     []byte(""),
							 | 
						|
											},
							 | 
						|
										},
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for _, tc := range testCases {
							 | 
						|
										t.Run(tc.name, func(t *testing.T) {
							 | 
						|
											// Test that detection doesn't panic on corrupted metadata
							 | 
						|
											result := IsSSEKMSEncrypted(tc.metadata)
							 | 
						|
											t.Logf("Detection result for %s: %v", tc.name, result)
							 | 
						|
										})
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// TestSSEMetadataDeserialization tests SSE-KMS metadata deserialization with various inputs
							 | 
						|
								func TestSSEMetadataDeserialization(t *testing.T) {
							 | 
						|
									testCases := []struct {
							 | 
						|
										name        string
							 | 
						|
										data        []byte
							 | 
						|
										expectError bool
							 | 
						|
									}{
							 | 
						|
										{
							 | 
						|
											name:        "Empty data",
							 | 
						|
											data:        []byte{},
							 | 
						|
											expectError: true,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Invalid JSON",
							 | 
						|
											data:        []byte("invalid-json"),
							 | 
						|
											expectError: true,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Valid JSON but wrong structure",
							 | 
						|
											data:        []byte(`{"wrong": "structure"}`),
							 | 
						|
											expectError: false, // Our deserialization might be lenient
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:        "Null data",
							 | 
						|
											data:        nil,
							 | 
						|
											expectError: true,
							 | 
						|
										},
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for _, tc := range testCases {
							 | 
						|
										t.Run(tc.name, func(t *testing.T) {
							 | 
						|
											_, err := DeserializeSSEKMSMetadata(tc.data)
							 | 
						|
											if tc.expectError && err == nil {
							 | 
						|
												t.Error("Expected error but got none")
							 | 
						|
											}
							 | 
						|
											if !tc.expectError && err != nil {
							 | 
						|
												t.Errorf("Expected no error but got: %v", err)
							 | 
						|
											}
							 | 
						|
										})
							 | 
						|
									}
							 | 
						|
								}
							 | 
						|
								
							 | 
						|
								// TestGeneralSSEDetection tests the general SSE detection that works across types
							 | 
						|
								func TestGeneralSSEDetection(t *testing.T) {
							 | 
						|
									testCases := []struct {
							 | 
						|
										name     string
							 | 
						|
										metadata map[string][]byte
							 | 
						|
										expected bool
							 | 
						|
									}{
							 | 
						|
										{
							 | 
						|
											name:     "No encryption",
							 | 
						|
											metadata: CreateTestMetadata(),
							 | 
						|
											expected: false,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name:     "SSE-C encrypted",
							 | 
						|
											metadata: CreateTestMetadataWithSSEC(GenerateTestSSECKey(1)),
							 | 
						|
											expected: true,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "SSE-KMS encrypted",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
							 | 
						|
											},
							 | 
						|
											expected: true,
							 | 
						|
										},
							 | 
						|
										{
							 | 
						|
											name: "SSE-S3 encrypted",
							 | 
						|
											metadata: map[string][]byte{
							 | 
						|
												s3_constants.AmzServerSideEncryption: []byte("AES256"),
							 | 
						|
											},
							 | 
						|
											expected: true,
							 | 
						|
										},
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									for _, tc := range testCases {
							 | 
						|
										t.Run(tc.name, func(t *testing.T) {
							 | 
						|
											result := IsAnySSEEncrypted(tc.metadata)
							 | 
						|
											if result != tc.expected {
							 | 
						|
												t.Errorf("Expected %v, got %v", tc.expected, result)
							 | 
						|
											}
							 | 
						|
										})
							 | 
						|
									}
							 | 
						|
								}
							 |