Merge pull request #114922 from ibihim/kmsv2-interface-move

[KMSv2] apiserver/kmsv2: mv Service interface into kmsv2
This commit is contained in:
Kubernetes Prow Robot 2023-01-17 10:10:33 -08:00 committed by GitHub
commit f7b02260f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 40 additions and 69 deletions

View File

@ -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))

View File

@ -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",
},

View File

@ -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,

View File

@ -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) {

View File

@ -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
}

View File

@ -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()

View File

@ -18,10 +18,6 @@ package service
import "context"
/*
Copied from: k8s.io/apiserver/pkg/storage/value/encrypt/envelope/kmsv2
*/
// 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.

View File

@ -40,13 +40,13 @@ import (
"k8s.io/apiserver/pkg/server/options/encryptionconfig"
"k8s.io/apiserver/pkg/storage/value"
aestransformer "k8s.io/apiserver/pkg/storage/value/encrypt/aes"
"k8s.io/apiserver/pkg/storage/value/encrypt/envelope/kmsv2"
kmstypes "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/kmsv2/v2alpha1"
kmsv2mock "k8s.io/apiserver/pkg/storage/value/encrypt/envelope/testing/v2alpha1"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/dynamic"
featuregatetesting "k8s.io/component-base/featuregate/testing"
kmsv2api "k8s.io/kms/apis/v2alpha1"
kmsv2svc "k8s.io/kms/service"
"k8s.io/kubernetes/test/integration/etcd"
)
@ -300,7 +300,7 @@ func TestKMSv2SingleService(t *testing.T) {
var kmsv2Calls int
origEnvelopeKMSv2ServiceFactory := encryptionconfig.EnvelopeKMSv2ServiceFactory
encryptionconfig.EnvelopeKMSv2ServiceFactory = func(ctx context.Context, endpoint string, callTimeout time.Duration) (kmsv2.Service, error) {
encryptionconfig.EnvelopeKMSv2ServiceFactory = func(ctx context.Context, endpoint string, callTimeout time.Duration) (kmsv2svc.Service, error) {
kmsv2Calls++
return origEnvelopeKMSv2ServiceFactory(ctx, endpoint, callTimeout)
}

1
vendor/modules.txt vendored
View File

@ -2098,6 +2098,7 @@ k8s.io/klog/v2/test
## explicit; go 1.19
k8s.io/kms/apis/v1beta1
k8s.io/kms/apis/v2alpha1
k8s.io/kms/service
# k8s.io/kube-aggregator v0.0.0 => ./staging/src/k8s.io/kube-aggregator
## explicit; go 1.19
k8s.io/kube-aggregator/pkg/apis/apiregistration