diff --git a/keyservice/internal/server/server.go b/keyservice/internal/server/server.go index 8ff9bed8a..f2da87da1 100644 --- a/keyservice/internal/server/server.go +++ b/keyservice/internal/server/server.go @@ -8,7 +8,9 @@ SPDX-License-Identifier: AGPL-3.0-only package server import ( + "bytes" "context" + "crypto/ed25519" "fmt" "log/slog" "net" @@ -18,6 +20,7 @@ import ( "github.com/edgelesssys/constellation/v2/internal/kms/kms" "github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/keyservice/keyserviceproto" + "golang.org/x/crypto/ssh" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -82,3 +85,27 @@ func (s *Server) GetDataKey(ctx context.Context, in *keyserviceproto.GetDataKeyR } return &keyserviceproto.GetDataKeyResponse{DataKey: key}, nil } + +// GetCAKey returns the CA key. +func (s *Server) GetCAKey(ctx context.Context, in *keyserviceproto.GetCAKeyRequest) (*keyserviceproto.GetCAKeyResponse, error) { + log := s.log.With("peerAddress", grpclog.PeerAddrFromContext(ctx)) + + key, err := s.conKMS.GetDEK(ctx, crypto.DEKPrefix, 256) + if err != nil { + log.With(slog.Any("error", err)).Error("Failed to get key for derivation") + return nil, status.Errorf(codes.Internal, "%v", err) + } + + _, priv, err := ed25519.GenerateKey(bytes.NewReader(key)) + if err != nil { + log.With(slog.Any("error", err)).Error("Failed to generate ed25519 key") + return nil, status.Errorf(codes.Internal, "%v", err) + } + + ca, err := ssh.NewSignerFromKey(priv) + if err != nil { + log.With(slog.Any("error", err)).Error("Failed to generate CA key") + return nil, status.Errorf(codes.Internal, "%v", err) + } + return &keyserviceproto.GetCAKeyResponse{CaKey: ssh.MarshalAuthorizedKey(ca.PublicKey())}, nil +} diff --git a/keyservice/keyserviceproto/keyservice.pb.go b/keyservice/keyserviceproto/keyservice.pb.go index 9008be73e..d2ddae3a8 100644 --- a/keyservice/keyserviceproto/keyservice.pb.go +++ b/keyservice/keyserviceproto/keyservice.pb.go @@ -250,9 +250,11 @@ var file_keyservice_keyserviceproto_keyservice_proto_goTypes = []any{ } var file_keyservice_keyserviceproto_keyservice_proto_depIdxs = []int32{ 0, // 0: kms.API.GetDataKey:input_type -> kms.GetDataKeyRequest - 1, // 1: kms.API.GetDataKey:output_type -> kms.GetDataKeyResponse - 1, // [1:2] is the sub-list for method output_type - 0, // [0:1] is the sub-list for method input_type + 2, // 1: kms.API.GetCAKey:input_type -> kms.GetCAKeyRequest + 1, // 2: kms.API.GetDataKey:output_type -> kms.GetDataKeyResponse + 3, // 3: kms.API.GetCAKey:output_type -> kms.GetCAKeyResponse + 2, // [2:4] is the sub-list for method output_type + 0, // [0:2] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name @@ -295,6 +297,7 @@ const _ = grpc.SupportPackageIsVersion6 // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type APIClient interface { GetDataKey(ctx context.Context, in *GetDataKeyRequest, opts ...grpc.CallOption) (*GetDataKeyResponse, error) + GetCAKey(ctx context.Context, in *GetCAKeyRequest, opts ...grpc.CallOption) (*GetCAKeyResponse, error) } type aPIClient struct { @@ -314,9 +317,19 @@ func (c *aPIClient) GetDataKey(ctx context.Context, in *GetDataKeyRequest, opts return out, nil } +func (c *aPIClient) GetCAKey(ctx context.Context, in *GetCAKeyRequest, opts ...grpc.CallOption) (*GetCAKeyResponse, error) { + out := new(GetCAKeyResponse) + err := c.cc.Invoke(ctx, "/kms.API/GetCAKey", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // APIServer is the server API for API service. type APIServer interface { GetDataKey(context.Context, *GetDataKeyRequest) (*GetDataKeyResponse, error) + GetCAKey(context.Context, *GetCAKeyRequest) (*GetCAKeyResponse, error) } // UnimplementedAPIServer can be embedded to have forward compatible implementations. @@ -326,6 +339,9 @@ type UnimplementedAPIServer struct { func (*UnimplementedAPIServer) GetDataKey(context.Context, *GetDataKeyRequest) (*GetDataKeyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetDataKey not implemented") } +func (*UnimplementedAPIServer) GetCAKey(context.Context, *GetCAKeyRequest) (*GetCAKeyResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetCAKey not implemented") +} func RegisterAPIServer(s *grpc.Server, srv APIServer) { s.RegisterService(&_API_serviceDesc, srv) @@ -349,6 +365,24 @@ func _API_GetDataKey_Handler(srv interface{}, ctx context.Context, dec func(inte return interceptor(ctx, in, info, handler) } +func _API_GetCAKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetCAKeyRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(APIServer).GetCAKey(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/kms.API/GetCAKey", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(APIServer).GetCAKey(ctx, req.(*GetCAKeyRequest)) + } + return interceptor(ctx, in, info, handler) +} + var _API_serviceDesc = grpc.ServiceDesc{ ServiceName: "kms.API", HandlerType: (*APIServer)(nil), @@ -357,6 +391,10 @@ var _API_serviceDesc = grpc.ServiceDesc{ MethodName: "GetDataKey", Handler: _API_GetDataKey_Handler, }, + { + MethodName: "GetCAKey", + Handler: _API_GetCAKey_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "keyservice/keyserviceproto/keyservice.proto", diff --git a/keyservice/keyserviceproto/keyservice.proto b/keyservice/keyserviceproto/keyservice.proto index 0ae5b7d89..d6a09f6f7 100644 --- a/keyservice/keyserviceproto/keyservice.proto +++ b/keyservice/keyserviceproto/keyservice.proto @@ -4,7 +4,10 @@ package kms; option go_package = "github.com/edgelesssys/constellation/v2/keyservice/keyserviceproto"; -service API { rpc GetDataKey(GetDataKeyRequest) returns (GetDataKeyResponse); } +service API { + rpc GetDataKey(GetDataKeyRequest) returns (GetDataKeyResponse); + rpc GetCAKey(GetCAKeyRequest) returns (GetCAKeyResponse); +} message GetDataKeyRequest { string data_key_id = 1;