Add certificate issuance, CSR signing, and cert listing to web UI

- Add SignCSR RPC to v2 CA proto and regenerate; implement handleSignCSR
  in CA engine and caServer gRPC layer; add SignCSR client method and
  POST /pki/sign-csr web route with result display in pki.html
- Fix issuer detail cert listing: template was using map-style index on
  CertSummary structs; switch to struct field access and populate
  IssuedBy/IssuedAt fields from proto response
- Add certificate detail view (cert_detail.html) with GET /cert/{serial}
  and GET /cert/{serial}/download routes
- Update Makefile proto target to generate both v1 and v2 protos

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-15 13:21:13 -07:00
parent 65c92fe5ec
commit b4dbc088cb
12 changed files with 785 additions and 82 deletions

View File

@@ -1308,6 +1308,182 @@ func (x *RenewCertResponse) GetChainPem() []byte {
return nil
}
type SignCSRRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
// issuer is the name of the issuer to sign with.
Issuer string `protobuf:"bytes,2,opt,name=issuer,proto3" json:"issuer,omitempty"`
// csr_pem is the PEM-encoded PKCS#10 certificate signing request.
CsrPem []byte `protobuf:"bytes,3,opt,name=csr_pem,json=csrPem,proto3" json:"csr_pem,omitempty"`
// profile selects key usage defaults (e.g. "server", "client", "peer").
// Defaults to "server" if empty.
Profile string `protobuf:"bytes,4,opt,name=profile,proto3" json:"profile,omitempty"`
// ttl overrides the profile's default validity period (e.g. "8760h").
Ttl string `protobuf:"bytes,5,opt,name=ttl,proto3" json:"ttl,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SignCSRRequest) Reset() {
*x = SignCSRRequest{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[22]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SignCSRRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SignCSRRequest) ProtoMessage() {}
func (x *SignCSRRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[22]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SignCSRRequest.ProtoReflect.Descriptor instead.
func (*SignCSRRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{22}
}
func (x *SignCSRRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
func (x *SignCSRRequest) GetIssuer() string {
if x != nil {
return x.Issuer
}
return ""
}
func (x *SignCSRRequest) GetCsrPem() []byte {
if x != nil {
return x.CsrPem
}
return nil
}
func (x *SignCSRRequest) GetProfile() string {
if x != nil {
return x.Profile
}
return ""
}
func (x *SignCSRRequest) GetTtl() string {
if x != nil {
return x.Ttl
}
return ""
}
type SignCSRResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Serial string `protobuf:"bytes,1,opt,name=serial,proto3" json:"serial,omitempty"`
CommonName string `protobuf:"bytes,2,opt,name=common_name,json=commonName,proto3" json:"common_name,omitempty"`
Sans []string `protobuf:"bytes,3,rep,name=sans,proto3" json:"sans,omitempty"`
IssuedBy string `protobuf:"bytes,4,opt,name=issued_by,json=issuedBy,proto3" json:"issued_by,omitempty"`
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
// cert_pem is the signed leaf certificate. No private key is returned
// because the caller already holds it.
CertPem []byte `protobuf:"bytes,6,opt,name=cert_pem,json=certPem,proto3" json:"cert_pem,omitempty"`
// chain_pem contains the full chain: leaf + issuer + root, PEM-concatenated.
ChainPem []byte `protobuf:"bytes,7,opt,name=chain_pem,json=chainPem,proto3" json:"chain_pem,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *SignCSRResponse) Reset() {
*x = SignCSRResponse{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[23]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *SignCSRResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SignCSRResponse) ProtoMessage() {}
func (x *SignCSRResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[23]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SignCSRResponse.ProtoReflect.Descriptor instead.
func (*SignCSRResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{23}
}
func (x *SignCSRResponse) GetSerial() string {
if x != nil {
return x.Serial
}
return ""
}
func (x *SignCSRResponse) GetCommonName() string {
if x != nil {
return x.CommonName
}
return ""
}
func (x *SignCSRResponse) GetSans() []string {
if x != nil {
return x.Sans
}
return nil
}
func (x *SignCSRResponse) GetIssuedBy() string {
if x != nil {
return x.IssuedBy
}
return ""
}
func (x *SignCSRResponse) GetExpiresAt() *timestamppb.Timestamp {
if x != nil {
return x.ExpiresAt
}
return nil
}
func (x *SignCSRResponse) GetCertPem() []byte {
if x != nil {
return x.CertPem
}
return nil
}
func (x *SignCSRResponse) GetChainPem() []byte {
if x != nil {
return x.ChainPem
}
return nil
}
// CertRecord is the full certificate record including the PEM-encoded cert.
type CertRecord struct {
state protoimpl.MessageState `protogen:"open.v1"`
@@ -1327,7 +1503,7 @@ type CertRecord struct {
func (x *CertRecord) Reset() {
*x = CertRecord{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[22]
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1339,7 +1515,7 @@ func (x *CertRecord) String() string {
func (*CertRecord) ProtoMessage() {}
func (x *CertRecord) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[22]
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[24]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1352,7 +1528,7 @@ func (x *CertRecord) ProtoReflect() protoreflect.Message {
// Deprecated: Use CertRecord.ProtoReflect.Descriptor instead.
func (*CertRecord) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{22}
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{24}
}
func (x *CertRecord) GetSerial() string {
@@ -1435,7 +1611,7 @@ type CertSummary struct {
func (x *CertSummary) Reset() {
*x = CertSummary{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[23]
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1447,7 +1623,7 @@ func (x *CertSummary) String() string {
func (*CertSummary) ProtoMessage() {}
func (x *CertSummary) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[23]
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[25]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1460,7 +1636,7 @@ func (x *CertSummary) ProtoReflect() protoreflect.Message {
// Deprecated: Use CertSummary.ProtoReflect.Descriptor instead.
func (*CertSummary) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{23}
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{25}
}
func (x *CertSummary) GetSerial() string {
@@ -1606,7 +1782,23 @@ const file_proto_metacrypt_v2_ca_proto_rawDesc = "" +
"expires_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt\x12\x19\n" +
"\bcert_pem\x18\x06 \x01(\fR\acertPem\x12\x17\n" +
"\akey_pem\x18\a \x01(\fR\x06keyPem\x12\x1b\n" +
"\tchain_pem\x18\b \x01(\fR\bchainPem\"\xb7\x02\n" +
"\tchain_pem\x18\b \x01(\fR\bchainPem\"\x83\x01\n" +
"\x0eSignCSRRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\x12\x16\n" +
"\x06issuer\x18\x02 \x01(\tR\x06issuer\x12\x17\n" +
"\acsr_pem\x18\x03 \x01(\fR\x06csrPem\x12\x18\n" +
"\aprofile\x18\x04 \x01(\tR\aprofile\x12\x10\n" +
"\x03ttl\x18\x05 \x01(\tR\x03ttl\"\xee\x01\n" +
"\x0fSignCSRResponse\x12\x16\n" +
"\x06serial\x18\x01 \x01(\tR\x06serial\x12\x1f\n" +
"\vcommon_name\x18\x02 \x01(\tR\n" +
"commonName\x12\x12\n" +
"\x04sans\x18\x03 \x03(\tR\x04sans\x12\x1b\n" +
"\tissued_by\x18\x04 \x01(\tR\bissuedBy\x129\n" +
"\n" +
"expires_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt\x12\x19\n" +
"\bcert_pem\x18\x06 \x01(\fR\acertPem\x12\x1b\n" +
"\tchain_pem\x18\a \x01(\fR\bchainPem\"\xb7\x02\n" +
"\n" +
"CertRecord\x12\x16\n" +
"\x06serial\x18\x01 \x01(\tR\x06serial\x12\x16\n" +
@@ -1629,7 +1821,7 @@ const file_proto_metacrypt_v2_ca_proto_rawDesc = "" +
"\tissued_by\x18\x05 \x01(\tR\bissuedBy\x127\n" +
"\tissued_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\bissuedAt\x129\n" +
"\n" +
"expires_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt2\x83\a\n" +
"expires_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt2\xcb\a\n" +
"\tCAService\x12O\n" +
"\n" +
"ImportRoot\x12\x1f.metacrypt.v2.ImportRootRequest\x1a .metacrypt.v2.ImportRootResponse\x12F\n" +
@@ -1642,7 +1834,8 @@ const file_proto_metacrypt_v2_ca_proto_rawDesc = "" +
"\tIssueCert\x12\x1e.metacrypt.v2.IssueCertRequest\x1a\x1f.metacrypt.v2.IssueCertResponse\x12F\n" +
"\aGetCert\x12\x1c.metacrypt.v2.GetCertRequest\x1a\x1d.metacrypt.v2.GetCertResponse\x12L\n" +
"\tListCerts\x12\x1e.metacrypt.v2.ListCertsRequest\x1a\x1f.metacrypt.v2.ListCertsResponse\x12L\n" +
"\tRenewCert\x12\x1e.metacrypt.v2.RenewCertRequest\x1a\x1f.metacrypt.v2.RenewCertResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
"\tRenewCert\x12\x1e.metacrypt.v2.RenewCertRequest\x1a\x1f.metacrypt.v2.RenewCertResponse\x12F\n" +
"\aSignCSR\x12\x1c.metacrypt.v2.SignCSRRequest\x1a\x1d.metacrypt.v2.SignCSRResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
var (
file_proto_metacrypt_v2_ca_proto_rawDescOnce sync.Once
@@ -1656,7 +1849,7 @@ func file_proto_metacrypt_v2_ca_proto_rawDescGZIP() []byte {
return file_proto_metacrypt_v2_ca_proto_rawDescData
}
var file_proto_metacrypt_v2_ca_proto_msgTypes = make([]protoimpl.MessageInfo, 24)
var file_proto_metacrypt_v2_ca_proto_msgTypes = make([]protoimpl.MessageInfo, 26)
var file_proto_metacrypt_v2_ca_proto_goTypes = []any{
(*ImportRootRequest)(nil), // 0: metacrypt.v2.ImportRootRequest
(*ImportRootResponse)(nil), // 1: metacrypt.v2.ImportRootResponse
@@ -1680,47 +1873,52 @@ var file_proto_metacrypt_v2_ca_proto_goTypes = []any{
(*ListCertsResponse)(nil), // 19: metacrypt.v2.ListCertsResponse
(*RenewCertRequest)(nil), // 20: metacrypt.v2.RenewCertRequest
(*RenewCertResponse)(nil), // 21: metacrypt.v2.RenewCertResponse
(*CertRecord)(nil), // 22: metacrypt.v2.CertRecord
(*CertSummary)(nil), // 23: metacrypt.v2.CertSummary
(*timestamppb.Timestamp)(nil), // 24: google.protobuf.Timestamp
(*SignCSRRequest)(nil), // 22: metacrypt.v2.SignCSRRequest
(*SignCSRResponse)(nil), // 23: metacrypt.v2.SignCSRResponse
(*CertRecord)(nil), // 24: metacrypt.v2.CertRecord
(*CertSummary)(nil), // 25: metacrypt.v2.CertSummary
(*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp
}
var file_proto_metacrypt_v2_ca_proto_depIdxs = []int32{
24, // 0: metacrypt.v2.ImportRootResponse.expires_at:type_name -> google.protobuf.Timestamp
24, // 1: metacrypt.v2.IssueCertResponse.expires_at:type_name -> google.protobuf.Timestamp
22, // 2: metacrypt.v2.GetCertResponse.cert:type_name -> metacrypt.v2.CertRecord
23, // 3: metacrypt.v2.ListCertsResponse.certs:type_name -> metacrypt.v2.CertSummary
24, // 4: metacrypt.v2.RenewCertResponse.expires_at:type_name -> google.protobuf.Timestamp
24, // 5: metacrypt.v2.CertRecord.issued_at:type_name -> google.protobuf.Timestamp
24, // 6: metacrypt.v2.CertRecord.expires_at:type_name -> google.protobuf.Timestamp
24, // 7: metacrypt.v2.CertSummary.issued_at:type_name -> google.protobuf.Timestamp
24, // 8: metacrypt.v2.CertSummary.expires_at:type_name -> google.protobuf.Timestamp
0, // 9: metacrypt.v2.CAService.ImportRoot:input_type -> metacrypt.v2.ImportRootRequest
2, // 10: metacrypt.v2.CAService.GetRoot:input_type -> metacrypt.v2.GetRootRequest
4, // 11: metacrypt.v2.CAService.CreateIssuer:input_type -> metacrypt.v2.CreateIssuerRequest
6, // 12: metacrypt.v2.CAService.DeleteIssuer:input_type -> metacrypt.v2.DeleteIssuerRequest
8, // 13: metacrypt.v2.CAService.ListIssuers:input_type -> metacrypt.v2.ListIssuersRequest
10, // 14: metacrypt.v2.CAService.GetIssuer:input_type -> metacrypt.v2.GetIssuerRequest
12, // 15: metacrypt.v2.CAService.GetChain:input_type -> metacrypt.v2.CAServiceGetChainRequest
14, // 16: metacrypt.v2.CAService.IssueCert:input_type -> metacrypt.v2.IssueCertRequest
16, // 17: metacrypt.v2.CAService.GetCert:input_type -> metacrypt.v2.GetCertRequest
18, // 18: metacrypt.v2.CAService.ListCerts:input_type -> metacrypt.v2.ListCertsRequest
20, // 19: metacrypt.v2.CAService.RenewCert:input_type -> metacrypt.v2.RenewCertRequest
1, // 20: metacrypt.v2.CAService.ImportRoot:output_type -> metacrypt.v2.ImportRootResponse
3, // 21: metacrypt.v2.CAService.GetRoot:output_type -> metacrypt.v2.GetRootResponse
5, // 22: metacrypt.v2.CAService.CreateIssuer:output_type -> metacrypt.v2.CreateIssuerResponse
7, // 23: metacrypt.v2.CAService.DeleteIssuer:output_type -> metacrypt.v2.DeleteIssuerResponse
9, // 24: metacrypt.v2.CAService.ListIssuers:output_type -> metacrypt.v2.ListIssuersResponse
11, // 25: metacrypt.v2.CAService.GetIssuer:output_type -> metacrypt.v2.GetIssuerResponse
13, // 26: metacrypt.v2.CAService.GetChain:output_type -> metacrypt.v2.CAServiceGetChainResponse
15, // 27: metacrypt.v2.CAService.IssueCert:output_type -> metacrypt.v2.IssueCertResponse
17, // 28: metacrypt.v2.CAService.GetCert:output_type -> metacrypt.v2.GetCertResponse
19, // 29: metacrypt.v2.CAService.ListCerts:output_type -> metacrypt.v2.ListCertsResponse
21, // 30: metacrypt.v2.CAService.RenewCert:output_type -> metacrypt.v2.RenewCertResponse
20, // [20:31] is the sub-list for method output_type
9, // [9:20] is the sub-list for method input_type
9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
26, // 0: metacrypt.v2.ImportRootResponse.expires_at:type_name -> google.protobuf.Timestamp
26, // 1: metacrypt.v2.IssueCertResponse.expires_at:type_name -> google.protobuf.Timestamp
24, // 2: metacrypt.v2.GetCertResponse.cert:type_name -> metacrypt.v2.CertRecord
25, // 3: metacrypt.v2.ListCertsResponse.certs:type_name -> metacrypt.v2.CertSummary
26, // 4: metacrypt.v2.RenewCertResponse.expires_at:type_name -> google.protobuf.Timestamp
26, // 5: metacrypt.v2.SignCSRResponse.expires_at:type_name -> google.protobuf.Timestamp
26, // 6: metacrypt.v2.CertRecord.issued_at:type_name -> google.protobuf.Timestamp
26, // 7: metacrypt.v2.CertRecord.expires_at:type_name -> google.protobuf.Timestamp
26, // 8: metacrypt.v2.CertSummary.issued_at:type_name -> google.protobuf.Timestamp
26, // 9: metacrypt.v2.CertSummary.expires_at:type_name -> google.protobuf.Timestamp
0, // 10: metacrypt.v2.CAService.ImportRoot:input_type -> metacrypt.v2.ImportRootRequest
2, // 11: metacrypt.v2.CAService.GetRoot:input_type -> metacrypt.v2.GetRootRequest
4, // 12: metacrypt.v2.CAService.CreateIssuer:input_type -> metacrypt.v2.CreateIssuerRequest
6, // 13: metacrypt.v2.CAService.DeleteIssuer:input_type -> metacrypt.v2.DeleteIssuerRequest
8, // 14: metacrypt.v2.CAService.ListIssuers:input_type -> metacrypt.v2.ListIssuersRequest
10, // 15: metacrypt.v2.CAService.GetIssuer:input_type -> metacrypt.v2.GetIssuerRequest
12, // 16: metacrypt.v2.CAService.GetChain:input_type -> metacrypt.v2.CAServiceGetChainRequest
14, // 17: metacrypt.v2.CAService.IssueCert:input_type -> metacrypt.v2.IssueCertRequest
16, // 18: metacrypt.v2.CAService.GetCert:input_type -> metacrypt.v2.GetCertRequest
18, // 19: metacrypt.v2.CAService.ListCerts:input_type -> metacrypt.v2.ListCertsRequest
20, // 20: metacrypt.v2.CAService.RenewCert:input_type -> metacrypt.v2.RenewCertRequest
22, // 21: metacrypt.v2.CAService.SignCSR:input_type -> metacrypt.v2.SignCSRRequest
1, // 22: metacrypt.v2.CAService.ImportRoot:output_type -> metacrypt.v2.ImportRootResponse
3, // 23: metacrypt.v2.CAService.GetRoot:output_type -> metacrypt.v2.GetRootResponse
5, // 24: metacrypt.v2.CAService.CreateIssuer:output_type -> metacrypt.v2.CreateIssuerResponse
7, // 25: metacrypt.v2.CAService.DeleteIssuer:output_type -> metacrypt.v2.DeleteIssuerResponse
9, // 26: metacrypt.v2.CAService.ListIssuers:output_type -> metacrypt.v2.ListIssuersResponse
11, // 27: metacrypt.v2.CAService.GetIssuer:output_type -> metacrypt.v2.GetIssuerResponse
13, // 28: metacrypt.v2.CAService.GetChain:output_type -> metacrypt.v2.CAServiceGetChainResponse
15, // 29: metacrypt.v2.CAService.IssueCert:output_type -> metacrypt.v2.IssueCertResponse
17, // 30: metacrypt.v2.CAService.GetCert:output_type -> metacrypt.v2.GetCertResponse
19, // 31: metacrypt.v2.CAService.ListCerts:output_type -> metacrypt.v2.ListCertsResponse
21, // 32: metacrypt.v2.CAService.RenewCert:output_type -> metacrypt.v2.RenewCertResponse
23, // 33: metacrypt.v2.CAService.SignCSR:output_type -> metacrypt.v2.SignCSRResponse
22, // [22:34] is the sub-list for method output_type
10, // [10:22] is the sub-list for method input_type
10, // [10:10] is the sub-list for extension type_name
10, // [10:10] is the sub-list for extension extendee
0, // [0:10] is the sub-list for field type_name
}
func init() { file_proto_metacrypt_v2_ca_proto_init() }
@@ -1734,7 +1932,7 @@ func file_proto_metacrypt_v2_ca_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_proto_metacrypt_v2_ca_proto_rawDesc), len(file_proto_metacrypt_v2_ca_proto_rawDesc)),
NumEnums: 0,
NumMessages: 24,
NumMessages: 26,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -30,6 +30,7 @@ const (
CAService_GetCert_FullMethodName = "/metacrypt.v2.CAService/GetCert"
CAService_ListCerts_FullMethodName = "/metacrypt.v2.CAService/ListCerts"
CAService_RenewCert_FullMethodName = "/metacrypt.v2.CAService/RenewCert"
CAService_SignCSR_FullMethodName = "/metacrypt.v2.CAService/SignCSR"
)
// CAServiceClient is the client API for CAService service.
@@ -67,6 +68,10 @@ type CAServiceClient interface {
// RenewCert renews an existing certificate, generating a new key and serial.
// Auth required.
RenewCert(ctx context.Context, in *RenewCertRequest, opts ...grpc.CallOption) (*RenewCertResponse, error)
// SignCSR signs an externally generated CSR with a named issuer. All Subject
// and SAN fields from the CSR are preserved exactly; profile defaults supply
// key usages and validity if not overridden. Auth required.
SignCSR(ctx context.Context, in *SignCSRRequest, opts ...grpc.CallOption) (*SignCSRResponse, error)
}
type cAServiceClient struct {
@@ -187,6 +192,16 @@ func (c *cAServiceClient) RenewCert(ctx context.Context, in *RenewCertRequest, o
return out, nil
}
func (c *cAServiceClient) SignCSR(ctx context.Context, in *SignCSRRequest, opts ...grpc.CallOption) (*SignCSRResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(SignCSRResponse)
err := c.cc.Invoke(ctx, CAService_SignCSR_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// CAServiceServer is the server API for CAService service.
// All implementations must embed UnimplementedCAServiceServer
// for forward compatibility.
@@ -222,6 +237,10 @@ type CAServiceServer interface {
// RenewCert renews an existing certificate, generating a new key and serial.
// Auth required.
RenewCert(context.Context, *RenewCertRequest) (*RenewCertResponse, error)
// SignCSR signs an externally generated CSR with a named issuer. All Subject
// and SAN fields from the CSR are preserved exactly; profile defaults supply
// key usages and validity if not overridden. Auth required.
SignCSR(context.Context, *SignCSRRequest) (*SignCSRResponse, error)
mustEmbedUnimplementedCAServiceServer()
}
@@ -265,6 +284,9 @@ func (UnimplementedCAServiceServer) ListCerts(context.Context, *ListCertsRequest
func (UnimplementedCAServiceServer) RenewCert(context.Context, *RenewCertRequest) (*RenewCertResponse, error) {
return nil, status.Error(codes.Unimplemented, "method RenewCert not implemented")
}
func (UnimplementedCAServiceServer) SignCSR(context.Context, *SignCSRRequest) (*SignCSRResponse, error) {
return nil, status.Error(codes.Unimplemented, "method SignCSR not implemented")
}
func (UnimplementedCAServiceServer) mustEmbedUnimplementedCAServiceServer() {}
func (UnimplementedCAServiceServer) testEmbeddedByValue() {}
@@ -484,6 +506,24 @@ func _CAService_RenewCert_Handler(srv interface{}, ctx context.Context, dec func
return interceptor(ctx, in, info, handler)
}
func _CAService_SignCSR_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SignCSRRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).SignCSR(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_SignCSR_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).SignCSR(ctx, req.(*SignCSRRequest))
}
return interceptor(ctx, in, info, handler)
}
// CAService_ServiceDesc is the grpc.ServiceDesc for CAService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -535,6 +575,10 @@ var CAService_ServiceDesc = grpc.ServiceDesc{
MethodName: "RenewCert",
Handler: _CAService_RenewCert_Handler,
},
{
MethodName: "SignCSR",
Handler: _CAService_SignCSR_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v2/ca.proto",