From 27312feb9983c18d1daf00afba788727d024cdd0 Mon Sep 17 00:00:00 2001 From: Steve Kuznetsov Date: Thu, 17 Feb 2022 07:29:44 -0800 Subject: [PATCH] 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 --- .../options/encryptionconfig/config_test.go | 23 +++---- .../apiserver/pkg/storage/etcd3/store.go | 20 +++---- .../apiserver/pkg/storage/etcd3/store_test.go | 38 ++++++------ .../apiserver/pkg/storage/etcd3/watcher.go | 4 +- .../pkg/storage/value/encrypt/aes/aes.go | 13 ++-- .../pkg/storage/value/encrypt/aes/aes_test.go | 60 +++++++++++-------- .../value/encrypt/envelope/envelope.go | 9 +-- .../value/encrypt/envelope/envelope_test.go | 37 +++++++----- .../value/encrypt/identity/identity.go | 11 ++-- .../value/encrypt/secretbox/secretbox.go | 5 +- .../value/encrypt/secretbox/secretbox_test.go | 37 +++++++----- .../pkg/storage/value/metrics_test.go | 5 +- .../pkg/storage/value/transformer.go | 29 ++++----- .../pkg/storage/value/transformer_test.go | 17 +++--- .../controlplane/kms_transformation_test.go | 6 +- .../secrets_transformation_test.go | 9 +-- .../controlplane/transformation_testcase.go | 7 ++- 17 files changed, 180 insertions(+), 150 deletions(-) diff --git a/staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config_test.go b/staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config_test.go index 3b4ece8e3a8..95fcf8e6e8d 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/options/encryptionconfig/config_test.go @@ -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) } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go index d7fe75eeaca..d263148cac8 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store.go @@ -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()) } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go index e22228534dc..6654f0bfdc5 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/store_test.go @@ -35,7 +35,7 @@ import ( clientv3 "go.etcd.io/etcd/client/v3" "google.golang.org/grpc/grpclog" - apitesting "k8s.io/apimachinery/pkg/api/apitesting" + "k8s.io/apimachinery/pkg/api/apitesting" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/conversion" @@ -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() { @@ -2210,18 +2210,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() @@ -2236,7 +2236,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) { @@ -2250,7 +2250,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) } } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go index d37991a0523..3241970f6e7 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/etcd3/watcher.go @@ -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 } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes.go index daa82f711fe..1e7047f8f62 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes.go @@ -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) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go index aea755423a5..37564c1db0d 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/aes/aes_test.go @@ -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 diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go index 357ea058237..9173eb06525 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go @@ -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 } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope_test.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope_test.go index 08676ddf2b4..4f030772eb9 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope_test.go @@ -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 } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/identity/identity.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/identity/identity.go index e322bd9b17c..7bdd5f6823e 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/identity/identity.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/identity/identity.go @@ -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 } diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox.go index 0eaa6282457..9aec8acd39e 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox.go @@ -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 { diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go index 4d87708b0d8..04dc841f4ad 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/encrypt/secretbox/secretbox_test.go @@ -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 diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/metrics_test.go b/staging/src/k8s.io/apiserver/pkg/storage/value/metrics_test.go index 0fc4834bc91..2a84e558ea7 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/metrics_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/metrics_test.go @@ -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) diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go b/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go index 3bc41cd9a24..3c0ca7a60da 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/transformer.go @@ -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 diff --git a/staging/src/k8s.io/apiserver/pkg/storage/value/transformer_test.go b/staging/src/k8s.io/apiserver/pkg/storage/value/transformer_test.go index f044da4fbbf..c204c8c8cc9 100644 --- a/staging/src/k8s.io/apiserver/pkg/storage/value/transformer_test.go +++ b/staging/src/k8s.io/apiserver/pkg/storage/value/transformer_test.go @@ -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) diff --git a/test/integration/controlplane/kms_transformation_test.go b/test/integration/controlplane/kms_transformation_test.go index 7d94183a7e0..6640f695093 100644 --- a/test/integration/controlplane/kms_transformation_test.go +++ b/test/integration/controlplane/kms_transformation_test.go @@ -24,7 +24,6 @@ import ( "context" "crypto/aes" "encoding/binary" - "fmt" "net/http" "strings" @@ -83,9 +82,10 @@ func (r envelope) plainTextPayload(secretETCDPath string) ([]byte, error) { return nil, fmt.Errorf("failed to initialize AES Cipher: %v", err) } // etcd path of the key is used as the authenticated context - need to pass it to decrypt - ctx := value.DefaultContext([]byte(secretETCDPath)) + ctx := context.Background() + dataCtx := value.DefaultContext([]byte(secretETCDPath)) aescbcTransformer := aestransformer.NewCBCTransformer(block) - plainSecret, _, err := aescbcTransformer.TransformFromStorage(r.cipherTextPayload(), ctx) + plainSecret, _, err := aescbcTransformer.TransformFromStorage(ctx, r.cipherTextPayload(), dataCtx) if err != nil { return nil, fmt.Errorf("failed to transform from storage via AESCBC, err: %v", err) } diff --git a/test/integration/controlplane/secrets_transformation_test.go b/test/integration/controlplane/secrets_transformation_test.go index 2f405bb6a8c..6c0090dbab2 100644 --- a/test/integration/controlplane/secrets_transformation_test.go +++ b/test/integration/controlplane/secrets_transformation_test.go @@ -17,6 +17,7 @@ limitations under the License. package controlplane import ( + "context" "crypto/aes" "crypto/cipher" "encoding/base64" @@ -131,7 +132,7 @@ func runBenchmark(b *testing.B, transformerConfig string) { test.printMetrics() } -func unSealWithGCMTransformer(cipherText []byte, ctx value.Context, +func unSealWithGCMTransformer(ctx context.Context, cipherText []byte, dataCtx value.Context, transformerConfig apiserverconfigv1.ProviderConfiguration) ([]byte, error) { block, err := newAESCipher(transformerConfig.AESGCM.Keys[0].Secret) @@ -141,7 +142,7 @@ func unSealWithGCMTransformer(cipherText []byte, ctx value.Context, gcmTransformer := aestransformer.NewGCMTransformer(block) - clearText, _, err := gcmTransformer.TransformFromStorage(cipherText, ctx) + clearText, _, err := gcmTransformer.TransformFromStorage(ctx, cipherText, dataCtx) if err != nil { return nil, fmt.Errorf("failed to decypt secret: %v", err) } @@ -149,7 +150,7 @@ func unSealWithGCMTransformer(cipherText []byte, ctx value.Context, return clearText, nil } -func unSealWithCBCTransformer(cipherText []byte, ctx value.Context, +func unSealWithCBCTransformer(ctx context.Context, cipherText []byte, dataCtx value.Context, transformerConfig apiserverconfigv1.ProviderConfiguration) ([]byte, error) { block, err := newAESCipher(transformerConfig.AESCBC.Keys[0].Secret) @@ -159,7 +160,7 @@ func unSealWithCBCTransformer(cipherText []byte, ctx value.Context, cbcTransformer := aestransformer.NewCBCTransformer(block) - clearText, _, err := cbcTransformer.TransformFromStorage(cipherText, ctx) + clearText, _, err := cbcTransformer.TransformFromStorage(ctx, cipherText, dataCtx) if err != nil { return nil, fmt.Errorf("failed to decypt secret: %v", err) } diff --git a/test/integration/controlplane/transformation_testcase.go b/test/integration/controlplane/transformation_testcase.go index dc3d2f0b4d7..82e8d8b0bc0 100644 --- a/test/integration/controlplane/transformation_testcase.go +++ b/test/integration/controlplane/transformation_testcase.go @@ -52,7 +52,7 @@ const ( metricsPrefix = "apiserver_storage_" ) -type unSealSecret func(cipherText []byte, ctx value.Context, config apiserverconfigv1.ProviderConfiguration) ([]byte, error) +type unSealSecret func(ctx context.Context, cipherText []byte, dataCtx value.Context, config apiserverconfigv1.ProviderConfiguration) ([]byte, error) type transformTest struct { logger kubeapiservertesting.Logger @@ -115,14 +115,15 @@ func (e *transformTest) run(unSealSecretFunc unSealSecret, expectedEnvelopePrefi } // etcd path of the key is used as the authenticated context - need to pass it to decrypt - ctx := value.DefaultContext([]byte(e.getETCDPath())) + ctx := context.Background() + dataCtx := value.DefaultContext([]byte(e.getETCDPath())) // Envelope header precedes the cipherTextPayload sealedData := response.Kvs[0].Value[len(expectedEnvelopePrefix):] transformerConfig, err := e.getEncryptionConfig() if err != nil { e.logger.Errorf("failed to parse transformer config: %v", err) } - v, err := unSealSecretFunc(sealedData, ctx, *transformerConfig) + v, err := unSealSecretFunc(ctx, sealedData, dataCtx, *transformerConfig) if err != nil { e.logger.Errorf("failed to unseal secret: %v", err) return