diff --git a/go.mod b/go.mod index 8670526b4..055a6ee32 100644 --- a/go.mod +++ b/go.mod @@ -44,10 +44,10 @@ require ( gopkg.in/square/go-jose.v2 v2.2.2 k8s.io/api v0.0.0-20230112183318-59fcd23597fd k8s.io/apimachinery v0.0.0-20230112182327-235f5123de4a - k8s.io/client-go v0.0.0-20230113000324-241dfe363021 + k8s.io/client-go v0.0.0-20230116012449-228b004f4a92 k8s.io/component-base v0.0.0-20230112192324-33f62c7b2818 k8s.io/klog/v2 v2.80.1 - k8s.io/kms v0.0.0-20230107081413-fd373b9a5aa5 + k8s.io/kms v0.0.0-20230117203143-407acb40b4f8 k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596 k8s.io/utils v0.0.0-20221107191617-1a15be271d1d sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.35 @@ -124,7 +124,7 @@ require ( replace ( k8s.io/api => k8s.io/api v0.0.0-20230112183318-59fcd23597fd k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20230112182327-235f5123de4a - k8s.io/client-go => k8s.io/client-go v0.0.0-20230113000324-241dfe363021 + k8s.io/client-go => k8s.io/client-go v0.0.0-20230116012449-228b004f4a92 k8s.io/component-base => k8s.io/component-base v0.0.0-20230112192324-33f62c7b2818 - k8s.io/kms => k8s.io/kms v0.0.0-20230107081413-fd373b9a5aa5 + k8s.io/kms => k8s.io/kms v0.0.0-20230117203143-407acb40b4f8 ) diff --git a/go.sum b/go.sum index 9a7523b48..6aed8b805 100644 --- a/go.sum +++ b/go.sum @@ -994,14 +994,14 @@ k8s.io/api v0.0.0-20230112183318-59fcd23597fd h1:Y/vljv797SrqMUZ4KwQaIDcz+lecu07 k8s.io/api v0.0.0-20230112183318-59fcd23597fd/go.mod h1:K1fbar68K91an+8RbH9eJWJRnoXQ5rugf6J5wsGMMWg= k8s.io/apimachinery v0.0.0-20230112182327-235f5123de4a h1:ztM2zo2xo0w+WBKGJ/V/TnavQfbZnADVA5s4p3LGDpo= k8s.io/apimachinery v0.0.0-20230112182327-235f5123de4a/go.mod h1:Kq932aOItR+rI/aiAVDXxxdRFNf0eLnI0gZmXJ6hl3o= -k8s.io/client-go v0.0.0-20230113000324-241dfe363021 h1:ApG3Cidw9Kn6WYh/56MjFtrK74S9h/cbYF2bPf6AEVY= -k8s.io/client-go v0.0.0-20230113000324-241dfe363021/go.mod h1:yGx/VWWKjooWFIfibkKEt0Vf6gG9wDALmEzcgJv5jPs= +k8s.io/client-go v0.0.0-20230116012449-228b004f4a92 h1:ufPl+2CEizC47k/ptJxbryxNF+EpJPG3aDIO6qUkXFE= +k8s.io/client-go v0.0.0-20230116012449-228b004f4a92/go.mod h1:yGx/VWWKjooWFIfibkKEt0Vf6gG9wDALmEzcgJv5jPs= k8s.io/component-base v0.0.0-20230112192324-33f62c7b2818 h1:sZ5awJx2PpXaOwNSEu8Pq6zovP1+YG/nWZpagmpDRcs= k8s.io/component-base v0.0.0-20230112192324-33f62c7b2818/go.mod h1:6IeVfLNdhjJkJFQHYMuwk7dgkOLA3Pt+Y7j7Md1d+CA= k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kms v0.0.0-20230107081413-fd373b9a5aa5 h1:lIrmdsSdF5Z8YODvH6hozkg5tUWRAtojzj1gyqwk5sc= -k8s.io/kms v0.0.0-20230107081413-fd373b9a5aa5/go.mod h1:8nNxRLuUXpWlFuo+Xt4yUheyyZDJ/DY6Ypd0EEmXypg= +k8s.io/kms v0.0.0-20230117203143-407acb40b4f8 h1:oYOLi+NfW2BoplN1w5lO0NdBaQpV5Oe8C2XmFkjFi8g= +k8s.io/kms v0.0.0-20230117203143-407acb40b4f8/go.mod h1:ND+WCT0K/L1kWk7CwCkd4wRBKmtGDBjslBC6X8QZEuU= k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596 h1:8cNCQs+WqqnSpZ7y0LMQPKD+RZUHU17VqLPMW3qxnxc= k8s.io/kube-openapi v0.0.0-20230109183929-3758b55a6596/go.mod h1:/BYxry62FuDzmI+i9B+X2pqfySRmSOW2ARmj5Zbqhj0= k8s.io/utils v0.0.0-20221107191617-1a15be271d1d h1:0Smp/HP1OH4Rvhe+4B8nWGERtlqAGSftbSbbmm45oFs= diff --git a/pkg/server/options/encryptionconfig/config.go b/pkg/server/options/encryptionconfig/config.go index 15c04898f..9adb5dd86 100644 --- a/pkg/server/options/encryptionconfig/config.go +++ b/pkg/server/options/encryptionconfig/config.go @@ -48,6 +48,7 @@ import ( "k8s.io/apiserver/pkg/storage/value/encrypt/identity" "k8s.io/apiserver/pkg/storage/value/encrypt/secretbox" utilfeature "k8s.io/apiserver/pkg/util/feature" + kmsservice "k8s.io/kms/service" ) const ( @@ -85,7 +86,7 @@ type kmsPluginProbe struct { type kmsv2PluginProbe struct { name string ttl time.Duration - service envelopekmsv2.Service + service kmsservice.Service lastResponse *kmsPluginHealthzResponse l *sync.Mutex } @@ -284,7 +285,7 @@ func (h *kmsv2PluginProbe) check(ctx context.Context) error { } // isKMSv2ProviderHealthy checks if the KMSv2-Plugin is healthy. -func isKMSv2ProviderHealthy(name string, response *envelopekmsv2.StatusResponse) error { +func isKMSv2ProviderHealthy(name string, response *kmsservice.StatusResponse) error { var errs []error if response.Healthz != "ok" { errs = append(errs, fmt.Errorf("got unexpected healthz status: %s", response.Healthz)) diff --git a/pkg/server/options/encryptionconfig/config_test.go b/pkg/server/options/encryptionconfig/config_test.go index 767bfc6c1..3e82a00f3 100644 --- a/pkg/server/options/encryptionconfig/config_test.go +++ b/pkg/server/options/encryptionconfig/config_test.go @@ -32,9 +32,9 @@ import ( "k8s.io/apiserver/pkg/features" "k8s.io/apiserver/pkg/storage/value" "k8s.io/apiserver/pkg/storage/value/encrypt/envelope" - envelopekmsv2 "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/kmsv2" utilfeature "k8s.io/apiserver/pkg/util/feature" featuregatetesting "k8s.io/component-base/featuregate/testing" + kmsservice "k8s.io/kms/service" ) const ( @@ -68,28 +68,28 @@ type testKMSv2EnvelopeService struct { err error } -func (t *testKMSv2EnvelopeService) Decrypt(ctx context.Context, uid string, req *envelopekmsv2.DecryptRequest) ([]byte, error) { +func (t *testKMSv2EnvelopeService) Decrypt(ctx context.Context, uid string, req *kmsservice.DecryptRequest) ([]byte, error) { if t.err != nil { return nil, t.err } return base64.StdEncoding.DecodeString(string(req.Ciphertext)) } -func (t *testKMSv2EnvelopeService) Encrypt(ctx context.Context, uid string, data []byte) (*envelopekmsv2.EncryptResponse, error) { +func (t *testKMSv2EnvelopeService) Encrypt(ctx context.Context, uid string, data []byte) (*kmsservice.EncryptResponse, error) { if t.err != nil { return nil, t.err } - return &envelopekmsv2.EncryptResponse{ + return &kmsservice.EncryptResponse{ Ciphertext: []byte(base64.StdEncoding.EncodeToString(data)), KeyID: "1", }, nil } -func (t *testKMSv2EnvelopeService) Status(ctx context.Context) (*envelopekmsv2.StatusResponse, error) { +func (t *testKMSv2EnvelopeService) Status(ctx context.Context) (*kmsservice.StatusResponse, error) { if t.err != nil { return nil, t.err } - return &envelopekmsv2.StatusResponse{Healthz: "ok", KeyID: "1", Version: "v2alpha1"}, nil + return &kmsservice.StatusResponse{Healthz: "ok", KeyID: "1", Version: "v2alpha1"}, nil } // The factory method to create mock envelope service. @@ -103,12 +103,12 @@ func newMockErrorEnvelopeService(endpoint string, timeout time.Duration) (envelo } // The factory method to create mock envelope kmsv2 service. -func newMockEnvelopeKMSv2Service(ctx context.Context, endpoint string, timeout time.Duration) (envelopekmsv2.Service, error) { +func newMockEnvelopeKMSv2Service(ctx context.Context, endpoint string, timeout time.Duration) (kmsservice.Service, error) { return &testKMSv2EnvelopeService{nil}, nil } // The factory method to create mock envelope kmsv2 service which always returns error. -func newMockErrorEnvelopeKMSv2Service(endpoint string, timeout time.Duration) (envelopekmsv2.Service, error) { +func newMockErrorEnvelopeKMSv2Service(endpoint string, timeout time.Duration) (kmsservice.Service, error) { return &testKMSv2EnvelopeService{errors.New("test")}, nil } @@ -773,23 +773,23 @@ func getTransformerFromEncryptionConfig(t *testing.T, encryptionConfigPath strin func TestIsKMSv2ProviderHealthyError(t *testing.T) { testCases := []struct { desc string - statusResponse *envelopekmsv2.StatusResponse + statusResponse *kmsservice.StatusResponse }{ { desc: "healthz status is not ok", - statusResponse: &envelopekmsv2.StatusResponse{ + statusResponse: &kmsservice.StatusResponse{ Healthz: "unhealthy", }, }, { desc: "version is not v2alpha1", - statusResponse: &envelopekmsv2.StatusResponse{ + statusResponse: &kmsservice.StatusResponse{ Version: "v1beta1", }, }, { desc: "missing keyID", - statusResponse: &envelopekmsv2.StatusResponse{ + statusResponse: &kmsservice.StatusResponse{ Healthz: "ok", Version: "v2alpha1", }, diff --git a/pkg/storage/value/encrypt/envelope/kmsv2/envelope.go b/pkg/storage/value/encrypt/envelope/kmsv2/envelope.go index 726e3053e..927e86fe1 100644 --- a/pkg/storage/value/encrypt/envelope/kmsv2/envelope.go +++ b/pkg/storage/value/encrypt/envelope/kmsv2/envelope.go @@ -35,6 +35,7 @@ import ( kmstypes "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/kmsv2/v2alpha1" "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/metrics" "k8s.io/klog/v2" + kmsservice "k8s.io/kms/service" "k8s.io/utils/lru" ) @@ -49,18 +50,8 @@ const ( encryptedDEKMaxSize = 1 * 1024 // 1 kB ) -// Service allows encrypting and decrypting data using an external Key Management Service. -type Service interface { - // Decrypt a given bytearray to obtain the original data as bytes. - Decrypt(ctx context.Context, uid string, req *DecryptRequest) ([]byte, error) - // Encrypt bytes to a ciphertext. - Encrypt(ctx context.Context, uid string, data []byte) (*EncryptResponse, error) - // Status returns the status of the KMS. - Status(ctx context.Context) (*StatusResponse, error) -} - type envelopeTransformer struct { - envelopeService Service + envelopeService kmsservice.Service // transformers is a thread-safe LRU cache which caches decrypted DEKs indexed by their encrypted form. transformers *lru.Cache @@ -72,32 +63,11 @@ type envelopeTransformer struct { cacheEnabled bool } -// EncryptResponse is the response from the Envelope service when encrypting data. -type EncryptResponse struct { - Ciphertext []byte - KeyID string - Annotations map[string][]byte -} - -// DecryptRequest is the request to the Envelope service when decrypting data. -type DecryptRequest struct { - Ciphertext []byte - KeyID string - Annotations map[string][]byte -} - -// StatusResponse is the response from the Envelope service when getting the status of the service. -type StatusResponse struct { - Version string - Healthz string - KeyID string -} - // NewEnvelopeTransformer returns a transformer which implements a KEK-DEK based envelope encryption scheme. // It uses envelopeService to encrypt and decrypt DEKs. Respective DEKs (in encrypted form) are prepended to // the data items they encrypt. A cache (of size cacheSize) is maintained to store the most recently // used decrypted DEKs in memory. -func NewEnvelopeTransformer(envelopeService Service, cacheSize int, baseTransformerFunc func(cipher.Block) value.Transformer) value.Transformer { +func NewEnvelopeTransformer(envelopeService kmsservice.Service, cacheSize int, baseTransformerFunc func(cipher.Block) value.Transformer) value.Transformer { var cache *lru.Cache if cacheSize > 0 { @@ -133,7 +103,7 @@ func (t *envelopeTransformer) TransformFromStorage(ctx context.Context, data []b } uid := string(uuid.NewUUID()) klog.V(6).InfoS("Decrypting content using envelope service", "uid", uid, "key", string(dataCtx.AuthenticatedData())) - key, err := t.envelopeService.Decrypt(ctx, uid, &DecryptRequest{ + key, err := t.envelopeService.Decrypt(ctx, uid, &kmsservice.DecryptRequest{ Ciphertext: encryptedObject.EncryptedDEK, KeyID: encryptedObject.KeyID, Annotations: encryptedObject.Annotations, diff --git a/pkg/storage/value/encrypt/envelope/kmsv2/envelope_test.go b/pkg/storage/value/encrypt/envelope/kmsv2/envelope_test.go index db876c500..c7ec176c6 100644 --- a/pkg/storage/value/encrypt/envelope/kmsv2/envelope_test.go +++ b/pkg/storage/value/encrypt/envelope/kmsv2/envelope_test.go @@ -30,6 +30,7 @@ import ( "k8s.io/apiserver/pkg/storage/value" aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes" kmstypes "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/kmsv2/v2alpha1" + kmsservice "k8s.io/kms/service" ) const ( @@ -46,7 +47,7 @@ type testEnvelopeService struct { keyVersion string } -func (t *testEnvelopeService) Decrypt(ctx context.Context, uid string, req *DecryptRequest) ([]byte, error) { +func (t *testEnvelopeService) Decrypt(ctx context.Context, uid string, req *kmsservice.DecryptRequest) ([]byte, error) { if t.disabled { return nil, fmt.Errorf("Envelope service was disabled") } @@ -59,7 +60,7 @@ func (t *testEnvelopeService) Decrypt(ctx context.Context, uid string, req *Decr return base64.StdEncoding.DecodeString(string(req.Ciphertext)) } -func (t *testEnvelopeService) Encrypt(ctx context.Context, uid string, data []byte) (*EncryptResponse, error) { +func (t *testEnvelopeService) Encrypt(ctx context.Context, uid string, data []byte) (*kmsservice.EncryptResponse, error) { if t.disabled { return nil, fmt.Errorf("Envelope service was disabled") } @@ -74,14 +75,14 @@ func (t *testEnvelopeService) Encrypt(ctx context.Context, uid string, data []by } else { annotations["local-kek.kms.kubernetes.io"] = []byte("encrypted-local-kek") } - return &EncryptResponse{Ciphertext: []byte(base64.StdEncoding.EncodeToString(data)), KeyID: t.keyVersion, Annotations: annotations}, nil + return &kmsservice.EncryptResponse{Ciphertext: []byte(base64.StdEncoding.EncodeToString(data)), KeyID: t.keyVersion, Annotations: annotations}, nil } -func (t *testEnvelopeService) Status(ctx context.Context) (*StatusResponse, error) { +func (t *testEnvelopeService) Status(ctx context.Context) (*kmsservice.StatusResponse, error) { if t.disabled { return nil, fmt.Errorf("Envelope service was disabled") } - return &StatusResponse{KeyID: t.keyVersion}, nil + return &kmsservice.StatusResponse{KeyID: t.keyVersion}, nil } func (t *testEnvelopeService) SetDisabledStatus(status bool) { diff --git a/pkg/storage/value/encrypt/envelope/kmsv2/grpc_service.go b/pkg/storage/value/encrypt/envelope/kmsv2/grpc_service.go index 692aeef53..cd22fa8d9 100644 --- a/pkg/storage/value/encrypt/envelope/kmsv2/grpc_service.go +++ b/pkg/storage/value/encrypt/envelope/kmsv2/grpc_service.go @@ -30,6 +30,7 @@ import ( "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/util" "k8s.io/klog/v2" kmsapi "k8s.io/kms/apis/v2alpha1" + kmsservice "k8s.io/kms/service" ) const ( @@ -45,7 +46,7 @@ type gRPCService struct { } // NewGRPCService returns an envelope.Service which use gRPC to communicate the remote KMS provider. -func NewGRPCService(ctx context.Context, endpoint string, callTimeout time.Duration) (Service, error) { +func NewGRPCService(ctx context.Context, endpoint string, callTimeout time.Duration) (kmsservice.Service, error) { klog.V(4).Infof("Configure KMS provider with endpoint: %s", endpoint) addr, err := util.ParseEndpoint(endpoint) @@ -88,7 +89,7 @@ func NewGRPCService(ctx context.Context, endpoint string, callTimeout time.Durat } // Decrypt a given data string to obtain the original byte data. -func (g *gRPCService) Decrypt(ctx context.Context, uid string, req *DecryptRequest) ([]byte, error) { +func (g *gRPCService) Decrypt(ctx context.Context, uid string, req *kmsservice.DecryptRequest) ([]byte, error) { ctx, cancel := context.WithTimeout(ctx, g.callTimeout) defer cancel() @@ -106,7 +107,7 @@ func (g *gRPCService) Decrypt(ctx context.Context, uid string, req *DecryptReque } // Encrypt bytes to a string ciphertext. -func (g *gRPCService) Encrypt(ctx context.Context, uid string, plaintext []byte) (*EncryptResponse, error) { +func (g *gRPCService) Encrypt(ctx context.Context, uid string, plaintext []byte) (*kmsservice.EncryptResponse, error) { ctx, cancel := context.WithTimeout(ctx, g.callTimeout) defer cancel() @@ -118,7 +119,7 @@ func (g *gRPCService) Encrypt(ctx context.Context, uid string, plaintext []byte) if err != nil { return nil, err } - return &EncryptResponse{ + return &kmsservice.EncryptResponse{ Ciphertext: response.Ciphertext, KeyID: response.KeyId, Annotations: response.Annotations, @@ -126,7 +127,7 @@ func (g *gRPCService) Encrypt(ctx context.Context, uid string, plaintext []byte) } // Status returns the status of the KMSv2 provider. -func (g *gRPCService) Status(ctx context.Context) (*StatusResponse, error) { +func (g *gRPCService) Status(ctx context.Context) (*kmsservice.StatusResponse, error) { ctx, cancel := context.WithTimeout(ctx, g.callTimeout) defer cancel() @@ -135,5 +136,5 @@ func (g *gRPCService) Status(ctx context.Context) (*StatusResponse, error) { if err != nil { return nil, err } - return &StatusResponse{Version: response.Version, Healthz: response.Healthz, KeyID: response.KeyId}, nil + return &kmsservice.StatusResponse{Version: response.Version, Healthz: response.Healthz, KeyID: response.KeyId}, nil } diff --git a/pkg/storage/value/encrypt/envelope/kmsv2/grpc_service_unix_test.go b/pkg/storage/value/encrypt/envelope/kmsv2/grpc_service_unix_test.go index 41c3ca967..7f2ac4f94 100644 --- a/pkg/storage/value/encrypt/envelope/kmsv2/grpc_service_unix_test.go +++ b/pkg/storage/value/encrypt/envelope/kmsv2/grpc_service_unix_test.go @@ -28,6 +28,7 @@ import ( mock "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/testing/v2alpha1" "k8s.io/apimachinery/pkg/util/uuid" + kmsservice "k8s.io/kms/service" ) type testSocket struct { @@ -120,7 +121,7 @@ func TestTimeouts(t *testing.T) { t.Run(tt.desc, func(t *testing.T) { t.Parallel() var ( - service Service + service kmsservice.Service err error data = []byte("test data") uid = string(uuid.NewUUID()) @@ -293,7 +294,7 @@ func TestGRPCService(t *testing.T) { keyID := "1" // Call service to decrypt data. - result, err := service.Decrypt(ctx, uid, &DecryptRequest{Ciphertext: resp.Ciphertext, KeyID: keyID}) + result, err := service.Decrypt(ctx, uid, &kmsservice.DecryptRequest{Ciphertext: resp.Ciphertext, KeyID: keyID}) if err != nil { t.Fatalf("failed when execute decrypt, error: %v", err) } @@ -342,7 +343,7 @@ func TestGRPCServiceConcurrentAccess(t *testing.T) { keyID := "1" // Call service to decrypt data. - result, err := service.Decrypt(ctx, uid, &DecryptRequest{Ciphertext: resp.Ciphertext, KeyID: keyID}) + result, err := service.Decrypt(ctx, uid, &kmsservice.DecryptRequest{Ciphertext: resp.Ciphertext, KeyID: keyID}) if err != nil { t.Errorf("failed when execute decrypt, error: %v", err) } @@ -356,7 +357,7 @@ func TestGRPCServiceConcurrentAccess(t *testing.T) { wg.Wait() } -func destroyService(service Service) { +func destroyService(service kmsservice.Service) { if service != nil { s := service.(*gRPCService) s.connection.Close()