From e442eafb33e3e9a22097ce6fbf4fa130be6d9ae5 Mon Sep 17 00:00:00 2001 From: Anish Ramasekar Date: Wed, 16 Mar 2022 17:54:10 +0000 Subject: [PATCH] feat: prepare KMS data encryption for migration to AES-GCM Signed-off-by: Anish Ramasekar Co-authored-by: Monis Khan Signed-off-by: Anish Ramasekar Kubernetes-commit: 90b42f91fd904b71fd52ca9ae55a5de73e6b779a --- pkg/server/options/encryptionconfig/config.go | 34 ++++++++++++++++++- pkg/storage/value/encrypt/aes/aes.go | 4 +-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/pkg/server/options/encryptionconfig/config.go b/pkg/server/options/encryptionconfig/config.go index fd0c95c22..6b7857e35 100644 --- a/pkg/server/options/encryptionconfig/config.go +++ b/pkg/server/options/encryptionconfig/config.go @@ -17,6 +17,7 @@ limitations under the License. package encryptionconfig import ( + "context" "crypto/aes" "crypto/cipher" "encoding/base64" @@ -32,6 +33,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/serializer" + utilerrors "k8s.io/apimachinery/pkg/util/errors" apiserverconfig "k8s.io/apiserver/pkg/apis/config" apiserverconfigv1 "k8s.io/apiserver/pkg/apis/config/v1" "k8s.io/apiserver/pkg/apis/config/validation" @@ -365,7 +367,13 @@ func secretboxPrefixTransformer(config *apiserverconfig.SecretboxConfiguration) } func envelopePrefixTransformer(config *apiserverconfig.KMSConfiguration, envelopeService envelope.Service, prefix string) (value.PrefixTransformer, error) { - envelopeTransformer, err := envelope.NewEnvelopeTransformer(envelopeService, int(*config.CacheSize), aestransformer.NewCBCTransformer) + baseTransformerFunc := func(block cipher.Block) value.Transformer { + // v1.24: write using AES-CBC only but support reads via AES-CBC and AES-GCM (so we can move to AES-GCM) + // TODO(aramase): swap this ordering in v1.25 + return unionTransformers{aestransformer.NewCBCTransformer(block), aestransformer.NewGCMTransformer(block)} + } + + envelopeTransformer, err := envelope.NewEnvelopeTransformer(envelopeService, int(*config.CacheSize), baseTransformerFunc) if err != nil { return value.PrefixTransformer{}, err } @@ -374,3 +382,27 @@ func envelopePrefixTransformer(config *apiserverconfig.KMSConfiguration, envelop Prefix: []byte(prefix + config.Name + ":"), }, nil } + +type unionTransformers []value.Transformer + +func (u unionTransformers) TransformFromStorage(ctx context.Context, data []byte, dataCtx value.Context) (out []byte, stale bool, err error) { + var errs []error + for i, transformer := range u { + result, stale, err := transformer.TransformFromStorage(ctx, data, dataCtx) + if err != nil { + errs = append(errs, err) + continue + } + // when i != 0, we have transformed the data from storage using the new transformer, + // we want to issue a write to etcd even if the contents of the data haven't changed + return result, stale || i != 0, nil + } + if err := utilerrors.Reduce(utilerrors.NewAggregate(errs)); err != nil { + return nil, false, err + } + return nil, false, fmt.Errorf("unionTransformers: unable to transform from storage") +} + +func (u unionTransformers) TransformToStorage(ctx context.Context, data []byte, dataCtx value.Context) (out []byte, err error) { + return u[0].TransformToStorage(ctx, data, dataCtx) +} diff --git a/pkg/storage/value/encrypt/aes/aes.go b/pkg/storage/value/encrypt/aes/aes.go index 1e7047f8f..69930c039 100644 --- a/pkg/storage/value/encrypt/aes/aes.go +++ b/pkg/storage/value/encrypt/aes/aes.go @@ -96,7 +96,7 @@ func NewCBCTransformer(block cipher.Block) value.Transformer { } var ( - errInvalidBlockSize = fmt.Errorf("the stored data is not a multiple of the block size") + ErrInvalidBlockSize = fmt.Errorf("the stored data is not a multiple of the block size") errInvalidPKCS7Data = errors.New("invalid PKCS7 data (empty or not padded)") errInvalidPKCS7Padding = errors.New("invalid padding on input") ) @@ -110,7 +110,7 @@ func (t *cbc) TransformFromStorage(ctx context.Context, data []byte, dataCtx val data = data[blockSize:] if len(data)%blockSize != 0 { - return nil, false, errInvalidBlockSize + return nil, false, ErrInvalidBlockSize } result := make([]byte, len(data))