Add gRPC client service for envelope transformer

This commit is contained in:
Wu Qiang 2017-11-14 09:05:01 +00:00
parent 8992aa0f06
commit 772fa0f62f
11 changed files with 792 additions and 2 deletions

View File

@ -8,22 +8,40 @@ load(
go_library(
name = "go_default_library",
srcs = ["envelope.go"],
srcs = [
"envelope.go",
"grpc_service.go",
"service.pb.go",
],
importpath = "k8s.io/apiserver/pkg/storage/value/encrypt/envelope",
deps = [
"//vendor/github.com/golang/protobuf/proto:go_default_library",
"//vendor/github.com/hashicorp/golang-lru:go_default_library",
"//vendor/golang.org/x/net/context:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
"//vendor/google.golang.org/grpc/credentials:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["envelope_test.go"],
srcs = [
"envelope_test.go",
"grpc_service_test.go",
"grpc_service_unix_test.go",
],
data = glob(["testdata/**"]),
embed = [":go_default_library"],
importpath = "k8s.io/apiserver/pkg/storage/value/encrypt/envelope",
deps = [
"//vendor/golang.org/x/net/context:go_default_library",
"//vendor/golang.org/x/sys/unix:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library",
"//vendor/google.golang.org/grpc/credentials:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/value:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/value/encrypt/aes:go_default_library",
"//vendor/k8s.io/client-go/util/cert:go_default_library",
],
)
@ -39,3 +57,9 @@ filegroup(
srcs = [":package-srcs"],
tags = ["automanaged"],
)
filegroup(
name = "go_default_library_protos",
srcs = ["service.proto"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,151 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package envelope transforms values for storage at rest using a Envelope provider
package envelope
import (
"crypto/tls"
"crypto/x509"
"fmt"
"io/ioutil"
"net"
"net/url"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"golang.org/x/net/context"
)
const (
// Supportied protocol schema for gRPC.
tcpProtocol = "tcp"
unixProtocol = "unix"
// Current version for the protocal interface definition.
version = "v1beta1"
)
type gRPCService struct {
// gRPC client instance
kmsClient KmsServiceClient
connection *grpc.ClientConn
}
// NewEnvelopeService returns an envelope.Service which use gRPC to communicate the remote KMS provider.
func NewEnvelopeService(endpoint, serverCert, clientCert, clientKey string) (Service, error) {
protocol, addr, err := parseEndpoint(endpoint)
if err != nil {
return nil, err
}
dialer := func(addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout(protocol, addr, timeout)
}
// With or without TLS/SSL support
tlsOption, err := getTlsDialOption(serverCert, clientCert, clientKey)
if err != nil {
return nil, err
}
conn, err := grpc.Dial(addr, tlsOption, grpc.WithDialer(dialer))
if err != nil {
return nil, fmt.Errorf("connect remote image service %s failed, error: %v", addr, err)
}
return &gRPCService{kmsClient: NewKmsServiceClient(conn), connection: conn}, nil
}
// Parse the endpoint to extract schema, host or path.
func parseEndpoint(endpoint string) (string, string, error) {
u, err := url.Parse(endpoint)
if err != nil {
return "", "", fmt.Errorf("invalid kms provider endpoint %q, error: %v", endpoint, err)
}
switch u.Scheme {
case tcpProtocol:
return tcpProtocol, u.Host, nil
case unixProtocol:
return unixProtocol, u.Path, nil
default:
return "", "", fmt.Errorf("invalid endpoint %q for remote KMS provider", endpoint)
}
}
// Build the TLS/SSL options for gRPC client.
func getTlsDialOption(serverCert, clientCert, clientKey string) (grpc.DialOption, error) {
// No TLS/SSL support.
if len(serverCert) == 0 && len(clientCert) == 0 && len(clientKey) == 0 {
return grpc.WithInsecure(), nil
}
// Set the CA that verify the certificate from the gRPC server.
certPool := x509.NewCertPool()
if len(serverCert) > 0 {
ca, err := ioutil.ReadFile(serverCert)
if err != nil {
return nil, fmt.Errorf("kms provider invalid server cert, error: %v", err)
}
if !certPool.AppendCertsFromPEM(ca) {
return nil, fmt.Errorf("can't append server cert for kms provider")
}
}
// Set client authenticate certificate.
certificates := make([]tls.Certificate, 0, 1)
if len(clientCert) != 0 || len(clientKey) != 0 {
if len(clientCert) == 0 || len(clientKey) == 0 {
return nil, fmt.Errorf("both client cert and key must be provided for kms provider")
}
cert, err := tls.LoadX509KeyPair(clientCert, clientKey)
if err != nil {
return nil, fmt.Errorf("kms provider invalid client cert or key, error: %v", err)
}
certificates = append(certificates, cert)
}
tlsConfig := tls.Config{
Certificates: certificates,
RootCAs: certPool,
}
transportCreds := credentials.NewTLS(&tlsConfig)
return grpc.WithTransportCredentials(transportCreds), nil
}
// Decrypt a given data string to obtain the original byte data.
func (g *gRPCService) Decrypt(cipher string) ([]byte, error) {
request := &DecryptRequest{Cipher: []byte(cipher), Version: version}
response, err := g.kmsClient.Decrypt(context.Background(), request)
if err != nil {
return nil, err
}
return response.Plain, nil
}
// Encrypt bytes to a string ciphertext.
func (g *gRPCService) Encrypt(plain []byte) (string, error) {
request := &EncryptRequest{Plain: plain, Version: version}
response, err := g.kmsClient.Encrypt(context.Background(), request)
if err != nil {
return "", err
}
return string(response.Cipher), nil
}

View File

@ -0,0 +1,218 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package envelope transforms values for storage at rest using a Envelope provider
package envelope
import (
"crypto/tls"
"encoding/base64"
"fmt"
"net"
"reflect"
"testing"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"golang.org/x/net/context"
"k8s.io/client-go/util/cert"
)
const (
// Port 0 to select any available port
listenerAddr = "127.0.0.1:0"
cafile = "testdata/ca.crt"
serverCert = "testdata/server.crt"
serverKey = "testdata/server.key"
clientCert = "testdata/client.crt"
clientKey = "testdata/client.key"
)
func TestTcpEndpoint(t *testing.T) {
// Start the gRPC server that listens on tcp socket.
listener, err := tcpListner()
if err != nil {
t.Fatal(err)
}
server := startTestKmsProvider(listener)
defer server.Stop()
endpoint := tcpProtocol + "://" + listener.Addr().String()
verifyService(t, endpoint, "", "", "")
}
func TestTlsEndpoint(t *testing.T) {
// Start the gRPC server that listens on tcp socket.
listener, err := tcpListner()
if err != nil {
t.Fatal(err)
}
tlsOption, err := tlsServerOption()
if err != nil {
t.Fatal(err)
}
server := startTestKmsProvider(listener, tlsOption)
defer server.Stop()
// There are 2 TLS case: no auth and client auth.
endpoint := tcpProtocol + "://" + listener.Addr().String()
certConfigs := []struct {
name string
serverCACert string
clientCert string
clientKey string
}{
{"noAuth", cafile, "", ""},
{"clientAuth", cafile, clientCert, clientKey},
}
for _, testCase := range certConfigs {
t.Run(testCase.name, func(t *testing.T) {
verifyService(t, endpoint, testCase.serverCACert, testCase.clientCert, testCase.clientKey)
})
}
}
func TestInvalidConfiguration(t *testing.T) {
// Start the gRPC server that listens on tcp socket.
listener, err := tcpListner()
if err != nil {
t.Fatal(err)
}
tlsOption, err := tlsServerOption()
if err != nil {
t.Fatal(err)
}
server := startTestKmsProvider(listener, tlsOption)
defer server.Stop()
endpoint := tcpProtocol + "://" + listener.Addr().String()
invalidConfigs := []struct {
name string
endpoint string
serverCACert string
clientCert string
clientKey string
}{
{"emptyConfiguration", "", "", "", ""},
{"invalidEndpoint", "http://localhost:80", "", "", ""},
{"invalidServerCACert", endpoint, "non-exits.pem", "", ""},
{"missClientKey", endpoint, cafile, clientCert, ""},
{"invalidClientCert", endpoint, cafile, "non-exists.pem", clientKey},
}
for _, testCase := range invalidConfigs {
t.Run(testCase.name, func(t *testing.T) {
_, err := NewEnvelopeService(
testCase.endpoint,
testCase.serverCACert,
testCase.clientCert,
testCase.clientKey,
)
if err == nil {
t.Fatalf("should fail to create envelope service for %s.", testCase.name)
}
})
}
}
func verifyService(t *testing.T, endpoint, serverCACert, clientCert, clientKey string) {
service, err := NewEnvelopeService(endpoint, serverCACert, clientCert, clientKey)
if err != nil {
t.Fatalf("failed to create envelope service, error: %v", err)
}
defer destroyService(service)
data := []byte("test data")
cipher, err := service.Encrypt(data)
if err != nil {
t.Fatalf("failed when execute encrypt, error: %v", err)
}
result, err := service.Decrypt(cipher)
if err != nil {
t.Fatalf("failed when execute decrypt, error: %v", err)
}
if !reflect.DeepEqual(data, result) {
t.Errorf("expect: %v, but: %v", data, result)
}
}
func destroyService(service Service) {
gs := service.(*gRPCService)
gs.connection.Close()
}
func tcpListner() (net.Listener, error) {
listener, err := net.Listen(tcpProtocol, listenerAddr)
if err != nil {
return nil, fmt.Errorf("failed to listen on the tcp address, error: %v", err)
}
return listener, nil
}
func startTestKmsProvider(listener net.Listener, options ...grpc.ServerOption) *grpc.Server {
server := grpc.NewServer(options...)
RegisterKmsServiceServer(server, &base64Server{})
go server.Serve(listener)
return server
}
func tlsServerOption() (grpc.ServerOption, error) {
certificate, err := tls.LoadX509KeyPair(serverCert, serverKey)
if err != nil {
return nil, fmt.Errorf("bad server cert or key, error: %v", err)
}
certPool, err := cert.NewPool(cafile)
if err != nil {
return nil, fmt.Errorf("bad ca file, error: %v", err)
}
tlsConfig := &tls.Config{
ClientAuth: tls.VerifyClientCertIfGiven,
Certificates: []tls.Certificate{certificate},
ClientCAs: certPool,
}
return grpc.Creds(credentials.NewTLS(tlsConfig)), nil
}
// Fake gRPC sever for remote KMS provider.
type base64Server struct{}
func (b *base64Server) Decrypt(ctx context.Context, request *DecryptRequest) (*DecryptResponse, error) {
buf := make([]byte, base64.StdEncoding.DecodedLen(len(request.Cipher)))
n, err := base64.StdEncoding.Decode(buf, request.Cipher)
if err != nil {
return nil, err
}
return &DecryptResponse{Plain: buf[:n]}, nil
}
func (b *base64Server) Encrypt(ctx context.Context, request *EncryptRequest) (*EncryptResponse, error) {
buf := make([]byte, base64.StdEncoding.EncodedLen(len(request.Plain)))
base64.StdEncoding.Encode(buf, request.Plain)
return &EncryptResponse{Cipher: buf}, nil
}

View File

@ -0,0 +1,73 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// +build !windows
// Package envelope transforms values for storage at rest using a Envelope provider
package envelope
import (
"fmt"
"net"
"os"
"testing"
"golang.org/x/sys/unix"
)
const (
sockFile = "/tmp/kms-provider.sock"
)
func TestUnixSockEndpoint(t *testing.T) {
// Start the gRPC server that listens on unix socket.
listener, err := unixSockListner()
if err != nil {
t.Fatal(err)
}
server := startTestKmsProvider(listener)
defer func() {
server.Stop()
if err := cleanSockFile(); err != nil {
t.Fatal(err)
}
}()
endpoint := unixProtocol + "://" + sockFile
verifyService(t, endpoint, "", "", "")
}
func unixSockListner() (net.Listener, error) {
if err := cleanSockFile(); err != nil {
return nil, err
}
listener, err := net.Listen(unixProtocol, sockFile)
if err != nil {
return nil, fmt.Errorf("failed to listen on the unix socket, error: %v", err)
}
return listener, nil
}
func cleanSockFile() error {
err := unix.Unlink(sockFile)
if err != nil && !os.IsNotExist(err) {
return fmt.Errorf("failed to delete the socket file, error: %v", err)
}
return nil
}

View File

@ -0,0 +1,225 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by protoc-gen-go.
// source: service.proto
// DO NOT EDIT!
/*
Package envelope is a generated protocol buffer package.
It is generated from these files:
service.proto
It has these top-level messages:
DecryptRequest
DecryptResponse
EncryptRequest
EncryptResponse
*/
package envelope
import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type DecryptRequest struct {
Cipher []byte `protobuf:"bytes,1,opt,name=cipher,proto3" json:"cipher,omitempty"`
// Version of the KMS plugin API, now use “v1beta1”
Version string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"`
}
func (m *DecryptRequest) Reset() { *m = DecryptRequest{} }
func (m *DecryptRequest) String() string { return proto.CompactTextString(m) }
func (*DecryptRequest) ProtoMessage() {}
func (*DecryptRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type DecryptResponse struct {
Plain []byte `protobuf:"bytes,1,opt,name=plain,proto3" json:"plain,omitempty"`
}
func (m *DecryptResponse) Reset() { *m = DecryptResponse{} }
func (m *DecryptResponse) String() string { return proto.CompactTextString(m) }
func (*DecryptResponse) ProtoMessage() {}
func (*DecryptResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
type EncryptRequest struct {
Plain []byte `protobuf:"bytes,1,opt,name=plain,proto3" json:"plain,omitempty"`
// Version of the KMS plugin API, now use “v1beta1”
Version string `protobuf:"bytes,2,opt,name=version" json:"version,omitempty"`
}
func (m *EncryptRequest) Reset() { *m = EncryptRequest{} }
func (m *EncryptRequest) String() string { return proto.CompactTextString(m) }
func (*EncryptRequest) ProtoMessage() {}
func (*EncryptRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
type EncryptResponse struct {
Cipher []byte `protobuf:"bytes,1,opt,name=cipher,proto3" json:"cipher,omitempty"`
}
func (m *EncryptResponse) Reset() { *m = EncryptResponse{} }
func (m *EncryptResponse) String() string { return proto.CompactTextString(m) }
func (*EncryptResponse) ProtoMessage() {}
func (*EncryptResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func init() {
proto.RegisterType((*DecryptRequest)(nil), "envelope.DecryptRequest")
proto.RegisterType((*DecryptResponse)(nil), "envelope.DecryptResponse")
proto.RegisterType((*EncryptRequest)(nil), "envelope.EncryptRequest")
proto.RegisterType((*EncryptResponse)(nil), "envelope.EncryptResponse")
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConn
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion4
// Client API for KmsService service
type KmsServiceClient interface {
Decrypt(ctx context.Context, in *DecryptRequest, opts ...grpc.CallOption) (*DecryptResponse, error)
Encrypt(ctx context.Context, in *EncryptRequest, opts ...grpc.CallOption) (*EncryptResponse, error)
}
type kmsServiceClient struct {
cc *grpc.ClientConn
}
func NewKmsServiceClient(cc *grpc.ClientConn) KmsServiceClient {
return &kmsServiceClient{cc}
}
func (c *kmsServiceClient) Decrypt(ctx context.Context, in *DecryptRequest, opts ...grpc.CallOption) (*DecryptResponse, error) {
out := new(DecryptResponse)
err := grpc.Invoke(ctx, "/envelope.KmsService/Decrypt", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *kmsServiceClient) Encrypt(ctx context.Context, in *EncryptRequest, opts ...grpc.CallOption) (*EncryptResponse, error) {
out := new(EncryptResponse)
err := grpc.Invoke(ctx, "/envelope.KmsService/Encrypt", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for KmsService service
type KmsServiceServer interface {
Decrypt(context.Context, *DecryptRequest) (*DecryptResponse, error)
Encrypt(context.Context, *EncryptRequest) (*EncryptResponse, error)
}
func RegisterKmsServiceServer(s *grpc.Server, srv KmsServiceServer) {
s.RegisterService(&_KmsService_serviceDesc, srv)
}
func _KmsService_Decrypt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DecryptRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(KmsServiceServer).Decrypt(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/envelope.KmsService/Decrypt",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(KmsServiceServer).Decrypt(ctx, req.(*DecryptRequest))
}
return interceptor(ctx, in, info, handler)
}
func _KmsService_Encrypt_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(EncryptRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(KmsServiceServer).Encrypt(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/envelope.KmsService/Encrypt",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(KmsServiceServer).Encrypt(ctx, req.(*EncryptRequest))
}
return interceptor(ctx, in, info, handler)
}
var _KmsService_serviceDesc = grpc.ServiceDesc{
ServiceName: "envelope.KmsService",
HandlerType: (*KmsServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Decrypt",
Handler: _KmsService_Decrypt_Handler,
},
{
MethodName: "Encrypt",
Handler: _KmsService_Encrypt_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "service.proto",
}
func init() { proto.RegisterFile("service.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 209 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2d, 0x4e, 0x2d, 0x2a,
0xcb, 0x4c, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x48, 0xcd, 0x2b, 0x4b, 0xcd,
0xc9, 0x2f, 0x48, 0x55, 0x72, 0xe2, 0xe2, 0x73, 0x49, 0x4d, 0x2e, 0xaa, 0x2c, 0x28, 0x09, 0x4a,
0x2d, 0x2c, 0x4d, 0x2d, 0x2e, 0x11, 0x12, 0xe3, 0x62, 0x4b, 0xce, 0x2c, 0xc8, 0x48, 0x2d, 0x92,
0x60, 0x54, 0x60, 0xd4, 0xe0, 0x09, 0x82, 0xf2, 0x84, 0x24, 0xb8, 0xd8, 0xcb, 0x52, 0x8b, 0x8a,
0x33, 0xf3, 0xf3, 0x24, 0x98, 0x14, 0x18, 0x35, 0x38, 0x83, 0x60, 0x5c, 0x25, 0x75, 0x2e, 0x7e,
0xb8, 0x19, 0xc5, 0x05, 0xf9, 0x79, 0xc5, 0xa9, 0x42, 0x22, 0x5c, 0xac, 0x05, 0x39, 0x89, 0x99,
0x79, 0x50, 0x33, 0x20, 0x1c, 0x25, 0x07, 0x2e, 0x3e, 0xd7, 0x3c, 0x14, 0xcb, 0xb0, 0xaa, 0xc3,
0x63, 0x95, 0x26, 0x17, 0x3f, 0xdc, 0x04, 0xa8, 0x55, 0x38, 0xdc, 0x6b, 0x34, 0x81, 0x91, 0x8b,
0xcb, 0x3b, 0xb7, 0x38, 0x18, 0xe2, 0x71, 0x21, 0x07, 0x2e, 0x76, 0xa8, 0x23, 0x85, 0x24, 0xf4,
0x60, 0xde, 0xd7, 0x43, 0xf5, 0xbb, 0x94, 0x24, 0x16, 0x19, 0x88, 0x35, 0x4a, 0x0c, 0x20, 0x13,
0xa0, 0x76, 0x23, 0x9b, 0x80, 0xea, 0x21, 0x64, 0x13, 0xd0, 0x1c, 0xaa, 0xc4, 0x90, 0xc4, 0x06,
0x0e, 0x7d, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xb0, 0xc2, 0xcf, 0x84, 0x8e, 0x01, 0x00,
0x00,
}

View File

@ -0,0 +1,29 @@
syntax = "proto3";
package envelope;
service KmsService {
rpc Decrypt(DecryptRequest) returns (DecryptResponse) {}
rpc Encrypt(EncryptRequest) returns (EncryptResponse) {}
}
message DecryptRequest {
bytes cipher = 1;
// Version of the KMS plugin API, now use v1beta1
string version = 2;
}
message DecryptResponse {
bytes plain = 1;
}
message EncryptRequest {
bytes plain = 1;
// Version of the KMS plugin API, now use v1beta1
string version = 2;
}
message EncryptResponse {
bytes cipher = 1;
}

View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDujCCAqKgAwIBAgIUASbBmHT/Y+wdxggFudEoKKgLXsYwDQYJKoZIhvcNAQEL
BQAwdTELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNV
BAcTAkNBMRgwFgYDVQQKEw9NeSBDb21wYW55IE5hbWUxEzARBgNVBAsTCk9yZyBV
bml0IDIxEjAQBgNVBAMTCU15IG93biBDQTAeFw0xNzA3MTcwNTMzMDBaFw0yMjA3
MTYwNTMzMDBaMHUxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1TYW4gRnJhbmNpc2Nv
MQswCQYDVQQHEwJDQTEYMBYGA1UEChMPTXkgQ29tcGFueSBOYW1lMRMwEQYDVQQL
EwpPcmcgVW5pdCAyMRIwEAYDVQQDEwlNeSBvd24gQ0EwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQC4c79AZIRgUjiE4ekjISLYw0nAH7c9FJf6+U22xwLe
X4Yc3uy94Md1lNhYyvNdba6qLLBKqThYCZYsXK2ZPRnmScYHS/edTmzhZ79tSXUA
+R0YJZK00taWyRCZm2tCgXWdWNebrDBwGL+b2P1bButw81CQVYzPQnZiTnnAOUMt
6qbMxGDXRhNydKGx43QtBuRWHS6wjJEjI50dGK8RBWDupBQrEQzaFt9gU3grTPlh
RWvClrM7LU3A1Ymz3Eq6l4tQhcUXSS3JJVhOLrvh4wujJv/tmIzYylrp7gbUvEYn
PW46UZHKrUM8tNthgTnvcychk73+ZZMoWIj5hsne0mTrAgMBAAGjQjBAMA4GA1Ud
DwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBShLj7pyAcfeLfB
l6vyHo5uvY5WnjANBgkqhkiG9w0BAQsFAAOCAQEAUK7jmNOHmTs58f9fIj6hGppt
Lz/l5+C6KA+1P03cdo+KgQb6MnzvKmhGFHD4QM0envHilHBRNO7VWgA7PuO2JtY1
NwWQfLoyWcft3OXLmJdWcUI9Che/UWFSxCmxC3U+Cb4+4bNq3j+ygt1T6/I9aTTo
/ymS8H+dXF4n69psY591PA8QeUbaQwc5SEWtIont/XWoq+NwXsrNYglPFzGiaoO6
gF52I3Z0o0fCHtnOIhBDwrOr7oPJy/SEo49WdnxtG5FcN7qNBvFET7/gOI8TxJMr
gTW3G6jSTjBA8sEIhD4k4LOXxWGWwemP6I/LI849/uKd+DoqKjr5Y/BQvcLy+g==
-----END CERTIFICATE-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCzCCAfOgAwIBAgIUHqXu3n2P44f2JjHIKPV0m41URRowDQYJKoZIhvcNAQEL
BQAwdTELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNV
BAcTAkNBMRgwFgYDVQQKEw9NeSBDb21wYW55IE5hbWUxEzARBgNVBAsTCk9yZyBV
bml0IDIxEjAQBgNVBAMTCU15IG93biBDQTAeFw0xNzA3MTcwNTQ1MDBaFw0yMjA3
MTYwNTQ1MDBaMEYxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMN
U2FuIEZyYW5jaXNjbzESMBAGA1UEAxMJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAE1na/uyZ4Za0+8letub+cQyqoz40NdouSbxcmb/EEv/rtPMmz
A3u+F8LeXt4SI2+ndQbL0DvpFAOBjJejb3jlfKOBjDCBiTAOBgNVHQ8BAf8EBAMC
BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU
856v+uMt0F4cgO0dk2k6HpaEa+IwHwYDVR0jBBgwFoAUoS4+6cgHH3i3wZer8h6O
br2OVp4wFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQBt
5uNxxxhWFCGlGBrVr2J2KA2IJ3thoMSn6lV9/qU2KMBBYneHHE0FG/ubrP9urQhI
KGPwXsfOdS3iuABOBziiuge9iQisHVWQuNEOtbINbdau2ZLsB2BKKAPit1xG+8gn
7leSvyurcpXPc6QuPHCP5hI081y3w+1H4IUDF0qXoi0jYC/BDwl+lk8yHGFQReu2
33QdhjXr9Wd20XBO8TJ3oQcAezYvb9bJFDgOkUEhSmMVf86YX0QkuphDvuuU3hQC
S4vVpIzM7xoH3xkvXgOMeReLV1df3J3iHyADhUWiS1RNskymGhFmUumlNUPimhUc
E0wqi62pL+kxg1zjXdXY
-----END CERTIFICATE-----

View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEINjBFDLQH8NJxn/DBF1lOm92fbx2QGkpfWwwADcPE5p7oAoGCCqGSM49
AwEHoUQDQgAE1na/uyZ4Za0+8letub+cQyqoz40NdouSbxcmb/EEv/rtPMmzA3u+
F8LeXt4SI2+ndQbL0DvpFAOBjJejb3jlfA==
-----END EC PRIVATE KEY-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDETCCAfmgAwIBAgIUU5D4PeHC+zpmc/jwwa2c/6aHPbowDQYJKoZIhvcNAQEL
BQAwdTELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDVNhbiBGcmFuY2lzY28xCzAJBgNV
BAcTAkNBMRgwFgYDVQQKEw9NeSBDb21wYW55IE5hbWUxEzARBgNVBAsTCk9yZyBV
bml0IDIxEjAQBgNVBAMTCU15IG93biBDQTAeFw0xNzA3MTcwNTM3MDBaFw0yMjA3
MTYwNTM3MDBaMEYxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMN
U2FuIEZyYW5jaXNjbzESMBAGA1UEAxMJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEd2CnjPbDOHsbR6CcMhzktDsBrRZAaLjpC/9IHtPH+ivDrey8
jJzZnD+9aLp5E/QG5Rf1tzKDH+oRatQ43mViHKOBkjCBjzAOBgNVHQ8BAf8EBAMC
BaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU
rkKlAy9PqK+TrUqApq4BVBSQgNQwHwYDVR0jBBgwFoAUoS4+6cgHH3i3wZer8h6O
br2OVp4wGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3DQEBCwUA
A4IBAQCikDXkrB4dw8zBrkIA6plgdcgVm1zJbRDhjAVHxHlh/ISPP7Zu9faLmlEN
GC0KK1AmQQciCyoI84VoBQ5WMtyMfbEn0klJ4OOtGwMZtZfgWSD0LX9APIZEU9WH
nvjLLCHkxbq/cf01pAYIlyBhI5vl7/m8b1xVYarKcb2/Homr8guTzRSyJb0Gmeoo
vdiGIhHhvP186OGzOOQVlorZ/WWJTlhXviGJ0QWARthUi+wEHRhJ+STH2VtOrKhb
4tvG0/G9mYK1LOIbZesHtF9C35XThkh/W/rKRWe6/J8pOYh/vFB/aQL73HPvIcpD
tcmR7635hb+42P7raby70UC7nLWf
-----END CERTIFICATE-----

View File

@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIN18H0TgTgqfYWVn2BtQym4mUfICD4XcuWE+nhn+fxSeoAoGCCqGSM49
AwEHoUQDQgAEd2CnjPbDOHsbR6CcMhzktDsBrRZAaLjpC/9IHtPH+ivDrey8jJzZ
nD+9aLp5E/QG5Rf1tzKDH+oRatQ43mViHA==
-----END EC PRIVATE KEY-----