mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			178 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			4.4 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"
 | 
						|
 | 
						|
	"k8s.io/apiserver/pkg/server/options/encryptionconfig"
 | 
						|
	"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: EncryptionConfig
 | 
						|
apiVersion: v1
 | 
						|
resources:
 | 
						|
  - resources:
 | 
						|
    - secrets
 | 
						|
    providers:
 | 
						|
    - aesgcm:
 | 
						|
        keys:
 | 
						|
        - name: key1
 | 
						|
          secret: c2VjcmV0IGlzIHNlY3VyZQ==
 | 
						|
`
 | 
						|
 | 
						|
	aesCBCConfigYAML = `
 | 
						|
kind: EncryptionConfig
 | 
						|
apiVersion: v1
 | 
						|
resources:
 | 
						|
  - resources:
 | 
						|
    - secrets
 | 
						|
    providers:
 | 
						|
    - aescbc:
 | 
						|
        keys:
 | 
						|
        - name: key1
 | 
						|
          secret: c2VjcmV0IGlzIHNlY3VyZQ==
 | 
						|
`
 | 
						|
 | 
						|
	identityConfigYAML = `
 | 
						|
kind: EncryptionConfig
 | 
						|
apiVersion: 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 EncryptionConfig 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()
 | 
						|
}
 | 
						|
 | 
						|
func unSealWithGCMTransformer(cipherText []byte, ctx value.Context,
 | 
						|
	transformerConfig encryptionconfig.ProviderConfig) ([]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 encryptionconfig.ProviderConfig) ([]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
 | 
						|
}
 |