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
|
package sse_test
import (
"bytes"
"context"
"io"
"testing"
"time"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/s3"
"github.com/aws/aws-sdk-go-v2/service/s3/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestSSEKMSOpenBaoIntegration tests SSE-KMS with real OpenBao KMS provider
// This test verifies that SeaweedFS can successfully encrypt and decrypt data
// using actual KMS operations through OpenBao, not just mock key IDs
func TestSSEKMSOpenBaoIntegration(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
defer cancel()
client, err := createS3Client(ctx, defaultConfig)
require.NoError(t, err, "Failed to create S3 client")
bucketName, err := createTestBucket(ctx, client, defaultConfig.BucketPrefix+"sse-kms-openbao-")
require.NoError(t, err, "Failed to create test bucket")
defer cleanupTestBucket(ctx, client, bucketName)
t.Run("Basic SSE-KMS with OpenBao", func(t *testing.T) {
testData := []byte("Hello, SSE-KMS with OpenBao integration!")
objectKey := "test-openbao-kms-object"
kmsKeyID := "test-key-123" // This key should exist in OpenBao
// Upload object with SSE-KMS
putResp, err := client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
Body: bytes.NewReader(testData),
ServerSideEncryption: types.ServerSideEncryptionAwsKms,
SSEKMSKeyId: aws.String(kmsKeyID),
})
require.NoError(t, err, "Failed to upload SSE-KMS object with OpenBao")
assert.NotEmpty(t, aws.ToString(putResp.ETag), "ETag should be present")
// Retrieve and verify object
getResp, err := client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
})
require.NoError(t, err, "Failed to retrieve SSE-KMS object")
defer getResp.Body.Close()
// Verify content matches (this proves encryption/decryption worked)
retrievedData, err := io.ReadAll(getResp.Body)
require.NoError(t, err, "Failed to read retrieved data")
assert.Equal(t, testData, retrievedData, "Decrypted data should match original")
// Verify SSE-KMS headers are present
assert.Equal(t, types.ServerSideEncryptionAwsKms, getResp.ServerSideEncryption, "Should indicate KMS encryption")
assert.Equal(t, kmsKeyID, aws.ToString(getResp.SSEKMSKeyId), "Should return the KMS key ID used")
})
t.Run("Multiple KMS Keys with OpenBao", func(t *testing.T) {
testCases := []struct {
keyID string
data string
objectKey string
}{
{"test-key-123", "Data encrypted with test-key-123", "object-key-123"},
{"seaweedfs-test-key", "Data encrypted with seaweedfs-test-key", "object-seaweedfs-key"},
{"high-security-key", "Data encrypted with high-security-key", "object-security-key"},
}
for _, tc := range testCases {
t.Run("Key_"+tc.keyID, func(t *testing.T) {
testData := []byte(tc.data)
// Upload with specific KMS key
_, err := client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(tc.objectKey),
Body: bytes.NewReader(testData),
ServerSideEncryption: types.ServerSideEncryptionAwsKms,
SSEKMSKeyId: aws.String(tc.keyID),
})
require.NoError(t, err, "Failed to upload with KMS key %s", tc.keyID)
// Retrieve and verify
getResp, err := client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(tc.objectKey),
})
require.NoError(t, err, "Failed to retrieve object encrypted with key %s", tc.keyID)
defer getResp.Body.Close()
retrievedData, err := io.ReadAll(getResp.Body)
require.NoError(t, err, "Failed to read data for key %s", tc.keyID)
// Verify data integrity (proves real encryption/decryption occurred)
assert.Equal(t, testData, retrievedData, "Data should match for key %s", tc.keyID)
assert.Equal(t, tc.keyID, aws.ToString(getResp.SSEKMSKeyId), "Should return correct key ID")
})
}
})
t.Run("Large Data with OpenBao KMS", func(t *testing.T) {
// Test with larger data to ensure chunked encryption works
testData := generateTestData(64 * 1024) // 64KB
objectKey := "large-openbao-kms-object"
kmsKeyID := "performance-key"
// Upload large object with SSE-KMS
_, err := client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
Body: bytes.NewReader(testData),
ServerSideEncryption: types.ServerSideEncryptionAwsKms,
SSEKMSKeyId: aws.String(kmsKeyID),
})
require.NoError(t, err, "Failed to upload large SSE-KMS object")
// Retrieve and verify large object
getResp, err := client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
})
require.NoError(t, err, "Failed to retrieve large SSE-KMS object")
defer getResp.Body.Close()
retrievedData, err := io.ReadAll(getResp.Body)
require.NoError(t, err, "Failed to read large data")
// Use MD5 comparison for large data
assertDataEqual(t, testData, retrievedData, "Large encrypted data should match original")
assert.Equal(t, kmsKeyID, aws.ToString(getResp.SSEKMSKeyId), "Should return performance key ID")
})
}
// TestSSEKMSOpenBaoAvailability checks if OpenBao KMS is available for testing
// This test can be run separately to verify the KMS setup
func TestSSEKMSOpenBaoAvailability(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
client, err := createS3Client(ctx, defaultConfig)
require.NoError(t, err, "Failed to create S3 client")
bucketName, err := createTestBucket(ctx, client, defaultConfig.BucketPrefix+"sse-kms-availability-")
require.NoError(t, err, "Failed to create test bucket")
defer cleanupTestBucket(ctx, client, bucketName)
// Try a simple KMS operation to verify availability
testData := []byte("KMS availability test")
objectKey := "kms-availability-test"
kmsKeyID := "test-key-123"
// This should succeed if KMS is properly configured
_, err = client.PutObject(ctx, &s3.PutObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
Body: bytes.NewReader(testData),
ServerSideEncryption: types.ServerSideEncryptionAwsKms,
SSEKMSKeyId: aws.String(kmsKeyID),
})
if err != nil {
t.Skipf("OpenBao KMS not available for testing: %v", err)
}
t.Logf("OpenBao KMS is available and working")
// Verify we can retrieve the object
getResp, err := client.GetObject(ctx, &s3.GetObjectInput{
Bucket: aws.String(bucketName),
Key: aws.String(objectKey),
})
require.NoError(t, err, "Failed to retrieve KMS test object")
defer getResp.Body.Close()
assert.Equal(t, types.ServerSideEncryptionAwsKms, getResp.ServerSideEncryption)
t.Logf("KMS encryption/decryption working correctly")
}
|