storage: transformers: pass a context.Context
When an envelope transformer calls out to KMS (for instance), it will be very helpful to pass a `context.Context` to allow for cancellation. This patch does that, while passing the previously-expected additional data via a context value. Signed-off-by: Steve Kuznetsov <skuznets@redhat.com> Kubernetes-commit: 27312feb9983c18d1daf00afba788727d024cdd0
This commit is contained in:
parent
0d701a6123
commit
af1cb1cefe
|
@ -18,6 +18,7 @@ package encryptionconfig
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
|
@ -184,7 +185,8 @@ func TestEncryptionProviderConfigCorrect(t *testing.T) {
|
|||
secretboxFirstTransformer := secretboxFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
|
||||
kmsFirstTransformer := kmsFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
|
||||
|
||||
context := value.DefaultContext([]byte(sampleContextText))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte(sampleContextText))
|
||||
originalText := []byte(sampleText)
|
||||
|
||||
transformers := []struct {
|
||||
|
@ -199,13 +201,13 @@ func TestEncryptionProviderConfigCorrect(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, testCase := range transformers {
|
||||
transformedData, err := testCase.Transformer.TransformToStorage(originalText, context)
|
||||
transformedData, err := testCase.Transformer.TransformToStorage(ctx, originalText, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: error while transforming data to storage: %s", testCase.Name, err)
|
||||
}
|
||||
|
||||
for _, transformer := range transformers {
|
||||
untransformedData, stale, err := transformer.Transformer.TransformFromStorage(transformedData, context)
|
||||
untransformedData, stale, err := transformer.Transformer.TransformFromStorage(ctx, transformedData, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: error while reading using %s transformer: %s", testCase.Name, transformer.Name, err)
|
||||
}
|
||||
|
@ -347,16 +349,17 @@ func TestCBCKeyRotationWithoutOverlappingProviders(t *testing.T) {
|
|||
func testCBCKeyRotationWithProviders(t *testing.T, firstEncryptionConfig, firstPrefix, secondEncryptionConfig, secondPrefix string) {
|
||||
p := getTransformerFromEncryptionConfig(t, firstEncryptionConfig)
|
||||
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
|
||||
out, err := p.TransformToStorage([]byte("firstvalue"), context)
|
||||
out, err := p.TransformToStorage(ctx, []byte("firstvalue"), dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.HasPrefix(out, []byte(firstPrefix)) {
|
||||
t.Fatalf("unexpected prefix: %q", out)
|
||||
}
|
||||
from, stale, err := p.TransformFromStorage(out, context)
|
||||
from, stale, err := p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -365,14 +368,14 @@ func testCBCKeyRotationWithProviders(t *testing.T, firstEncryptionConfig, firstP
|
|||
}
|
||||
|
||||
// verify changing the context fails storage
|
||||
_, _, err = p.TransformFromStorage(out, value.DefaultContext([]byte("incorrect_context")))
|
||||
_, _, err = p.TransformFromStorage(ctx, out, value.DefaultContext([]byte("incorrect_context")))
|
||||
if err != nil {
|
||||
t.Fatalf("CBC mode does not support authentication: %v", err)
|
||||
}
|
||||
|
||||
// reverse the order, use the second key
|
||||
p = getTransformerFromEncryptionConfig(t, secondEncryptionConfig)
|
||||
from, stale, err = p.TransformFromStorage(out, context)
|
||||
from, stale, err = p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -380,14 +383,14 @@ func testCBCKeyRotationWithProviders(t *testing.T, firstEncryptionConfig, firstP
|
|||
t.Fatalf("unexpected data: %t %q", stale, from)
|
||||
}
|
||||
|
||||
out, err = p.TransformToStorage([]byte("firstvalue"), context)
|
||||
out, err = p.TransformToStorage(ctx, []byte("firstvalue"), dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.HasPrefix(out, []byte(secondPrefix)) {
|
||||
t.Fatalf("unexpected prefix: %q", out)
|
||||
}
|
||||
from, stale, err = p.TransformFromStorage(out, context)
|
||||
from, stale, err = p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ func (s *store) Get(ctx context.Context, key string, opts storage.GetOptions, ou
|
|||
}
|
||||
kv := getResp.Kvs[0]
|
||||
|
||||
data, _, err := s.transformer.TransformFromStorage(kv.Value, authenticatedDataString(key))
|
||||
data, _, err := s.transformer.TransformFromStorage(ctx, kv.Value, authenticatedDataString(key))
|
||||
if err != nil {
|
||||
return storage.NewInternalError(err.Error())
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object,
|
|||
return err
|
||||
}
|
||||
|
||||
newData, err := s.transformer.TransformToStorage(data, authenticatedDataString(key))
|
||||
newData, err := s.transformer.TransformToStorage(ctx, data, authenticatedDataString(key))
|
||||
if err != nil {
|
||||
return storage.NewInternalError(err.Error())
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ func (s *store) conditionalDelete(
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.getState(getResp, key, v, false)
|
||||
return s.getState(ctx, getResp, key, v, false)
|
||||
}
|
||||
|
||||
var origState *objState
|
||||
|
@ -296,7 +296,7 @@ func (s *store) conditionalDelete(
|
|||
if !txnResp.Succeeded {
|
||||
getResp := (*clientv3.GetResponse)(txnResp.Responses[0].GetResponseRange())
|
||||
klog.V(4).Infof("deletion of %s failed because of a conflict, going to retry", key)
|
||||
origState, err = s.getState(getResp, key, v, false)
|
||||
origState, err = s.getState(ctx, getResp, key, v, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -327,7 +327,7 @@ func (s *store) GuaranteedUpdate(
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.getState(getResp, key, v, ignoreNotFound)
|
||||
return s.getState(ctx, getResp, key, v, ignoreNotFound)
|
||||
}
|
||||
|
||||
var origState *objState
|
||||
|
@ -415,7 +415,7 @@ func (s *store) GuaranteedUpdate(
|
|||
}
|
||||
}
|
||||
|
||||
newData, err := s.transformer.TransformToStorage(data, transformContext)
|
||||
newData, err := s.transformer.TransformToStorage(ctx, data, transformContext)
|
||||
if err != nil {
|
||||
return storage.NewInternalError(err.Error())
|
||||
}
|
||||
|
@ -442,7 +442,7 @@ func (s *store) GuaranteedUpdate(
|
|||
if !txnResp.Succeeded {
|
||||
getResp := (*clientv3.GetResponse)(txnResp.Responses[0].GetResponseRange())
|
||||
klog.V(4).Infof("GuaranteedUpdate of %s failed because of a conflict, going to retry", key)
|
||||
origState, err = s.getState(getResp, key, v, ignoreNotFound)
|
||||
origState, err = s.getState(ctx, getResp, key, v, ignoreNotFound)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -728,7 +728,7 @@ func (s *store) list(ctx context.Context, key string, opts storage.ListOptions,
|
|||
}
|
||||
lastKey = kv.Key
|
||||
|
||||
data, _, err := s.transformer.TransformFromStorage(kv.Value, authenticatedDataString(kv.Key))
|
||||
data, _, err := s.transformer.TransformFromStorage(ctx, kv.Value, authenticatedDataString(kv.Key))
|
||||
if err != nil {
|
||||
return storage.NewInternalErrorf("unable to transform key %q: %v", kv.Key, err)
|
||||
}
|
||||
|
@ -828,7 +828,7 @@ func (s *store) Watch(ctx context.Context, key string, opts storage.ListOptions)
|
|||
return s.watcher.Watch(ctx, key, int64(rev), opts.Recursive, opts.ProgressNotify, opts.Predicate)
|
||||
}
|
||||
|
||||
func (s *store) getState(getResp *clientv3.GetResponse, key string, v reflect.Value, ignoreNotFound bool) (*objState, error) {
|
||||
func (s *store) getState(ctx context.Context, getResp *clientv3.GetResponse, key string, v reflect.Value, ignoreNotFound bool) (*objState, error) {
|
||||
state := &objState{
|
||||
meta: &storage.ResponseMeta{},
|
||||
}
|
||||
|
@ -847,7 +847,7 @@ func (s *store) getState(getResp *clientv3.GetResponse, key string, v reflect.Va
|
|||
return nil, err
|
||||
}
|
||||
} else {
|
||||
data, stale, err := s.transformer.TransformFromStorage(getResp.Kvs[0].Value, authenticatedDataString(key))
|
||||
data, stale, err := s.transformer.TransformFromStorage(ctx, getResp.Kvs[0].Value, authenticatedDataString(key))
|
||||
if err != nil {
|
||||
return nil, storage.NewInternalError(err.Error())
|
||||
}
|
||||
|
|
|
@ -79,24 +79,24 @@ type prefixTransformer struct {
|
|||
reads uint64
|
||||
}
|
||||
|
||||
func (p *prefixTransformer) TransformFromStorage(b []byte, ctx value.Context) ([]byte, bool, error) {
|
||||
func (p *prefixTransformer) TransformFromStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, bool, error) {
|
||||
atomic.AddUint64(&p.reads, 1)
|
||||
if ctx == nil {
|
||||
if dataCtx == nil {
|
||||
panic("no context provided")
|
||||
}
|
||||
if !bytes.HasPrefix(b, p.prefix) {
|
||||
return nil, false, fmt.Errorf("value does not have expected prefix %q: %s,", p.prefix, string(b))
|
||||
if !bytes.HasPrefix(data, p.prefix) {
|
||||
return nil, false, fmt.Errorf("value does not have expected prefix %q: %s,", p.prefix, string(data))
|
||||
}
|
||||
return bytes.TrimPrefix(b, p.prefix), p.stale, p.err
|
||||
return bytes.TrimPrefix(data, p.prefix), p.stale, p.err
|
||||
}
|
||||
func (p *prefixTransformer) TransformToStorage(b []byte, ctx value.Context) ([]byte, error) {
|
||||
if ctx == nil {
|
||||
func (p *prefixTransformer) TransformToStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, error) {
|
||||
if dataCtx == nil {
|
||||
panic("no context provided")
|
||||
}
|
||||
if len(b) > 0 {
|
||||
return append(append([]byte{}, p.prefix...), b...), p.err
|
||||
if len(data) > 0 {
|
||||
return append(append([]byte{}, p.prefix...), data...), p.err
|
||||
}
|
||||
return b, p.err
|
||||
return data, p.err
|
||||
}
|
||||
|
||||
func (p *prefixTransformer) resetReads() {
|
||||
|
@ -2231,18 +2231,18 @@ type fancyTransformer struct {
|
|||
index int
|
||||
}
|
||||
|
||||
func (t *fancyTransformer) TransformFromStorage(b []byte, ctx value.Context) ([]byte, bool, error) {
|
||||
if err := t.createObject(); err != nil {
|
||||
func (t *fancyTransformer) TransformFromStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, bool, error) {
|
||||
if err := t.createObject(ctx); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return t.transformer.TransformFromStorage(b, ctx)
|
||||
return t.transformer.TransformFromStorage(ctx, data, dataCtx)
|
||||
}
|
||||
|
||||
func (t *fancyTransformer) TransformToStorage(b []byte, ctx value.Context) ([]byte, error) {
|
||||
return t.transformer.TransformToStorage(b, ctx)
|
||||
func (t *fancyTransformer) TransformToStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, error) {
|
||||
return t.transformer.TransformToStorage(ctx, data, dataCtx)
|
||||
}
|
||||
|
||||
func (t *fancyTransformer) createObject() error {
|
||||
func (t *fancyTransformer) createObject(ctx context.Context) error {
|
||||
t.lock.Lock()
|
||||
defer t.lock.Unlock()
|
||||
|
||||
|
@ -2257,7 +2257,7 @@ func (t *fancyTransformer) createObject() error {
|
|||
},
|
||||
}
|
||||
out := &example.Pod{}
|
||||
return t.store.Create(context.TODO(), key, obj, out, 0)
|
||||
return t.store.Create(ctx, key, obj, out, 0)
|
||||
}
|
||||
|
||||
func TestConsistentList(t *testing.T) {
|
||||
|
@ -2271,7 +2271,7 @@ func TestConsistentList(t *testing.T) {
|
|||
transformer.store = store
|
||||
|
||||
for i := 0; i < 5; i++ {
|
||||
if err := transformer.createObject(); err != nil {
|
||||
if err := transformer.createObject(context.TODO()); err != nil {
|
||||
t.Fatalf("failed to create object: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -426,7 +426,7 @@ func (wc *watchChan) prepareObjs(e *event) (curObj runtime.Object, oldObj runtim
|
|||
}
|
||||
|
||||
if !e.isDeleted {
|
||||
data, _, err := wc.watcher.transformer.TransformFromStorage(e.value, authenticatedDataString(e.key))
|
||||
data, _, err := wc.watcher.transformer.TransformFromStorage(wc.ctx, e.value, authenticatedDataString(e.key))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ func (wc *watchChan) prepareObjs(e *event) (curObj runtime.Object, oldObj runtim
|
|||
// we need the object only to compute whether it was filtered out
|
||||
// before).
|
||||
if len(e.prevValue) > 0 && (e.isDeleted || !wc.acceptAll()) {
|
||||
data, _, err := wc.watcher.transformer.TransformFromStorage(e.prevValue, authenticatedDataString(e.key))
|
||||
data, _, err := wc.watcher.transformer.TransformFromStorage(wc.ctx, e.prevValue, authenticatedDataString(e.key))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ package aes
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
|
@ -52,7 +53,7 @@ func NewGCMTransformer(block cipher.Block) value.Transformer {
|
|||
return &gcm{block: block}
|
||||
}
|
||||
|
||||
func (t *gcm) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||
func (t *gcm) TransformFromStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, bool, error) {
|
||||
aead, err := cipher.NewGCM(t.block)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
|
@ -61,11 +62,11 @@ func (t *gcm) TransformFromStorage(data []byte, context value.Context) ([]byte,
|
|||
if len(data) < nonceSize {
|
||||
return nil, false, fmt.Errorf("the stored data was shorter than the required size")
|
||||
}
|
||||
result, err := aead.Open(nil, data[:nonceSize], data[nonceSize:], context.AuthenticatedData())
|
||||
result, err := aead.Open(nil, data[:nonceSize], data[nonceSize:], dataCtx.AuthenticatedData())
|
||||
return result, false, err
|
||||
}
|
||||
|
||||
func (t *gcm) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||
func (t *gcm) TransformToStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, error) {
|
||||
aead, err := cipher.NewGCM(t.block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -79,7 +80,7 @@ func (t *gcm) TransformToStorage(data []byte, context value.Context) ([]byte, er
|
|||
if n != nonceSize {
|
||||
return nil, fmt.Errorf("unable to read sufficient random bytes")
|
||||
}
|
||||
cipherText := aead.Seal(result[nonceSize:nonceSize], result[:nonceSize], data, context.AuthenticatedData())
|
||||
cipherText := aead.Seal(result[nonceSize:nonceSize], result[:nonceSize], data, dataCtx.AuthenticatedData())
|
||||
return result[:nonceSize+len(cipherText)], nil
|
||||
}
|
||||
|
||||
|
@ -100,7 +101,7 @@ var (
|
|||
errInvalidPKCS7Padding = errors.New("invalid padding on input")
|
||||
)
|
||||
|
||||
func (t *cbc) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||
func (t *cbc) TransformFromStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, bool, error) {
|
||||
blockSize := aes.BlockSize
|
||||
if len(data) < blockSize {
|
||||
return nil, false, fmt.Errorf("the stored data was shorter than the required size")
|
||||
|
@ -133,7 +134,7 @@ func (t *cbc) TransformFromStorage(data []byte, context value.Context) ([]byte,
|
|||
return result[:size], false, nil
|
||||
}
|
||||
|
||||
func (t *cbc) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||
func (t *cbc) TransformToStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, error) {
|
||||
blockSize := aes.BlockSize
|
||||
paddingSize := blockSize - (len(data) % blockSize)
|
||||
result := make([]byte, blockSize+len(data)+paddingSize)
|
||||
|
|
|
@ -18,6 +18,7 @@ package aes
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
|
@ -56,20 +57,21 @@ func TestGCMKeyRotation(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
|
||||
p := value.NewPrefixTransformers(testErr,
|
||||
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewGCMTransformer(block1)},
|
||||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewGCMTransformer(block2)},
|
||||
)
|
||||
out, err := p.TransformToStorage([]byte("firstvalue"), context)
|
||||
out, err := p.TransformToStorage(ctx, []byte("firstvalue"), dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.HasPrefix(out, []byte("first:")) {
|
||||
t.Fatalf("unexpected prefix: %q", out)
|
||||
}
|
||||
from, stale, err := p.TransformFromStorage(out, context)
|
||||
from, stale, err := p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -78,7 +80,7 @@ func TestGCMKeyRotation(t *testing.T) {
|
|||
}
|
||||
|
||||
// verify changing the context fails storage
|
||||
_, _, err = p.TransformFromStorage(out, value.DefaultContext([]byte("incorrect_context")))
|
||||
_, _, err = p.TransformFromStorage(ctx, out, value.DefaultContext([]byte("incorrect_context")))
|
||||
if err == nil {
|
||||
t.Fatalf("expected unauthenticated data")
|
||||
}
|
||||
|
@ -88,7 +90,7 @@ func TestGCMKeyRotation(t *testing.T) {
|
|||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewGCMTransformer(block2)},
|
||||
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewGCMTransformer(block1)},
|
||||
)
|
||||
from, stale, err = p.TransformFromStorage(out, context)
|
||||
from, stale, err = p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -108,20 +110,21 @@ func TestCBCKeyRotation(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
|
||||
p := value.NewPrefixTransformers(testErr,
|
||||
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewCBCTransformer(block1)},
|
||||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewCBCTransformer(block2)},
|
||||
)
|
||||
out, err := p.TransformToStorage([]byte("firstvalue"), context)
|
||||
out, err := p.TransformToStorage(ctx, []byte("firstvalue"), dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.HasPrefix(out, []byte("first:")) {
|
||||
t.Fatalf("unexpected prefix: %q", out)
|
||||
}
|
||||
from, stale, err := p.TransformFromStorage(out, context)
|
||||
from, stale, err := p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -130,7 +133,7 @@ func TestCBCKeyRotation(t *testing.T) {
|
|||
}
|
||||
|
||||
// verify changing the context fails storage
|
||||
_, _, err = p.TransformFromStorage(out, value.DefaultContext([]byte("incorrect_context")))
|
||||
_, _, err = p.TransformFromStorage(ctx, out, value.DefaultContext([]byte("incorrect_context")))
|
||||
if err != nil {
|
||||
t.Fatalf("CBC mode does not support authentication: %v", err)
|
||||
}
|
||||
|
@ -140,7 +143,7 @@ func TestCBCKeyRotation(t *testing.T) {
|
|||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewCBCTransformer(block2)},
|
||||
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewCBCTransformer(block1)},
|
||||
)
|
||||
from, stale, err = p.TransformFromStorage(out, context)
|
||||
from, stale, err = p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -199,10 +202,11 @@ func benchmarkGCMRead(b *testing.B, keyLength int, valueLength int, expectStale
|
|||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewGCMTransformer(block2)},
|
||||
)
|
||||
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||
|
||||
out, err := p.TransformToStorage(v, context)
|
||||
out, err := p.TransformToStorage(ctx, v, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -216,7 +220,7 @@ func benchmarkGCMRead(b *testing.B, keyLength int, valueLength int, expectStale
|
|||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
from, stale, err := p.TransformFromStorage(out, context)
|
||||
from, stale, err := p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -241,12 +245,13 @@ func benchmarkGCMWrite(b *testing.B, keyLength int, valueLength int) {
|
|||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewGCMTransformer(block2)},
|
||||
)
|
||||
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := p.TransformToStorage(v, context)
|
||||
_, err := p.TransformToStorage(ctx, v, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -302,10 +307,11 @@ func benchmarkCBCRead(b *testing.B, keyLength int, valueLength int, expectStale
|
|||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewCBCTransformer(block2)},
|
||||
)
|
||||
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||
|
||||
out, err := p.TransformToStorage(v, context)
|
||||
out, err := p.TransformToStorage(ctx, v, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -319,7 +325,7 @@ func benchmarkCBCRead(b *testing.B, keyLength int, valueLength int, expectStale
|
|||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
from, stale, err := p.TransformFromStorage(out, context)
|
||||
from, stale, err := p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -344,12 +350,13 @@ func benchmarkCBCWrite(b *testing.B, keyLength int, valueLength int) {
|
|||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewCBCTransformer(block2)},
|
||||
)
|
||||
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := p.TransformToStorage(v, context)
|
||||
_, err := p.TransformToStorage(ctx, v, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -373,9 +380,10 @@ func TestRoundTrip(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
tests := []struct {
|
||||
name string
|
||||
context value.Context
|
||||
dataCtx value.Context
|
||||
t value.Transformer
|
||||
}{
|
||||
{name: "GCM 16 byte key", t: NewGCMTransformer(aes16block)},
|
||||
|
@ -385,9 +393,9 @@ func TestRoundTrip(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
context := tt.context
|
||||
if context == nil {
|
||||
context = value.DefaultContext("")
|
||||
dataCtx := tt.dataCtx
|
||||
if dataCtx == nil {
|
||||
dataCtx = value.DefaultContext([]byte(""))
|
||||
}
|
||||
for _, l := range lengths {
|
||||
data := make([]byte, l)
|
||||
|
@ -396,13 +404,13 @@ func TestRoundTrip(t *testing.T) {
|
|||
}
|
||||
original := append([]byte{}, data...)
|
||||
|
||||
ciphertext, err := tt.t.TransformToStorage(data, context)
|
||||
ciphertext, err := tt.t.TransformToStorage(ctx, data, dataCtx)
|
||||
if err != nil {
|
||||
t.Errorf("TransformToStorage error = %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
result, stale, err := tt.t.TransformFromStorage(ciphertext, context)
|
||||
result, stale, err := tt.t.TransformFromStorage(ctx, ciphertext, dataCtx)
|
||||
if err != nil {
|
||||
t.Errorf("TransformFromStorage error = %v", err)
|
||||
continue
|
||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
package envelope
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
|
@ -79,7 +80,7 @@ func NewEnvelopeTransformer(envelopeService Service, cacheSize int, baseTransfor
|
|||
}
|
||||
|
||||
// TransformFromStorage decrypts data encrypted by this transformer using envelope encryption.
|
||||
func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||
func (t *envelopeTransformer) TransformFromStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, bool, error) {
|
||||
recordArrival(fromStorageLabel, time.Now())
|
||||
|
||||
// Read the 16 bit length-of-DEK encoded at the start of the encrypted DEK. 16 bits can
|
||||
|
@ -113,11 +114,11 @@ func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Co
|
|||
}
|
||||
}
|
||||
|
||||
return transformer.TransformFromStorage(encData, context)
|
||||
return transformer.TransformFromStorage(ctx, encData, dataCtx)
|
||||
}
|
||||
|
||||
// TransformToStorage encrypts data to be written to disk using envelope encryption.
|
||||
func (t *envelopeTransformer) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||
func (t *envelopeTransformer) TransformToStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, error) {
|
||||
recordArrival(toStorageLabel, time.Now())
|
||||
newKey, err := generateKey(32)
|
||||
if err != nil {
|
||||
|
@ -137,7 +138,7 @@ func (t *envelopeTransformer) TransformToStorage(data []byte, context value.Cont
|
|||
return nil, err
|
||||
}
|
||||
|
||||
result, err := transformer.TransformToStorage(data, context)
|
||||
result, err := transformer.TransformToStorage(ctx, data, dataCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package envelope
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
|
@ -101,14 +102,15 @@ func TestEnvelopeCaching(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to initialize envelope transformer: %v", err)
|
||||
}
|
||||
context := value.DefaultContext([]byte(testContextText))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte(testContextText))
|
||||
originalText := []byte(testText)
|
||||
|
||||
transformedData, err := envelopeTransformer.TransformToStorage(originalText, context)
|
||||
transformedData, err := envelopeTransformer.TransformToStorage(ctx, originalText, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatalf("envelopeTransformer: error while transforming data to storage: %s", err)
|
||||
}
|
||||
untransformedData, _, err := envelopeTransformer.TransformFromStorage(transformedData, context)
|
||||
untransformedData, _, err := envelopeTransformer.TransformFromStorage(ctx, transformedData, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatalf("could not decrypt Envelope transformer's encrypted data even once: %v", err)
|
||||
}
|
||||
|
@ -118,7 +120,7 @@ func TestEnvelopeCaching(t *testing.T) {
|
|||
|
||||
envelopeService.SetDisabledStatus(tt.simulateKMSPluginFailure)
|
||||
// Subsequent read for the same data should work fine due to caching.
|
||||
untransformedData, _, err = envelopeTransformer.TransformFromStorage(transformedData, context)
|
||||
untransformedData, _, err = envelopeTransformer.TransformFromStorage(ctx, transformedData, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatalf("could not decrypt Envelope transformer's encrypted data using just cache: %v", err)
|
||||
}
|
||||
|
@ -135,7 +137,8 @@ func TestEnvelopeCacheLimit(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to initialize envelope transformer: %v", err)
|
||||
}
|
||||
context := value.DefaultContext([]byte(testContextText))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte(testContextText))
|
||||
|
||||
transformedOutputs := map[int][]byte{}
|
||||
|
||||
|
@ -143,7 +146,7 @@ func TestEnvelopeCacheLimit(t *testing.T) {
|
|||
for i := 0; i < 2*testEnvelopeCacheSize; i++ {
|
||||
numberText := []byte(strconv.Itoa(i))
|
||||
|
||||
res, err := envelopeTransformer.TransformToStorage(numberText, context)
|
||||
res, err := envelopeTransformer.TransformToStorage(ctx, numberText, dataCtx)
|
||||
transformedOutputs[i] = res
|
||||
if err != nil {
|
||||
t.Fatalf("envelopeTransformer: error while transforming data (%v) to storage: %s", numberText, err)
|
||||
|
@ -154,7 +157,7 @@ func TestEnvelopeCacheLimit(t *testing.T) {
|
|||
for i := 0; i < 2*testEnvelopeCacheSize; i++ {
|
||||
numberText := []byte(strconv.Itoa(i))
|
||||
|
||||
output, _, err := envelopeTransformer.TransformFromStorage(transformedOutputs[i], context)
|
||||
output, _, err := envelopeTransformer.TransformFromStorage(ctx, transformedOutputs[i], dataCtx)
|
||||
if err != nil {
|
||||
t.Fatalf("envelopeTransformer: error while transforming data (%v) from storage: %s", transformedOutputs[i], err)
|
||||
}
|
||||
|
@ -202,17 +205,18 @@ func BenchmarkAESGCMRead(b *testing.B) {
|
|||
}
|
||||
|
||||
func benchmarkRead(b *testing.B, transformer value.Transformer, valueLength int) {
|
||||
context := value.DefaultContext([]byte(testContextText))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte(testContextText))
|
||||
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||
|
||||
out, err := transformer.TransformToStorage(v, context)
|
||||
out, err := transformer.TransformToStorage(ctx, v, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
from, stale, err := transformer.TransformFromStorage(out, context)
|
||||
from, stale, err := transformer.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -230,14 +234,15 @@ func TestBackwardsCompatibility(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed to initialize envelope transformer: %v", err)
|
||||
}
|
||||
context := value.DefaultContext([]byte(testContextText))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte(testContextText))
|
||||
originalText := []byte(testText)
|
||||
|
||||
transformedData, err := oldTransformToStorage(envelopeTransformerInst.(*envelopeTransformer), originalText, context)
|
||||
transformedData, err := oldTransformToStorage(ctx, envelopeTransformerInst.(*envelopeTransformer), originalText, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatalf("envelopeTransformer: error while transforming data to storage: %s", err)
|
||||
}
|
||||
untransformedData, _, err := envelopeTransformerInst.TransformFromStorage(transformedData, context)
|
||||
untransformedData, _, err := envelopeTransformerInst.TransformFromStorage(ctx, transformedData, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatalf("could not decrypt Envelope transformer's encrypted data even once: %v", err)
|
||||
}
|
||||
|
@ -247,7 +252,7 @@ func TestBackwardsCompatibility(t *testing.T) {
|
|||
|
||||
envelopeService.SetDisabledStatus(true)
|
||||
// Subsequent read for the same data should work fine due to caching.
|
||||
untransformedData, _, err = envelopeTransformerInst.TransformFromStorage(transformedData, context)
|
||||
untransformedData, _, err = envelopeTransformerInst.TransformFromStorage(ctx, transformedData, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatalf("could not decrypt Envelope transformer's encrypted data using just cache: %v", err)
|
||||
}
|
||||
|
@ -257,7 +262,7 @@ func TestBackwardsCompatibility(t *testing.T) {
|
|||
}
|
||||
|
||||
// remove after 1.13
|
||||
func oldTransformToStorage(t *envelopeTransformer, data []byte, context value.Context) ([]byte, error) {
|
||||
func oldTransformToStorage(ctx context.Context, t *envelopeTransformer, data []byte, dataCtx value.Context) ([]byte, error) {
|
||||
newKey, err := generateKey(32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -282,7 +287,7 @@ func oldTransformToStorage(t *envelopeTransformer, data []byte, context value.Co
|
|||
|
||||
prefixedData := make([]byte, len(prefix), len(data)+len(prefix))
|
||||
copy(prefixedData, prefix)
|
||||
result, err := transformer.TransformToStorage(data, context)
|
||||
result, err := transformer.TransformToStorage(ctx, data, dataCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package identity
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apiserver/pkg/storage/value"
|
||||
|
@ -34,17 +35,17 @@ func NewEncryptCheckTransformer() value.Transformer {
|
|||
}
|
||||
|
||||
// TransformFromStorage returns the input bytes if the data is not encrypted
|
||||
func (identityTransformer) TransformFromStorage(b []byte, context value.Context) ([]byte, bool, error) {
|
||||
func (identityTransformer) TransformFromStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, bool, error) {
|
||||
// identityTransformer has to return an error if the data is encoded using another transformer.
|
||||
// JSON data starts with '{'. Protobuf data has a prefix 'k8s[\x00-\xFF]'.
|
||||
// Prefix 'k8s:enc:' is reserved for encrypted data on disk.
|
||||
if bytes.HasPrefix(b, []byte("k8s:enc:")) {
|
||||
if bytes.HasPrefix(data, []byte("k8s:enc:")) {
|
||||
return []byte{}, false, fmt.Errorf("identity transformer tried to read encrypted data")
|
||||
}
|
||||
return b, false, nil
|
||||
return data, false, nil
|
||||
}
|
||||
|
||||
// TransformToStorage implements the Transformer interface for identityTransformer
|
||||
func (identityTransformer) TransformToStorage(b []byte, context value.Context) ([]byte, error) {
|
||||
return b, nil
|
||||
func (identityTransformer) TransformToStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, error) {
|
||||
return data, nil
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
|||
package secretbox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
|
||||
|
@ -41,7 +42,7 @@ func NewSecretboxTransformer(key [32]byte) value.Transformer {
|
|||
return &secretboxTransformer{key: key}
|
||||
}
|
||||
|
||||
func (t *secretboxTransformer) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||
func (t *secretboxTransformer) TransformFromStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, bool, error) {
|
||||
if len(data) < (secretbox.Overhead + nonceSize) {
|
||||
return nil, false, fmt.Errorf("the stored data was shorter than the required size")
|
||||
}
|
||||
|
@ -56,7 +57,7 @@ func (t *secretboxTransformer) TransformFromStorage(data []byte, context value.C
|
|||
return result, false, nil
|
||||
}
|
||||
|
||||
func (t *secretboxTransformer) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||
func (t *secretboxTransformer) TransformToStorage(ctx context.Context, data []byte, dataCtx value.Context) ([]byte, error) {
|
||||
var nonce [nonceSize]byte
|
||||
n, err := rand.Read(nonce[:])
|
||||
if err != nil {
|
||||
|
|
|
@ -18,6 +18,7 @@ package secretbox
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
@ -35,20 +36,21 @@ var (
|
|||
|
||||
func TestSecretboxKeyRotation(t *testing.T) {
|
||||
testErr := fmt.Errorf("test error")
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
|
||||
p := value.NewPrefixTransformers(testErr,
|
||||
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)},
|
||||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)},
|
||||
)
|
||||
out, err := p.TransformToStorage([]byte("firstvalue"), context)
|
||||
out, err := p.TransformToStorage(ctx, []byte("firstvalue"), dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.HasPrefix(out, []byte("first:")) {
|
||||
t.Fatalf("unexpected prefix: %q", out)
|
||||
}
|
||||
from, stale, err := p.TransformFromStorage(out, context)
|
||||
from, stale, err := p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -58,7 +60,7 @@ func TestSecretboxKeyRotation(t *testing.T) {
|
|||
|
||||
// verify changing the context does not fails storage
|
||||
// Secretbox is not currently an authenticating store
|
||||
_, _, err = p.TransformFromStorage(out, value.DefaultContext([]byte("incorrect_context")))
|
||||
_, _, err = p.TransformFromStorage(ctx, out, value.DefaultContext([]byte("incorrect_context")))
|
||||
if err != nil {
|
||||
t.Fatalf("secretbox is not authenticated")
|
||||
}
|
||||
|
@ -68,7 +70,7 @@ func TestSecretboxKeyRotation(t *testing.T) {
|
|||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)},
|
||||
value.PrefixTransformer{Prefix: []byte("first:"), Transformer: NewSecretboxTransformer(key1)},
|
||||
)
|
||||
from, stale, err = p.TransformFromStorage(out, context)
|
||||
from, stale, err = p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -117,10 +119,11 @@ func benchmarkSecretboxRead(b *testing.B, keyLength int, valueLength int, expect
|
|||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)},
|
||||
)
|
||||
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||
|
||||
out, err := p.TransformToStorage(v, context)
|
||||
out, err := p.TransformToStorage(ctx, v, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -134,7 +137,7 @@ func benchmarkSecretboxRead(b *testing.B, keyLength int, valueLength int, expect
|
|||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
from, stale, err := p.TransformFromStorage(out, context)
|
||||
from, stale, err := p.TransformFromStorage(ctx, out, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -151,12 +154,13 @@ func benchmarkSecretboxWrite(b *testing.B, keyLength int, valueLength int) {
|
|||
value.PrefixTransformer{Prefix: []byte("second:"), Transformer: NewSecretboxTransformer(key2)},
|
||||
)
|
||||
|
||||
context := value.DefaultContext([]byte("authenticated_data"))
|
||||
ctx := context.Background()
|
||||
dataCtx := value.DefaultContext([]byte("authenticated_data"))
|
||||
v := bytes.Repeat([]byte("0123456789abcdef"), valueLength/16)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err := p.TransformToStorage(v, context)
|
||||
_, err := p.TransformToStorage(ctx, v, dataCtx)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
@ -167,18 +171,19 @@ func benchmarkSecretboxWrite(b *testing.B, keyLength int, valueLength int) {
|
|||
func TestRoundTrip(t *testing.T) {
|
||||
lengths := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 128, 1024}
|
||||
|
||||
ctx := context.Background()
|
||||
tests := []struct {
|
||||
name string
|
||||
context value.Context
|
||||
dataCtx value.Context
|
||||
t value.Transformer
|
||||
}{
|
||||
{name: "Secretbox 32 byte key", t: NewSecretboxTransformer(key1)},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
context := tt.context
|
||||
if context == nil {
|
||||
context = value.DefaultContext("")
|
||||
dataCtx := tt.dataCtx
|
||||
if dataCtx == nil {
|
||||
dataCtx = value.DefaultContext([]byte(""))
|
||||
}
|
||||
for _, l := range lengths {
|
||||
data := make([]byte, l)
|
||||
|
@ -187,13 +192,13 @@ func TestRoundTrip(t *testing.T) {
|
|||
}
|
||||
original := append([]byte{}, data...)
|
||||
|
||||
ciphertext, err := tt.t.TransformToStorage(data, context)
|
||||
ciphertext, err := tt.t.TransformToStorage(ctx, data, dataCtx)
|
||||
if err != nil {
|
||||
t.Errorf("TransformToStorage error = %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
result, stale, err := tt.t.TransformFromStorage(ciphertext, context)
|
||||
result, stale, err := tt.t.TransformFromStorage(ctx, ciphertext, dataCtx)
|
||||
if err != nil {
|
||||
t.Errorf("TransformFromStorage error = %v", err)
|
||||
continue
|
||||
|
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package value
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -102,8 +103,8 @@ func TestTotals(t *testing.T) {
|
|||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.desc, func(t *testing.T) {
|
||||
tt.prefix.TransformToStorage([]byte("value"), nil)
|
||||
tt.prefix.TransformFromStorage([]byte("k8s:enc:kms:v1:value"), nil)
|
||||
tt.prefix.TransformToStorage(context.Background(), []byte("value"), nil)
|
||||
tt.prefix.TransformFromStorage(context.Background(), []byte("k8s:enc:kms:v1:value"), nil)
|
||||
defer transformerOperationsTotal.Reset()
|
||||
if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tt.want), tt.metrics...); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
@ -19,6 +19,7 @@ package value
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -45,9 +46,9 @@ type Transformer interface {
|
|||
// TransformFromStorage may transform the provided data from its underlying storage representation or return an error.
|
||||
// Stale is true if the object on disk is stale and a write to etcd should be issued, even if the contents of the object
|
||||
// have not changed.
|
||||
TransformFromStorage(data []byte, context Context) (out []byte, stale bool, err error)
|
||||
TransformFromStorage(ctx context.Context, data []byte, dataCtx Context) (out []byte, stale bool, err error)
|
||||
// TransformToStorage may transform the provided data into the appropriate form in storage or return an error.
|
||||
TransformToStorage(data []byte, context Context) (out []byte, err error)
|
||||
TransformToStorage(ctx context.Context, data []byte, dataCtx Context) (out []byte, err error)
|
||||
}
|
||||
|
||||
type identityTransformer struct{}
|
||||
|
@ -55,11 +56,11 @@ type identityTransformer struct{}
|
|||
// IdentityTransformer performs no transformation of the provided data.
|
||||
var IdentityTransformer Transformer = identityTransformer{}
|
||||
|
||||
func (identityTransformer) TransformFromStorage(b []byte, ctx Context) ([]byte, bool, error) {
|
||||
return b, false, nil
|
||||
func (identityTransformer) TransformFromStorage(ctx context.Context, data []byte, dataCtx Context) ([]byte, bool, error) {
|
||||
return data, false, nil
|
||||
}
|
||||
func (identityTransformer) TransformToStorage(b []byte, ctx Context) ([]byte, error) {
|
||||
return b, nil
|
||||
func (identityTransformer) TransformToStorage(ctx context.Context, data []byte, dataCtx Context) ([]byte, error) {
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// DefaultContext is a simple implementation of Context for a slice of bytes.
|
||||
|
@ -86,17 +87,17 @@ func (t *MutableTransformer) Set(transformer Transformer) {
|
|||
t.lock.Unlock()
|
||||
}
|
||||
|
||||
func (t *MutableTransformer) TransformFromStorage(data []byte, context Context) (out []byte, stale bool, err error) {
|
||||
func (t *MutableTransformer) TransformFromStorage(ctx context.Context, data []byte, dataCtx Context) (out []byte, stale bool, err error) {
|
||||
t.lock.RLock()
|
||||
transformer := t.transformer
|
||||
t.lock.RUnlock()
|
||||
return transformer.TransformFromStorage(data, context)
|
||||
return transformer.TransformFromStorage(ctx, data, dataCtx)
|
||||
}
|
||||
func (t *MutableTransformer) TransformToStorage(data []byte, context Context) (out []byte, err error) {
|
||||
func (t *MutableTransformer) TransformToStorage(ctx context.Context, data []byte, dataCtx Context) (out []byte, err error) {
|
||||
t.lock.RLock()
|
||||
transformer := t.transformer
|
||||
t.lock.RUnlock()
|
||||
return transformer.TransformToStorage(data, context)
|
||||
return transformer.TransformToStorage(ctx, data, dataCtx)
|
||||
}
|
||||
|
||||
// PrefixTransformer holds a transformer interface and the prefix that the transformation is located under.
|
||||
|
@ -129,12 +130,12 @@ func NewPrefixTransformers(err error, transformers ...PrefixTransformer) Transfo
|
|||
// TransformFromStorage finds the first transformer with a prefix matching the provided data and returns
|
||||
// the result of transforming the value. It will always mark any transformation as stale that is not using
|
||||
// the first transformer.
|
||||
func (t *prefixTransformers) TransformFromStorage(data []byte, context Context) ([]byte, bool, error) {
|
||||
func (t *prefixTransformers) TransformFromStorage(ctx context.Context, data []byte, dataCtx Context) ([]byte, bool, error) {
|
||||
start := time.Now()
|
||||
var errs []error
|
||||
for i, transformer := range t.transformers {
|
||||
if bytes.HasPrefix(data, transformer.Prefix) {
|
||||
result, stale, err := transformer.Transformer.TransformFromStorage(data[len(transformer.Prefix):], context)
|
||||
result, stale, err := transformer.Transformer.TransformFromStorage(ctx, data[len(transformer.Prefix):], dataCtx)
|
||||
// To migrate away from encryption, user can specify an identity transformer higher up
|
||||
// (in the config file) than the encryption transformer. In that scenario, the identity transformer needs to
|
||||
// identify (during reads from disk) whether the data being read is encrypted or not. If the data is encrypted,
|
||||
|
@ -194,12 +195,12 @@ func (t *prefixTransformers) TransformFromStorage(data []byte, context Context)
|
|||
}
|
||||
|
||||
// TransformToStorage uses the first transformer and adds its prefix to the data.
|
||||
func (t *prefixTransformers) TransformToStorage(data []byte, context Context) ([]byte, error) {
|
||||
func (t *prefixTransformers) TransformToStorage(ctx context.Context, data []byte, dataCtx Context) ([]byte, error) {
|
||||
start := time.Now()
|
||||
transformer := t.transformers[0]
|
||||
prefixedData := make([]byte, len(transformer.Prefix), len(data)+len(transformer.Prefix))
|
||||
copy(prefixedData, transformer.Prefix)
|
||||
result, err := transformer.Transformer.TransformToStorage(data, context)
|
||||
result, err := transformer.Transformer.TransformToStorage(ctx, data, dataCtx)
|
||||
RecordTransformation("to_storage", string(transformer.Prefix), start, err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -18,6 +18,7 @@ package value
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -33,13 +34,13 @@ type testTransformer struct {
|
|||
receivedFrom, receivedTo []byte
|
||||
}
|
||||
|
||||
func (t *testTransformer) TransformFromStorage(from []byte, context Context) (data []byte, stale bool, err error) {
|
||||
t.receivedFrom = from
|
||||
func (t *testTransformer) TransformFromStorage(ctx context.Context, data []byte, dataCtx Context) (out []byte, stale bool, err error) {
|
||||
t.receivedFrom = data
|
||||
return t.from, t.stale, t.err
|
||||
}
|
||||
|
||||
func (t *testTransformer) TransformToStorage(to []byte, context Context) (data []byte, err error) {
|
||||
t.receivedTo = to
|
||||
func (t *testTransformer) TransformToStorage(ctx context.Context, data []byte, dataCtx Context) (out []byte, err error) {
|
||||
t.receivedTo = data
|
||||
return t.to, t.err
|
||||
}
|
||||
|
||||
|
@ -68,7 +69,7 @@ func TestPrefixFrom(t *testing.T) {
|
|||
{[]byte("stale:value"), []byte("value3"), true, nil, 3},
|
||||
}
|
||||
for i, test := range testCases {
|
||||
got, stale, err := p.TransformFromStorage(test.input, nil)
|
||||
got, stale, err := p.TransformFromStorage(context.Background(), test.input, nil)
|
||||
if err != test.err || stale != test.stale || !bytes.Equal(got, test.expect) {
|
||||
t.Errorf("%d: unexpected out: %q %t %#v", i, string(got), stale, err)
|
||||
continue
|
||||
|
@ -93,7 +94,7 @@ func TestPrefixTo(t *testing.T) {
|
|||
}
|
||||
for i, test := range testCases {
|
||||
p := NewPrefixTransformers(testErr, test.transformers...)
|
||||
got, err := p.TransformToStorage([]byte("value"), nil)
|
||||
got, err := p.TransformToStorage(context.Background(), []byte("value"), nil)
|
||||
if err != test.err || !bytes.Equal(got, test.expect) {
|
||||
t.Errorf("%d: unexpected out: %q %#v", i, string(got), err)
|
||||
continue
|
||||
|
@ -183,7 +184,7 @@ func TestPrefixFromMetrics(t *testing.T) {
|
|||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
tc.prefix.TransformFromStorage(tc.input, nil)
|
||||
tc.prefix.TransformFromStorage(context.Background(), tc.input, nil)
|
||||
defer transformerOperationsTotal.Reset()
|
||||
if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tc.want), tc.metrics...); err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -241,7 +242,7 @@ func TestPrefixToMetrics(t *testing.T) {
|
|||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
tc.prefix.TransformToStorage(tc.input, nil)
|
||||
tc.prefix.TransformToStorage(context.Background(), tc.input, nil)
|
||||
defer transformerOperationsTotal.Reset()
|
||||
if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tc.want), tc.metrics...); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
Loading…
Reference in New Issue