Add benchmarks for envelope transformer

This commit is contained in:
Saksham Sharma 2017-07-22 11:45:36 -07:00
parent d23a1f135d
commit 449e811ebe
3 changed files with 76 additions and 10 deletions

View File

@ -15,7 +15,6 @@ go_library(
deps = [ deps = [
"//vendor/github.com/hashicorp/golang-lru:go_default_library", "//vendor/github.com/hashicorp/golang-lru:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library",
], ],
) )
@ -24,5 +23,8 @@ go_test(
srcs = ["envelope_test.go"], srcs = ["envelope_test.go"],
library = ":go_default_library", library = ":go_default_library",
tags = ["automanaged"], tags = ["automanaged"],
deps = ["//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library"], deps = [
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library",
],
) )

View File

@ -19,12 +19,12 @@ package envelope
import ( import (
"crypto/aes" "crypto/aes"
"crypto/cipher"
"crypto/rand" "crypto/rand"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"k8s.io/apiserver/pkg/storage/value" "k8s.io/apiserver/pkg/storage/value"
aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
) )
@ -48,13 +48,16 @@ type envelopeTransformer struct {
// cacheSize is the maximum number of DEKs that are cached. // cacheSize is the maximum number of DEKs that are cached.
cacheSize int cacheSize int
// baseTransformerFunc creates a new transformer for encrypting the data with the DEK.
baseTransformerFunc func(cipher.Block) value.Transformer
} }
// NewEnvelopeTransformer returns a transformer which implements a KEK-DEK based envelope encryption scheme. // NewEnvelopeTransformer returns a transformer which implements a KEK-DEK based envelope encryption scheme.
// It uses envelopeService to encrypt and decrypt DEKs. Respective DEKs (in encrypted form) are prepended to // It uses envelopeService to encrypt and decrypt DEKs. Respective DEKs (in encrypted form) are prepended to
// the data items they encrypt. A cache (of size cacheSize) is maintained to store the most recently // the data items they encrypt. A cache (of size cacheSize) is maintained to store the most recently
// used decrypted DEKs in memory. // used decrypted DEKs in memory.
func NewEnvelopeTransformer(envelopeService Service, cacheSize int) (value.Transformer, error) { func NewEnvelopeTransformer(envelopeService Service, cacheSize int, baseTransformerFunc func(cipher.Block) value.Transformer) (value.Transformer, error) {
if cacheSize == 0 { if cacheSize == 0 {
cacheSize = defaultCacheSize cacheSize = defaultCacheSize
} }
@ -63,9 +66,10 @@ func NewEnvelopeTransformer(envelopeService Service, cacheSize int) (value.Trans
return nil, err return nil, err
} }
return &envelopeTransformer{ return &envelopeTransformer{
envelopeService: envelopeService, envelopeService: envelopeService,
transformers: cache, transformers: cache,
cacheSize: cacheSize, cacheSize: cacheSize,
baseTransformerFunc: baseTransformerFunc,
}, nil }, nil
} }
@ -141,7 +145,7 @@ func (t *envelopeTransformer) addTransformer(encKey string, key []byte) (value.T
if err != nil { if err != nil {
return nil, err return nil, err
} }
transformer := aestransformer.NewCBCTransformer(block) transformer := t.baseTransformerFunc(block)
t.transformers.Add(encKey, transformer) t.transformers.Add(encKey, transformer)
return transformer, nil return transformer, nil
} }

View File

@ -18,6 +18,7 @@ package envelope
import ( import (
"bytes" "bytes"
"crypto/aes"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"strconv" "strconv"
@ -25,6 +26,7 @@ import (
"testing" "testing"
"k8s.io/apiserver/pkg/storage/value" "k8s.io/apiserver/pkg/storage/value"
aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
) )
const ( const (
@ -76,7 +78,7 @@ func newTestEnvelopeService() *testEnvelopeService {
// Throw error if Envelope transformer tries to contact Envelope without hitting cache. // Throw error if Envelope transformer tries to contact Envelope without hitting cache.
func TestEnvelopeCaching(t *testing.T) { func TestEnvelopeCaching(t *testing.T) {
envelopeService := newTestEnvelopeService() envelopeService := newTestEnvelopeService()
envelopeTransformer, err := NewEnvelopeTransformer(envelopeService, testEnvelopeCacheSize) envelopeTransformer, err := NewEnvelopeTransformer(envelopeService, testEnvelopeCacheSize, aestransformer.NewCBCTransformer)
if err != nil { if err != nil {
t.Fatalf("failed to initialize envelope transformer: %v", err) t.Fatalf("failed to initialize envelope transformer: %v", err)
} }
@ -108,7 +110,7 @@ func TestEnvelopeCaching(t *testing.T) {
// Makes Envelope transformer hit cache limit, throws error if it misbehaves. // Makes Envelope transformer hit cache limit, throws error if it misbehaves.
func TestEnvelopeCacheLimit(t *testing.T) { func TestEnvelopeCacheLimit(t *testing.T) {
envelopeTransformer, err := NewEnvelopeTransformer(newTestEnvelopeService(), testEnvelopeCacheSize) envelopeTransformer, err := NewEnvelopeTransformer(newTestEnvelopeService(), testEnvelopeCacheSize, aestransformer.NewCBCTransformer)
if err != nil { if err != nil {
t.Fatalf("failed to initialize envelope transformer: %v", err) t.Fatalf("failed to initialize envelope transformer: %v", err)
} }
@ -141,3 +143,61 @@ func TestEnvelopeCacheLimit(t *testing.T) {
} }
} }
} }
func BenchmarkEnvelopeCBCRead(b *testing.B) {
envelopeTransformer, err := NewEnvelopeTransformer(newTestEnvelopeService(), testEnvelopeCacheSize, aestransformer.NewCBCTransformer)
if err != nil {
b.Fatalf("failed to initialize envelope transformer: %v", err)
}
benchmarkRead(b, envelopeTransformer, 1024)
}
func BenchmarkAESCBCRead(b *testing.B) {
block, err := aes.NewCipher(bytes.Repeat([]byte("a"), 32))
if err != nil {
b.Fatal(err)
}
aesCBCTransformer := aestransformer.NewCBCTransformer(block)
benchmarkRead(b, aesCBCTransformer, 1024)
}
func BenchmarkEnvelopeGCMRead(b *testing.B) {
envelopeTransformer, err := NewEnvelopeTransformer(newTestEnvelopeService(), testEnvelopeCacheSize, aestransformer.NewGCMTransformer)
if err != nil {
b.Fatalf("failed to initialize envelope transformer: %v", err)
}
benchmarkRead(b, envelopeTransformer, 1024)
}
func BenchmarkAESGCMRead(b *testing.B) {
block, err := aes.NewCipher(bytes.Repeat([]byte("a"), 32))
if err != nil {
b.Fatal(err)
}
aesGCMTransformer := aestransformer.NewGCMTransformer(block)
benchmarkRead(b, aesGCMTransformer, 1024)
}
func benchmarkRead(b *testing.B, transformer value.Transformer, valueLength int) {
context := value.DefaultContext([]byte(testContextText))
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
out, err := transformer.TransformToStorage(v, context)
if err != nil {
b.Fatal(err)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
from, stale, err := transformer.TransformFromStorage(out, context)
if err != nil {
b.Fatal(err)
}
if stale {
b.Fatalf("unexpected data: %t %q", stale, from)
}
}
b.StopTimer()
}