mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-10-24 17:10:44 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			179 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
| Copyright 2017 The Kubernetes Authors.
 | |
| 
 | |
| Licensed under the Apache License, Version 2.0 (the "License");
 | |
| you may not use this file except in compliance with the License.
 | |
| You may obtain a copy of the License at
 | |
| 
 | |
|     http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| Unless required by applicable law or agreed to in writing, software
 | |
| distributed under the License is distributed on an "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| See the License for the specific language governing permissions and
 | |
| limitations under the License.
 | |
| */
 | |
| 
 | |
| package master
 | |
| 
 | |
| import (
 | |
| 	"crypto/aes"
 | |
| 	"crypto/cipher"
 | |
| 	"encoding/base64"
 | |
| 	"fmt"
 | |
| 	"testing"
 | |
| 
 | |
| 	apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1"
 | |
| 	"k8s.io/apiserver/pkg/storage/value"
 | |
| 	aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	aesGCMPrefix = "k8s:enc:aesgcm:v1:key1:"
 | |
| 	aesCBCPrefix = "k8s:enc:aescbc:v1:key1:"
 | |
| 
 | |
| 	aesGCMConfigYAML = `
 | |
| kind: EncryptionConfiguration
 | |
| apiVersion: apiserver.config.k8s.io/v1
 | |
| resources:
 | |
|   - resources:
 | |
|     - secrets
 | |
|     providers:
 | |
|     - aesgcm:
 | |
|         keys:
 | |
|         - name: key1
 | |
|           secret: c2VjcmV0IGlzIHNlY3VyZQ==
 | |
| `
 | |
| 
 | |
| 	aesCBCConfigYAML = `
 | |
| kind: EncryptionConfiguration
 | |
| apiVersion: apiserver.config.k8s.io/v1
 | |
| resources:
 | |
|   - resources:
 | |
|     - secrets
 | |
|     providers:
 | |
|     - aescbc:
 | |
|         keys:
 | |
|         - name: key1
 | |
|           secret: c2VjcmV0IGlzIHNlY3VyZQ==
 | |
| `
 | |
| 
 | |
| 	identityConfigYAML = `
 | |
| kind: EncryptionConfiguration
 | |
| apiVersion: apiserver.config.k8s.io/v1
 | |
| resources:
 | |
|   - resources:
 | |
|     - secrets
 | |
|     providers:
 | |
|     - identity: {}
 | |
| `
 | |
| )
 | |
| 
 | |
| // TestSecretsShouldBeEnveloped is an integration test between KubeAPI and etcd that checks:
 | |
| // 1. Secrets are encrypted on write
 | |
| // 2. Secrets are decrypted on read
 | |
| // when EncryptionConfiguration is passed to KubeAPI server.
 | |
| func TestSecretsShouldBeTransformed(t *testing.T) {
 | |
| 	var testCases = []struct {
 | |
| 		transformerConfigContent string
 | |
| 		transformerPrefix        string
 | |
| 		unSealFunc               unSealSecret
 | |
| 	}{
 | |
| 		{aesGCMConfigYAML, aesGCMPrefix, unSealWithGCMTransformer},
 | |
| 		{aesCBCConfigYAML, aesCBCPrefix, unSealWithCBCTransformer},
 | |
| 		// TODO: add secretbox
 | |
| 	}
 | |
| 	for _, tt := range testCases {
 | |
| 		test, err := newTransformTest(t, tt.transformerConfigContent)
 | |
| 		if err != nil {
 | |
| 			test.cleanUp()
 | |
| 			t.Errorf("failed to setup test for envelop %s, error was %v", tt.transformerPrefix, err)
 | |
| 			continue
 | |
| 		}
 | |
| 		test.run(tt.unSealFunc, tt.transformerPrefix)
 | |
| 		test.cleanUp()
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // Baseline (no enveloping) - use to contrast with enveloping benchmarks.
 | |
| func BenchmarkBase(b *testing.B) {
 | |
| 	runBenchmark(b, "")
 | |
| }
 | |
| 
 | |
| // Identity transformer is a NOOP (crypto-wise) - use to contrast with AESGCM and AESCBC benchmark results.
 | |
| func BenchmarkIdentityWrite(b *testing.B) {
 | |
| 	runBenchmark(b, identityConfigYAML)
 | |
| }
 | |
| 
 | |
| func BenchmarkAESGCMEnvelopeWrite(b *testing.B) {
 | |
| 	runBenchmark(b, aesGCMConfigYAML)
 | |
| }
 | |
| 
 | |
| func BenchmarkAESCBCEnvelopeWrite(b *testing.B) {
 | |
| 	runBenchmark(b, aesCBCConfigYAML)
 | |
| }
 | |
| 
 | |
| func runBenchmark(b *testing.B, transformerConfig string) {
 | |
| 	b.StopTimer()
 | |
| 	test, err := newTransformTest(b, transformerConfig)
 | |
| 	defer test.cleanUp()
 | |
| 	if err != nil {
 | |
| 		b.Fatalf("failed to setup benchmark for config %s, error was %v", transformerConfig, err)
 | |
| 	}
 | |
| 
 | |
| 	b.StartTimer()
 | |
| 	test.benchmark(b)
 | |
| 	b.StopTimer()
 | |
| 	test.printMetrics()
 | |
| }
 | |
| 
 | |
| func unSealWithGCMTransformer(cipherText []byte, ctx value.Context,
 | |
| 	transformerConfig apiserverconfigv1.ProviderConfiguration) ([]byte, error) {
 | |
| 
 | |
| 	block, err := newAESCipher(transformerConfig.AESGCM.Keys[0].Secret)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to create block cipher: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	gcmTransformer := aestransformer.NewGCMTransformer(block)
 | |
| 
 | |
| 	clearText, _, err := gcmTransformer.TransformFromStorage(cipherText, ctx)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to decypt secret: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	return clearText, nil
 | |
| }
 | |
| 
 | |
| func unSealWithCBCTransformer(cipherText []byte, ctx value.Context,
 | |
| 	transformerConfig apiserverconfigv1.ProviderConfiguration) ([]byte, error) {
 | |
| 
 | |
| 	block, err := newAESCipher(transformerConfig.AESCBC.Keys[0].Secret)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	cbcTransformer := aestransformer.NewCBCTransformer(block)
 | |
| 
 | |
| 	clearText, _, err := cbcTransformer.TransformFromStorage(cipherText, ctx)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to decypt secret: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	return clearText, nil
 | |
| }
 | |
| 
 | |
| func newAESCipher(key string) (cipher.Block, error) {
 | |
| 	k, err := base64.StdEncoding.DecodeString(key)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to decode config secret: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	block, err := aes.NewCipher(k)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to create AES cipher: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	return block, nil
 | |
| }
 |