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.
628 lines
18 KiB
628 lines
18 KiB
package s3api
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
|
|
)
|
|
|
|
// TestSSECObjectCopy tests copying SSE-C encrypted objects with different keys
|
|
func TestSSECObjectCopy(t *testing.T) {
|
|
// Original key for source object
|
|
sourceKey := GenerateTestSSECKey(1)
|
|
sourceCustomerKey := &SSECustomerKey{
|
|
Algorithm: "AES256",
|
|
Key: sourceKey.Key,
|
|
KeyMD5: sourceKey.KeyMD5,
|
|
}
|
|
|
|
// Destination key for target object
|
|
destKey := GenerateTestSSECKey(2)
|
|
destCustomerKey := &SSECustomerKey{
|
|
Algorithm: "AES256",
|
|
Key: destKey.Key,
|
|
KeyMD5: destKey.KeyMD5,
|
|
}
|
|
|
|
testData := "Hello, SSE-C copy world!"
|
|
|
|
// Encrypt with source key
|
|
encryptedReader, iv, err := CreateSSECEncryptedReader(strings.NewReader(testData), sourceCustomerKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create encrypted reader: %v", err)
|
|
}
|
|
|
|
encryptedData, err := io.ReadAll(encryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read encrypted data: %v", err)
|
|
}
|
|
|
|
// Test copy strategy determination
|
|
sourceMetadata := make(map[string][]byte)
|
|
StoreIVInMetadata(sourceMetadata, iv)
|
|
sourceMetadata[s3_constants.AmzServerSideEncryptionCustomerAlgorithm] = []byte("AES256")
|
|
sourceMetadata[s3_constants.AmzServerSideEncryptionCustomerKeyMD5] = []byte(sourceKey.KeyMD5)
|
|
|
|
t.Run("Same key copy (direct copy)", func(t *testing.T) {
|
|
strategy, err := DetermineSSECCopyStrategy(sourceMetadata, sourceCustomerKey, sourceCustomerKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to determine copy strategy: %v", err)
|
|
}
|
|
|
|
if strategy != SSECCopyStrategyDirect {
|
|
t.Errorf("Expected direct copy strategy for same key, got %v", strategy)
|
|
}
|
|
})
|
|
|
|
t.Run("Different key copy (decrypt-encrypt)", func(t *testing.T) {
|
|
strategy, err := DetermineSSECCopyStrategy(sourceMetadata, sourceCustomerKey, destCustomerKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to determine copy strategy: %v", err)
|
|
}
|
|
|
|
if strategy != SSECCopyStrategyDecryptEncrypt {
|
|
t.Errorf("Expected decrypt-encrypt copy strategy for different keys, got %v", strategy)
|
|
}
|
|
})
|
|
|
|
t.Run("Can direct copy check", func(t *testing.T) {
|
|
// Same key should allow direct copy
|
|
canDirect := CanDirectCopySSEC(sourceMetadata, sourceCustomerKey, sourceCustomerKey)
|
|
if !canDirect {
|
|
t.Error("Should allow direct copy with same key")
|
|
}
|
|
|
|
// Different key should not allow direct copy
|
|
canDirect = CanDirectCopySSEC(sourceMetadata, sourceCustomerKey, destCustomerKey)
|
|
if canDirect {
|
|
t.Error("Should not allow direct copy with different keys")
|
|
}
|
|
})
|
|
|
|
// Test actual copy operation (decrypt with source key, encrypt with dest key)
|
|
t.Run("Full copy operation", func(t *testing.T) {
|
|
// Decrypt with source key
|
|
decryptedReader, err := CreateSSECDecryptedReader(bytes.NewReader(encryptedData), sourceCustomerKey, iv)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create decrypted reader: %v", err)
|
|
}
|
|
|
|
// Re-encrypt with destination key
|
|
reEncryptedReader, destIV, err := CreateSSECEncryptedReader(decryptedReader, destCustomerKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create re-encrypted reader: %v", err)
|
|
}
|
|
|
|
reEncryptedData, err := io.ReadAll(reEncryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read re-encrypted data: %v", err)
|
|
}
|
|
|
|
// Verify we can decrypt with destination key
|
|
finalDecryptedReader, err := CreateSSECDecryptedReader(bytes.NewReader(reEncryptedData), destCustomerKey, destIV)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create final decrypted reader: %v", err)
|
|
}
|
|
|
|
finalData, err := io.ReadAll(finalDecryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read final decrypted data: %v", err)
|
|
}
|
|
|
|
if string(finalData) != testData {
|
|
t.Errorf("Expected %s, got %s", testData, string(finalData))
|
|
}
|
|
})
|
|
}
|
|
|
|
// TestSSEKMSObjectCopy tests copying SSE-KMS encrypted objects
|
|
func TestSSEKMSObjectCopy(t *testing.T) {
|
|
kmsKey := SetupTestKMS(t)
|
|
defer kmsKey.Cleanup()
|
|
|
|
testData := "Hello, SSE-KMS copy world!"
|
|
encryptionContext := BuildEncryptionContext("test-bucket", "test-object", false)
|
|
|
|
// Encrypt with SSE-KMS
|
|
encryptedReader, sseKey, err := CreateSSEKMSEncryptedReader(strings.NewReader(testData), kmsKey.KeyID, encryptionContext)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create encrypted reader: %v", err)
|
|
}
|
|
|
|
encryptedData, err := io.ReadAll(encryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read encrypted data: %v", err)
|
|
}
|
|
|
|
t.Run("Same KMS key copy", func(t *testing.T) {
|
|
// Decrypt with original key
|
|
decryptedReader, err := CreateSSEKMSDecryptedReader(bytes.NewReader(encryptedData), sseKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create decrypted reader: %v", err)
|
|
}
|
|
|
|
// Re-encrypt with same KMS key
|
|
reEncryptedReader, newSseKey, err := CreateSSEKMSEncryptedReader(decryptedReader, kmsKey.KeyID, encryptionContext)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create re-encrypted reader: %v", err)
|
|
}
|
|
|
|
reEncryptedData, err := io.ReadAll(reEncryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read re-encrypted data: %v", err)
|
|
}
|
|
|
|
// Verify we can decrypt with new key
|
|
finalDecryptedReader, err := CreateSSEKMSDecryptedReader(bytes.NewReader(reEncryptedData), newSseKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create final decrypted reader: %v", err)
|
|
}
|
|
|
|
finalData, err := io.ReadAll(finalDecryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read final decrypted data: %v", err)
|
|
}
|
|
|
|
if string(finalData) != testData {
|
|
t.Errorf("Expected %s, got %s", testData, string(finalData))
|
|
}
|
|
})
|
|
}
|
|
|
|
// TestSSECToSSEKMSCopy tests cross-encryption copy (SSE-C to SSE-KMS)
|
|
func TestSSECToSSEKMSCopy(t *testing.T) {
|
|
// Setup SSE-C key
|
|
ssecKey := GenerateTestSSECKey(1)
|
|
ssecCustomerKey := &SSECustomerKey{
|
|
Algorithm: "AES256",
|
|
Key: ssecKey.Key,
|
|
KeyMD5: ssecKey.KeyMD5,
|
|
}
|
|
|
|
// Setup SSE-KMS
|
|
kmsKey := SetupTestKMS(t)
|
|
defer kmsKey.Cleanup()
|
|
|
|
testData := "Hello, cross-encryption copy world!"
|
|
|
|
// Encrypt with SSE-C
|
|
encryptedReader, ssecIV, err := CreateSSECEncryptedReader(strings.NewReader(testData), ssecCustomerKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-C encrypted reader: %v", err)
|
|
}
|
|
|
|
encryptedData, err := io.ReadAll(encryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read SSE-C encrypted data: %v", err)
|
|
}
|
|
|
|
// Decrypt SSE-C data
|
|
decryptedReader, err := CreateSSECDecryptedReader(bytes.NewReader(encryptedData), ssecCustomerKey, ssecIV)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-C decrypted reader: %v", err)
|
|
}
|
|
|
|
// Re-encrypt with SSE-KMS
|
|
encryptionContext := BuildEncryptionContext("test-bucket", "test-object", false)
|
|
reEncryptedReader, sseKmsKey, err := CreateSSEKMSEncryptedReader(decryptedReader, kmsKey.KeyID, encryptionContext)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-KMS encrypted reader: %v", err)
|
|
}
|
|
|
|
reEncryptedData, err := io.ReadAll(reEncryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read SSE-KMS encrypted data: %v", err)
|
|
}
|
|
|
|
// Decrypt with SSE-KMS
|
|
finalDecryptedReader, err := CreateSSEKMSDecryptedReader(bytes.NewReader(reEncryptedData), sseKmsKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-KMS decrypted reader: %v", err)
|
|
}
|
|
|
|
finalData, err := io.ReadAll(finalDecryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read final decrypted data: %v", err)
|
|
}
|
|
|
|
if string(finalData) != testData {
|
|
t.Errorf("Expected %s, got %s", testData, string(finalData))
|
|
}
|
|
}
|
|
|
|
// TestSSEKMSToSSECCopy tests cross-encryption copy (SSE-KMS to SSE-C)
|
|
func TestSSEKMSToSSECCopy(t *testing.T) {
|
|
// Setup SSE-KMS
|
|
kmsKey := SetupTestKMS(t)
|
|
defer kmsKey.Cleanup()
|
|
|
|
// Setup SSE-C key
|
|
ssecKey := GenerateTestSSECKey(1)
|
|
ssecCustomerKey := &SSECustomerKey{
|
|
Algorithm: "AES256",
|
|
Key: ssecKey.Key,
|
|
KeyMD5: ssecKey.KeyMD5,
|
|
}
|
|
|
|
testData := "Hello, reverse cross-encryption copy world!"
|
|
encryptionContext := BuildEncryptionContext("test-bucket", "test-object", false)
|
|
|
|
// Encrypt with SSE-KMS
|
|
encryptedReader, sseKmsKey, err := CreateSSEKMSEncryptedReader(strings.NewReader(testData), kmsKey.KeyID, encryptionContext)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-KMS encrypted reader: %v", err)
|
|
}
|
|
|
|
encryptedData, err := io.ReadAll(encryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read SSE-KMS encrypted data: %v", err)
|
|
}
|
|
|
|
// Decrypt SSE-KMS data
|
|
decryptedReader, err := CreateSSEKMSDecryptedReader(bytes.NewReader(encryptedData), sseKmsKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-KMS decrypted reader: %v", err)
|
|
}
|
|
|
|
// Re-encrypt with SSE-C
|
|
reEncryptedReader, reEncryptedIV, err := CreateSSECEncryptedReader(decryptedReader, ssecCustomerKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-C encrypted reader: %v", err)
|
|
}
|
|
|
|
reEncryptedData, err := io.ReadAll(reEncryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read SSE-C encrypted data: %v", err)
|
|
}
|
|
|
|
// Decrypt with SSE-C
|
|
finalDecryptedReader, err := CreateSSECDecryptedReader(bytes.NewReader(reEncryptedData), ssecCustomerKey, reEncryptedIV)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create SSE-C decrypted reader: %v", err)
|
|
}
|
|
|
|
finalData, err := io.ReadAll(finalDecryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read final decrypted data: %v", err)
|
|
}
|
|
|
|
if string(finalData) != testData {
|
|
t.Errorf("Expected %s, got %s", testData, string(finalData))
|
|
}
|
|
}
|
|
|
|
// TestSSECopyWithCorruptedSource tests copy operations with corrupted source data
|
|
func TestSSECopyWithCorruptedSource(t *testing.T) {
|
|
ssecKey := GenerateTestSSECKey(1)
|
|
ssecCustomerKey := &SSECustomerKey{
|
|
Algorithm: "AES256",
|
|
Key: ssecKey.Key,
|
|
KeyMD5: ssecKey.KeyMD5,
|
|
}
|
|
|
|
testData := "Hello, corruption test!"
|
|
|
|
// Encrypt data
|
|
encryptedReader, iv, err := CreateSSECEncryptedReader(strings.NewReader(testData), ssecCustomerKey)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create encrypted reader: %v", err)
|
|
}
|
|
|
|
encryptedData, err := io.ReadAll(encryptedReader)
|
|
if err != nil {
|
|
t.Fatalf("Failed to read encrypted data: %v", err)
|
|
}
|
|
|
|
// Corrupt the encrypted data
|
|
corruptedData := make([]byte, len(encryptedData))
|
|
copy(corruptedData, encryptedData)
|
|
if len(corruptedData) > s3_constants.AESBlockSize {
|
|
// Corrupt a byte after the IV
|
|
corruptedData[s3_constants.AESBlockSize] ^= 0xFF
|
|
}
|
|
|
|
// Try to decrypt corrupted data
|
|
decryptedReader, err := CreateSSECDecryptedReader(bytes.NewReader(corruptedData), ssecCustomerKey, iv)
|
|
if err != nil {
|
|
t.Fatalf("Failed to create decrypted reader for corrupted data: %v", err)
|
|
}
|
|
|
|
decryptedData, err := io.ReadAll(decryptedReader)
|
|
if err != nil {
|
|
// This is okay - corrupted data might cause read errors
|
|
t.Logf("Read error for corrupted data (expected): %v", err)
|
|
return
|
|
}
|
|
|
|
// If we can read it, the data should be different from original
|
|
if string(decryptedData) == testData {
|
|
t.Error("Decrypted corrupted data should not match original")
|
|
}
|
|
}
|
|
|
|
// TestSSEKMSCopyStrategy tests SSE-KMS copy strategy determination
|
|
func TestSSEKMSCopyStrategy(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
srcMetadata map[string][]byte
|
|
destKeyID string
|
|
expectedStrategy SSEKMSCopyStrategy
|
|
}{
|
|
{
|
|
name: "Unencrypted to unencrypted",
|
|
srcMetadata: map[string][]byte{},
|
|
destKeyID: "",
|
|
expectedStrategy: SSEKMSCopyStrategyDirect,
|
|
},
|
|
{
|
|
name: "Same KMS key",
|
|
srcMetadata: map[string][]byte{
|
|
s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: []byte("test-key-123"),
|
|
},
|
|
destKeyID: "test-key-123",
|
|
expectedStrategy: SSEKMSCopyStrategyDirect,
|
|
},
|
|
{
|
|
name: "Different KMS keys",
|
|
srcMetadata: map[string][]byte{
|
|
s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: []byte("test-key-123"),
|
|
},
|
|
destKeyID: "test-key-456",
|
|
expectedStrategy: SSEKMSCopyStrategyDecryptEncrypt,
|
|
},
|
|
{
|
|
name: "Encrypted to unencrypted",
|
|
srcMetadata: map[string][]byte{
|
|
s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: []byte("test-key-123"),
|
|
},
|
|
destKeyID: "",
|
|
expectedStrategy: SSEKMSCopyStrategyDecryptEncrypt,
|
|
},
|
|
{
|
|
name: "Unencrypted to encrypted",
|
|
srcMetadata: map[string][]byte{},
|
|
destKeyID: "test-key-123",
|
|
expectedStrategy: SSEKMSCopyStrategyDecryptEncrypt,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
strategy, err := DetermineSSEKMSCopyStrategy(tt.srcMetadata, tt.destKeyID)
|
|
if err != nil {
|
|
t.Fatalf("DetermineSSEKMSCopyStrategy failed: %v", err)
|
|
}
|
|
if strategy != tt.expectedStrategy {
|
|
t.Errorf("Expected strategy %v, got %v", tt.expectedStrategy, strategy)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestSSEKMSCopyHeaders tests SSE-KMS copy header parsing
|
|
func TestSSEKMSCopyHeaders(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
headers map[string]string
|
|
expectedKeyID string
|
|
expectedContext map[string]string
|
|
expectedBucketKey bool
|
|
expectError bool
|
|
}{
|
|
{
|
|
name: "No SSE-KMS headers",
|
|
headers: map[string]string{},
|
|
expectedKeyID: "",
|
|
expectedContext: nil,
|
|
expectedBucketKey: false,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "SSE-KMS with key ID",
|
|
headers: map[string]string{
|
|
s3_constants.AmzServerSideEncryption: "aws:kms",
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: "test-key-123",
|
|
},
|
|
expectedKeyID: "test-key-123",
|
|
expectedContext: nil,
|
|
expectedBucketKey: false,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "SSE-KMS with all options",
|
|
headers: map[string]string{
|
|
s3_constants.AmzServerSideEncryption: "aws:kms",
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: "test-key-123",
|
|
s3_constants.AmzServerSideEncryptionContext: "eyJ0ZXN0IjoidmFsdWUifQ==", // base64 of {"test":"value"}
|
|
s3_constants.AmzServerSideEncryptionBucketKeyEnabled: "true",
|
|
},
|
|
expectedKeyID: "test-key-123",
|
|
expectedContext: map[string]string{"test": "value"},
|
|
expectedBucketKey: true,
|
|
expectError: false,
|
|
},
|
|
{
|
|
name: "Invalid key ID",
|
|
headers: map[string]string{
|
|
s3_constants.AmzServerSideEncryption: "aws:kms",
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: "invalid key id",
|
|
},
|
|
expectError: true,
|
|
},
|
|
{
|
|
name: "Invalid encryption context",
|
|
headers: map[string]string{
|
|
s3_constants.AmzServerSideEncryption: "aws:kms",
|
|
s3_constants.AmzServerSideEncryptionContext: "invalid-base64!",
|
|
},
|
|
expectError: true,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
req, _ := http.NewRequest("PUT", "/test", nil)
|
|
for k, v := range tt.headers {
|
|
req.Header.Set(k, v)
|
|
}
|
|
|
|
keyID, context, bucketKey, err := ParseSSEKMSCopyHeaders(req)
|
|
|
|
if tt.expectError {
|
|
if err == nil {
|
|
t.Error("Expected error but got none")
|
|
}
|
|
return
|
|
}
|
|
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %v", err)
|
|
}
|
|
|
|
if keyID != tt.expectedKeyID {
|
|
t.Errorf("Expected keyID %s, got %s", tt.expectedKeyID, keyID)
|
|
}
|
|
|
|
if !mapsEqual(context, tt.expectedContext) {
|
|
t.Errorf("Expected context %v, got %v", tt.expectedContext, context)
|
|
}
|
|
|
|
if bucketKey != tt.expectedBucketKey {
|
|
t.Errorf("Expected bucketKey %v, got %v", tt.expectedBucketKey, bucketKey)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestSSEKMSDirectCopy tests direct copy scenarios
|
|
func TestSSEKMSDirectCopy(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
srcMetadata map[string][]byte
|
|
destKeyID string
|
|
canDirect bool
|
|
}{
|
|
{
|
|
name: "Both unencrypted",
|
|
srcMetadata: map[string][]byte{},
|
|
destKeyID: "",
|
|
canDirect: true,
|
|
},
|
|
{
|
|
name: "Same key ID",
|
|
srcMetadata: map[string][]byte{
|
|
s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: []byte("test-key-123"),
|
|
},
|
|
destKeyID: "test-key-123",
|
|
canDirect: true,
|
|
},
|
|
{
|
|
name: "Different key IDs",
|
|
srcMetadata: map[string][]byte{
|
|
s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: []byte("test-key-123"),
|
|
},
|
|
destKeyID: "test-key-456",
|
|
canDirect: false,
|
|
},
|
|
{
|
|
name: "Source encrypted, dest unencrypted",
|
|
srcMetadata: map[string][]byte{
|
|
s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: []byte("test-key-123"),
|
|
},
|
|
destKeyID: "",
|
|
canDirect: false,
|
|
},
|
|
{
|
|
name: "Source unencrypted, dest encrypted",
|
|
srcMetadata: map[string][]byte{},
|
|
destKeyID: "test-key-123",
|
|
canDirect: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
canDirect := CanDirectCopySSEKMS(tt.srcMetadata, tt.destKeyID)
|
|
if canDirect != tt.canDirect {
|
|
t.Errorf("Expected canDirect %v, got %v", tt.canDirect, canDirect)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// TestGetSourceSSEKMSInfo tests extraction of SSE-KMS info from metadata
|
|
func TestGetSourceSSEKMSInfo(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
metadata map[string][]byte
|
|
expectedKeyID string
|
|
expectedEncrypted bool
|
|
}{
|
|
{
|
|
name: "No encryption",
|
|
metadata: map[string][]byte{},
|
|
expectedKeyID: "",
|
|
expectedEncrypted: false,
|
|
},
|
|
{
|
|
name: "SSE-KMS with key ID",
|
|
metadata: map[string][]byte{
|
|
s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
|
|
s3_constants.AmzServerSideEncryptionAwsKmsKeyId: []byte("test-key-123"),
|
|
},
|
|
expectedKeyID: "test-key-123",
|
|
expectedEncrypted: true,
|
|
},
|
|
{
|
|
name: "SSE-KMS without key ID (default key)",
|
|
metadata: map[string][]byte{
|
|
s3_constants.AmzServerSideEncryption: []byte("aws:kms"),
|
|
},
|
|
expectedKeyID: "",
|
|
expectedEncrypted: true,
|
|
},
|
|
{
|
|
name: "Non-KMS encryption",
|
|
metadata: map[string][]byte{
|
|
s3_constants.AmzServerSideEncryption: []byte("AES256"),
|
|
},
|
|
expectedKeyID: "",
|
|
expectedEncrypted: false,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
keyID, encrypted := GetSourceSSEKMSInfo(tt.metadata)
|
|
if keyID != tt.expectedKeyID {
|
|
t.Errorf("Expected keyID %s, got %s", tt.expectedKeyID, keyID)
|
|
}
|
|
if encrypted != tt.expectedEncrypted {
|
|
t.Errorf("Expected encrypted %v, got %v", tt.expectedEncrypted, encrypted)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Helper function to compare maps
|
|
func mapsEqual(a, b map[string]string) bool {
|
|
if len(a) != len(b) {
|
|
return false
|
|
}
|
|
for k, v := range a {
|
|
if b[k] != v {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|