1
16
17 package transformation
18
19 import (
20 "context"
21 "crypto/aes"
22 "crypto/cipher"
23 "encoding/base64"
24 "fmt"
25 "testing"
26
27 apiserverv1 "k8s.io/apiserver/pkg/apis/apiserver/v1"
28 "k8s.io/apiserver/pkg/storage/value"
29 aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
30 )
31
32 const (
33 aesGCMPrefix = "k8s:enc:aesgcm:v1:key1:"
34 aesCBCPrefix = "k8s:enc:aescbc:v1:key1:"
35
36 aesGCMConfigYAML = `
37 kind: EncryptionConfiguration
38 apiVersion: apiserver.config.k8s.io/v1
39 resources:
40 - resources:
41 - secrets
42 providers:
43 - aesgcm:
44 keys:
45 - name: key1
46 secret: c2VjcmV0IGlzIHNlY3VyZQ==
47 `
48
49 aesCBCConfigYAML = `
50 kind: EncryptionConfiguration
51 apiVersion: apiserver.config.k8s.io/v1
52 resources:
53 - resources:
54 - secrets
55 providers:
56 - aescbc:
57 keys:
58 - name: key1
59 secret: c2VjcmV0IGlzIHNlY3VyZQ==
60 `
61
62 identityConfigYAML = `
63 kind: EncryptionConfiguration
64 apiVersion: apiserver.config.k8s.io/v1
65 resources:
66 - resources:
67 - secrets
68 providers:
69 - identity: {}
70 `
71 )
72
73
74
75
76
77 func TestSecretsShouldBeTransformed(t *testing.T) {
78 var testCases = []struct {
79 transformerConfigContent string
80 transformerPrefix string
81 unSealFunc unSealSecret
82 }{
83 {aesGCMConfigYAML, aesGCMPrefix, unSealWithGCMTransformer},
84 {aesCBCConfigYAML, aesCBCPrefix, unSealWithCBCTransformer},
85
86 }
87 for _, tt := range testCases {
88 test, err := newTransformTest(t, tt.transformerConfigContent, false, "", nil)
89 if err != nil {
90 t.Fatalf("failed to setup test for envelop %s, error was %v", tt.transformerPrefix, err)
91 continue
92 }
93 test.secret, err = test.createSecret(testSecret, testNamespace)
94 if err != nil {
95 t.Fatalf("Failed to create test secret, error: %v", err)
96 }
97 test.runResource(test.logger, tt.unSealFunc, tt.transformerPrefix, "", "v1", "secrets", test.secret.Name, test.secret.Namespace)
98 test.cleanUp()
99 }
100 }
101
102
103 func BenchmarkBase(b *testing.B) {
104 runBenchmark(b, "")
105 }
106
107
108 func BenchmarkIdentityWrite(b *testing.B) {
109 runBenchmark(b, identityConfigYAML)
110 }
111
112 func BenchmarkAESGCMEnvelopeWrite(b *testing.B) {
113 runBenchmark(b, aesGCMConfigYAML)
114 }
115
116 func BenchmarkAESCBCEnvelopeWrite(b *testing.B) {
117 runBenchmark(b, aesCBCConfigYAML)
118 }
119
120 func runBenchmark(b *testing.B, transformerConfig string) {
121 b.StopTimer()
122 test, err := newTransformTest(b, transformerConfig, false, "", nil)
123 if err != nil {
124 b.Fatalf("failed to setup benchmark for config %s, error was %v", transformerConfig, err)
125 }
126 defer test.cleanUp()
127
128 b.StartTimer()
129 test.benchmark(b)
130 b.StopTimer()
131 test.printMetrics()
132 }
133
134 func unSealWithGCMTransformer(ctx context.Context, cipherText []byte, dataCtx value.Context,
135 transformerConfig apiserverv1.ProviderConfiguration) ([]byte, error) {
136
137 block, err := newAESCipher(transformerConfig.AESGCM.Keys[0].Secret)
138 if err != nil {
139 return nil, fmt.Errorf("failed to create block cipher: %v", err)
140 }
141
142 gcmTransformer, err := aestransformer.NewGCMTransformer(block)
143 if err != nil {
144 return nil, fmt.Errorf("failed to create transformer from block: %v", err)
145 }
146
147 clearText, _, err := gcmTransformer.TransformFromStorage(ctx, cipherText, dataCtx)
148 if err != nil {
149 return nil, fmt.Errorf("failed to decypt secret: %v", err)
150 }
151
152 return clearText, nil
153 }
154
155 func unSealWithCBCTransformer(ctx context.Context, cipherText []byte, dataCtx value.Context,
156 transformerConfig apiserverv1.ProviderConfiguration) ([]byte, error) {
157
158 block, err := newAESCipher(transformerConfig.AESCBC.Keys[0].Secret)
159 if err != nil {
160 return nil, err
161 }
162
163 cbcTransformer := aestransformer.NewCBCTransformer(block)
164
165 clearText, _, err := cbcTransformer.TransformFromStorage(ctx, cipherText, dataCtx)
166 if err != nil {
167 return nil, fmt.Errorf("failed to decypt secret: %v", err)
168 }
169
170 return clearText, nil
171 }
172
173 func newAESCipher(key string) (cipher.Block, error) {
174 k, err := base64.StdEncoding.DecodeString(key)
175 if err != nil {
176 return nil, fmt.Errorf("failed to decode config secret: %v", err)
177 }
178
179 block, err := aes.NewCipher(k)
180 if err != nil {
181 return nil, fmt.Errorf("failed to create AES cipher: %v", err)
182 }
183
184 return block, nil
185 }
186
View as plain text