1
0
mirror of https://github.com/getsops/sops.git synced 2026-02-05 12:45:21 +01:00

First step towards remote keys

This commit is contained in:
Adrian Utrilla
2017-08-14 20:07:45 -07:00
parent 486a9c8b4c
commit 6e4dfdec09
3 changed files with 587 additions and 0 deletions

432
keyservice/keyservice.pb.go Normal file
View File

@@ -0,0 +1,432 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: keyservice.proto
/*
Package keyservice is a generated protocol buffer package.
It is generated from these files:
keyservice.proto
It has these top-level messages:
Key
GpgKey
KmsKey
EncryptRequest
EncryptResponse
DecryptRequest
DecryptResponse
*/
package keyservice
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 Key struct {
// Types that are valid to be assigned to KeyType:
// *Key_KmsKey
// *Key_GpgKey
KeyType isKey_KeyType `protobuf_oneof:"key_type"`
}
func (m *Key) Reset() { *m = Key{} }
func (m *Key) String() string { return proto.CompactTextString(m) }
func (*Key) ProtoMessage() {}
func (*Key) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
type isKey_KeyType interface {
isKey_KeyType()
}
type Key_KmsKey struct {
KmsKey *KmsKey `protobuf:"bytes,1,opt,name=kms_key,json=kmsKey,oneof"`
}
type Key_GpgKey struct {
GpgKey *GpgKey `protobuf:"bytes,2,opt,name=gpg_key,json=gpgKey,oneof"`
}
func (*Key_KmsKey) isKey_KeyType() {}
func (*Key_GpgKey) isKey_KeyType() {}
func (m *Key) GetKeyType() isKey_KeyType {
if m != nil {
return m.KeyType
}
return nil
}
func (m *Key) GetKmsKey() *KmsKey {
if x, ok := m.GetKeyType().(*Key_KmsKey); ok {
return x.KmsKey
}
return nil
}
func (m *Key) GetGpgKey() *GpgKey {
if x, ok := m.GetKeyType().(*Key_GpgKey); ok {
return x.GpgKey
}
return nil
}
// XXX_OneofFuncs is for the internal use of the proto package.
func (*Key) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) {
return _Key_OneofMarshaler, _Key_OneofUnmarshaler, _Key_OneofSizer, []interface{}{
(*Key_KmsKey)(nil),
(*Key_GpgKey)(nil),
}
}
func _Key_OneofMarshaler(msg proto.Message, b *proto.Buffer) error {
m := msg.(*Key)
// key_type
switch x := m.KeyType.(type) {
case *Key_KmsKey:
b.EncodeVarint(1<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.KmsKey); err != nil {
return err
}
case *Key_GpgKey:
b.EncodeVarint(2<<3 | proto.WireBytes)
if err := b.EncodeMessage(x.GpgKey); err != nil {
return err
}
case nil:
default:
return fmt.Errorf("Key.KeyType has unexpected type %T", x)
}
return nil
}
func _Key_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) {
m := msg.(*Key)
switch tag {
case 1: // key_type.kms_key
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(KmsKey)
err := b.DecodeMessage(msg)
m.KeyType = &Key_KmsKey{msg}
return true, err
case 2: // key_type.gpg_key
if wire != proto.WireBytes {
return true, proto.ErrInternalBadWireType
}
msg := new(GpgKey)
err := b.DecodeMessage(msg)
m.KeyType = &Key_GpgKey{msg}
return true, err
default:
return false, nil
}
}
func _Key_OneofSizer(msg proto.Message) (n int) {
m := msg.(*Key)
// key_type
switch x := m.KeyType.(type) {
case *Key_KmsKey:
s := proto.Size(x.KmsKey)
n += proto.SizeVarint(1<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case *Key_GpgKey:
s := proto.Size(x.GpgKey)
n += proto.SizeVarint(2<<3 | proto.WireBytes)
n += proto.SizeVarint(uint64(s))
n += s
case nil:
default:
panic(fmt.Sprintf("proto: unexpected type %T in oneof", x))
}
return n
}
type GpgKey struct {
Fingerprint string `protobuf:"bytes,1,opt,name=fingerprint" json:"fingerprint,omitempty"`
}
func (m *GpgKey) Reset() { *m = GpgKey{} }
func (m *GpgKey) String() string { return proto.CompactTextString(m) }
func (*GpgKey) ProtoMessage() {}
func (*GpgKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *GpgKey) GetFingerprint() string {
if m != nil {
return m.Fingerprint
}
return ""
}
type KmsKey struct {
Arn string `protobuf:"bytes,1,opt,name=arn" json:"arn,omitempty"`
Role string `protobuf:"bytes,2,opt,name=role" json:"role,omitempty"`
Context map[string]string `protobuf:"bytes,3,rep,name=context" json:"context,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
}
func (m *KmsKey) Reset() { *m = KmsKey{} }
func (m *KmsKey) String() string { return proto.CompactTextString(m) }
func (*KmsKey) ProtoMessage() {}
func (*KmsKey) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
func (m *KmsKey) GetArn() string {
if m != nil {
return m.Arn
}
return ""
}
func (m *KmsKey) GetRole() string {
if m != nil {
return m.Role
}
return ""
}
func (m *KmsKey) GetContext() map[string]string {
if m != nil {
return m.Context
}
return nil
}
type EncryptRequest struct {
Key *Key `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"`
Plaintext []byte `protobuf:"bytes,2,opt,name=plaintext,proto3" json:"plaintext,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{3} }
func (m *EncryptRequest) GetKey() *Key {
if m != nil {
return m.Key
}
return nil
}
func (m *EncryptRequest) GetPlaintext() []byte {
if m != nil {
return m.Plaintext
}
return nil
}
type EncryptResponse struct {
Ciphertext []byte `protobuf:"bytes,1,opt,name=ciphertext,proto3" json:"ciphertext,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{4} }
func (m *EncryptResponse) GetCiphertext() []byte {
if m != nil {
return m.Ciphertext
}
return nil
}
type DecryptRequest struct {
Key *Key `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"`
Ciphertext []byte `protobuf:"bytes,2,opt,name=ciphertext,proto3" json:"ciphertext,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{5} }
func (m *DecryptRequest) GetKey() *Key {
if m != nil {
return m.Key
}
return nil
}
func (m *DecryptRequest) GetCiphertext() []byte {
if m != nil {
return m.Ciphertext
}
return nil
}
type DecryptResponse struct {
Plaintext []byte `protobuf:"bytes,1,opt,name=plaintext,proto3" json:"plaintext,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{6} }
func (m *DecryptResponse) GetPlaintext() []byte {
if m != nil {
return m.Plaintext
}
return nil
}
func init() {
proto.RegisterType((*Key)(nil), "Key")
proto.RegisterType((*GpgKey)(nil), "GpgKey")
proto.RegisterType((*KmsKey)(nil), "KmsKey")
proto.RegisterType((*EncryptRequest)(nil), "EncryptRequest")
proto.RegisterType((*EncryptResponse)(nil), "EncryptResponse")
proto.RegisterType((*DecryptRequest)(nil), "DecryptRequest")
proto.RegisterType((*DecryptResponse)(nil), "DecryptResponse")
}
// 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 KeyService service
type KeyServiceClient interface {
Encrypt(ctx context.Context, in *EncryptRequest, opts ...grpc.CallOption) (*EncryptResponse, error)
Decrypt(ctx context.Context, in *DecryptRequest, opts ...grpc.CallOption) (*DecryptResponse, error)
}
type keyServiceClient struct {
cc *grpc.ClientConn
}
func NewKeyServiceClient(cc *grpc.ClientConn) KeyServiceClient {
return &keyServiceClient{cc}
}
func (c *keyServiceClient) Encrypt(ctx context.Context, in *EncryptRequest, opts ...grpc.CallOption) (*EncryptResponse, error) {
out := new(EncryptResponse)
err := grpc.Invoke(ctx, "/KeyService/Encrypt", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *keyServiceClient) Decrypt(ctx context.Context, in *DecryptRequest, opts ...grpc.CallOption) (*DecryptResponse, error) {
out := new(DecryptResponse)
err := grpc.Invoke(ctx, "/KeyService/Decrypt", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for KeyService service
type KeyServiceServer interface {
Encrypt(context.Context, *EncryptRequest) (*EncryptResponse, error)
Decrypt(context.Context, *DecryptRequest) (*DecryptResponse, error)
}
func RegisterKeyServiceServer(s *grpc.Server, srv KeyServiceServer) {
s.RegisterService(&_KeyService_serviceDesc, srv)
}
func _KeyService_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.(KeyServiceServer).Encrypt(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/KeyService/Encrypt",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(KeyServiceServer).Encrypt(ctx, req.(*EncryptRequest))
}
return interceptor(ctx, in, info, handler)
}
func _KeyService_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.(KeyServiceServer).Decrypt(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/KeyService/Decrypt",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(KeyServiceServer).Decrypt(ctx, req.(*DecryptRequest))
}
return interceptor(ctx, in, info, handler)
}
var _KeyService_serviceDesc = grpc.ServiceDesc{
ServiceName: "KeyService",
HandlerType: (*KeyServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Encrypt",
Handler: _KeyService_Encrypt_Handler,
},
{
MethodName: "Decrypt",
Handler: _KeyService_Decrypt_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "keyservice.proto",
}
func init() { proto.RegisterFile("keyservice.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 361 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x52, 0x4d, 0x4f, 0xab, 0x40,
0x14, 0x2d, 0xa5, 0x8f, 0x3e, 0x2e, 0x4d, 0x21, 0x93, 0xe6, 0xa5, 0x69, 0x5e, 0x4c, 0x33, 0xab,
0xc6, 0xc5, 0x18, 0x71, 0x63, 0xba, 0x54, 0xab, 0x4d, 0xd8, 0xe1, 0xca, 0x55, 0x53, 0xc9, 0x15,
0x09, 0x14, 0xc6, 0x61, 0xda, 0x38, 0x7f, 0xc5, 0x5f, 0x6b, 0x18, 0xe8, 0x07, 0x75, 0xe3, 0xee,
0xcc, 0x99, 0x73, 0xcf, 0x39, 0x77, 0x32, 0xe0, 0xa5, 0xa8, 0x4a, 0x14, 0xbb, 0x24, 0x42, 0xc6,
0x45, 0x21, 0x0b, 0xfa, 0x02, 0x66, 0x80, 0x8a, 0x50, 0xe8, 0xa7, 0x9b, 0x72, 0x95, 0xa2, 0x1a,
0x1b, 0x53, 0x63, 0xe6, 0xf8, 0x7d, 0x16, 0x6c, 0xca, 0x00, 0xd5, 0xb2, 0x13, 0x5a, 0xa9, 0x46,
0x95, 0x26, 0xe6, 0xb1, 0xd6, 0x74, 0x1b, 0xcd, 0x13, 0x8f, 0x1b, 0x4d, 0xac, 0xd1, 0x1d, 0xc0,
0xdf, 0x14, 0xd5, 0x4a, 0x2a, 0x8e, 0xf4, 0x12, 0xac, 0xfa, 0x9e, 0x4c, 0xc1, 0x79, 0x4b, 0xf2,
0x18, 0x05, 0x17, 0x49, 0x2e, 0x75, 0x82, 0x1d, 0x9e, 0x52, 0xf4, 0xcb, 0x00, 0xab, 0x0e, 0x24,
0x1e, 0x98, 0x6b, 0x91, 0x37, 0xa2, 0x0a, 0x12, 0x02, 0x3d, 0x51, 0x64, 0xa8, 0x53, 0xed, 0x50,
0x63, 0xc2, 0xa0, 0x1f, 0x15, 0xb9, 0xc4, 0x4f, 0x39, 0x36, 0xa7, 0xe6, 0xcc, 0xf1, 0x47, 0x4d,
0x61, 0x76, 0x5f, 0xd3, 0x8b, 0x5c, 0x0a, 0x15, 0xee, 0x45, 0x93, 0x39, 0x0c, 0x4e, 0x2f, 0xaa,
0x94, 0xfd, 0xb2, 0x76, 0x58, 0x41, 0x32, 0x82, 0x3f, 0xbb, 0x75, 0xb6, 0xdd, 0xc7, 0xd4, 0x87,
0x79, 0xf7, 0xd6, 0xa0, 0x8f, 0x30, 0x5c, 0xe4, 0x91, 0x50, 0x5c, 0x86, 0xf8, 0xb1, 0xc5, 0x52,
0x92, 0x7f, 0xc7, 0x69, 0xc7, 0xef, 0xb1, 0x00, 0x55, 0xed, 0xf1, 0x1f, 0x6c, 0x9e, 0xad, 0x93,
0xba, 0x57, 0xe5, 0x33, 0x08, 0x8f, 0x04, 0xbd, 0x06, 0xf7, 0xe0, 0x53, 0xf2, 0x22, 0x2f, 0x91,
0x5c, 0x00, 0x44, 0x09, 0x7f, 0x47, 0xa1, 0x27, 0x0c, 0x3d, 0x71, 0xc2, 0xd0, 0x25, 0x0c, 0x1f,
0xf0, 0x57, 0xd1, 0x6d, 0xa7, 0xee, 0x0f, 0xa7, 0x2b, 0x70, 0x0f, 0x4e, 0x4d, 0x78, 0xab, 0xad,
0x71, 0xd6, 0xd6, 0xcf, 0x00, 0x02, 0x54, 0xcf, 0xf5, 0x6f, 0xa9, 0xde, 0xbb, 0xe9, 0x4e, 0x5c,
0xd6, 0x7e, 0x8d, 0x89, 0xc7, 0xce, 0xd6, 0xa2, 0x9d, 0x4a, 0xdf, 0xc4, 0x11, 0x97, 0xb5, 0x57,
0x98, 0x78, 0xec, 0xac, 0x09, 0xed, 0xbc, 0x5a, 0xfa, 0x3b, 0xde, 0x7c, 0x07, 0x00, 0x00, 0xff,
0xff, 0xa3, 0x20, 0x0a, 0xea, 0xa2, 0x02, 0x00, 0x00,
}

View File

@@ -0,0 +1,41 @@
syntax = "proto3";
message Key {
oneof key_type {
KmsKey kms_key = 1;
GpgKey gpg_key = 2;
}
}
message GpgKey {
string fingerprint = 1;
}
message KmsKey {
string arn = 1;
string role = 2;
map<string, string> context = 3;
}
message EncryptRequest {
Key key = 1;
bytes plaintext = 2;
}
message EncryptResponse {
bytes ciphertext = 1;
}
message DecryptRequest {
Key key = 1;
bytes ciphertext = 2;
}
message DecryptResponse {
bytes plaintext = 1;
}
service KeyService {
rpc Encrypt (EncryptRequest) returns (EncryptResponse) {}
rpc Decrypt (DecryptRequest) returns (DecryptResponse) {}
}

114
keyservice/server.go Normal file
View File

@@ -0,0 +1,114 @@
package keyservice
import (
"go.mozilla.org/sops/kms"
"go.mozilla.org/sops/pgp"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
)
type Server struct{}
func (ks *Server) encryptWithPgp(key *GpgKey, plaintext []byte) ([]byte, error) {
pgpKey := pgp.NewMasterKeyFromFingerprint(key.Fingerprint)
err := pgpKey.Encrypt(plaintext)
if err != nil {
return nil, err
}
return []byte(pgpKey.EncryptedKey), nil
}
func (ks *Server) encryptWithKms(key *KmsKey, plaintext []byte) ([]byte, error) {
var ctx map[string]*string
for k, v := range key.Context {
ctx[k] = &v
}
kmsKey := kms.MasterKey{
Arn: key.Arn,
Role: key.Role,
EncryptionContext: ctx,
}
err := kmsKey.Encrypt(plaintext)
if err != nil {
return nil, err
}
return []byte(kmsKey.EncryptedKey), nil
}
func (ks *Server) decryptWithPgp(key *GpgKey, ciphertext []byte) ([]byte, error) {
pgpKey := pgp.NewMasterKeyFromFingerprint(key.Fingerprint)
pgpKey.EncryptedKey = string(ciphertext)
plaintext, err := pgpKey.Decrypt()
return []byte(plaintext), err
}
func (ks *Server) decryptWithKms(key *KmsKey, ciphertext []byte) ([]byte, error) {
var ctx map[string]*string
for k, v := range key.Context {
ctx[k] = &v
}
kmsKey := kms.MasterKey{
Arn: key.Arn,
Role: key.Role,
EncryptionContext: ctx,
}
kmsKey.EncryptedKey = string(ciphertext)
plaintext, err := kmsKey.Decrypt()
return []byte(plaintext), err
}
func (ks Server) Encrypt(ctx context.Context,
req *EncryptRequest) (*EncryptResponse, error) {
key := *req.Key
switch k := key.KeyType.(type) {
case *Key_GpgKey:
ciphertext, err := ks.encryptWithPgp(k.GpgKey, req.Plaintext)
if err != nil {
return nil, err
}
return &EncryptResponse{
Ciphertext: ciphertext,
}, nil
case *Key_KmsKey:
ciphertext, err := ks.encryptWithKms(k.KmsKey, req.Plaintext)
if err != nil {
return nil, err
}
return &EncryptResponse{
Ciphertext: ciphertext,
}, nil
case nil:
return nil, grpc.Errorf(codes.NotFound, "Must provide a key")
default:
return nil, grpc.Errorf(codes.NotFound, "Unknown key type")
}
}
func (ks Server) Decrypt(ctx context.Context,
req *DecryptRequest) (*DecryptResponse, error) {
key := *req.Key
switch k := key.KeyType.(type) {
case *Key_GpgKey:
plaintext, err := ks.decryptWithPgp(k.GpgKey, req.Ciphertext)
if err != nil {
return nil, err
}
return &DecryptResponse{
Plaintext: plaintext,
}, nil
case *Key_KmsKey:
plaintext, err := ks.decryptWithKms(k.KmsKey, req.Ciphertext)
if err != nil {
return nil, err
}
return &DecryptResponse{
Plaintext: plaintext,
}, nil
case nil:
return nil, grpc.Errorf(codes.NotFound, "Must provide a key")
default:
return nil, grpc.Errorf(codes.NotFound, "Unknown key type")
}
}