Add certificate revocation, deletion, and retrieval

Admins can now revoke or delete certificate records from the cert detail
page in the web UI. Revoked certificates display a [REVOKED] badge and
show revocation metadata (time and actor). Deletion redirects to the
issuer page.

The REST API gains three new authenticated endpoints that mirror the
gRPC surface:
  GET    /v1/ca/{mount}/cert/{serial}         (auth required)
  POST   /v1/ca/{mount}/cert/{serial}/revoke  (admin only)
  DELETE /v1/ca/{mount}/cert/{serial}         (admin only)

The CA engine stores revocation state (revoked, revoked_at, revoked_by)
directly in the existing CertRecord barrier entry. The proto CertRecord
message is extended with the same three fields (field numbers 10–12).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-15 13:37:54 -07:00
parent 74e35ce63e
commit d574685b99
27 changed files with 839 additions and 91 deletions

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.4
// protoc v3.20.3
// source: proto/metacrypt/v1/acme.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.33.4
// - protoc v3.20.3
// source: proto/metacrypt/v1/acme.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.4
// protoc v3.20.3
// source: proto/metacrypt/v1/auth.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.33.4
// - protoc v3.20.3
// source: proto/metacrypt/v1/auth.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.4
// protoc v3.20.3
// source: proto/metacrypt/v1/common.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.4
// protoc v3.20.3
// source: proto/metacrypt/v1/engine.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.33.4
// - protoc v3.20.3
// source: proto/metacrypt/v1/engine.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.4
// protoc v3.20.3
// source: proto/metacrypt/v1/pki.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.33.4
// - protoc v3.20.3
// source: proto/metacrypt/v1/pki.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.4
// protoc v3.20.3
// source: proto/metacrypt/v1/policy.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.33.4
// - protoc v3.20.3
// source: proto/metacrypt/v1/policy.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc v6.33.4
// protoc v3.20.3
// source: proto/metacrypt/v1/system.proto
package metacryptv1

View File

@@ -1,7 +1,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc v6.33.4
// - protoc v3.20.3
// source: proto/metacrypt/v1/system.proto
package metacryptv1

View File

@@ -1484,6 +1484,198 @@ func (x *SignCSRResponse) GetChainPem() []byte {
return nil
}
type RevokeCertRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
Serial string `protobuf:"bytes,2,opt,name=serial,proto3" json:"serial,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RevokeCertRequest) Reset() {
*x = RevokeCertRequest{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[24]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RevokeCertRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RevokeCertRequest) ProtoMessage() {}
func (x *RevokeCertRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[24]
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 RevokeCertRequest.ProtoReflect.Descriptor instead.
func (*RevokeCertRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{24}
}
func (x *RevokeCertRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
func (x *RevokeCertRequest) GetSerial() string {
if x != nil {
return x.Serial
}
return ""
}
type RevokeCertResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
Serial string `protobuf:"bytes,1,opt,name=serial,proto3" json:"serial,omitempty"`
RevokedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=revoked_at,json=revokedAt,proto3" json:"revoked_at,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *RevokeCertResponse) Reset() {
*x = RevokeCertResponse{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[25]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *RevokeCertResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RevokeCertResponse) ProtoMessage() {}
func (x *RevokeCertResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[25]
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 RevokeCertResponse.ProtoReflect.Descriptor instead.
func (*RevokeCertResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{25}
}
func (x *RevokeCertResponse) GetSerial() string {
if x != nil {
return x.Serial
}
return ""
}
func (x *RevokeCertResponse) GetRevokedAt() *timestamppb.Timestamp {
if x != nil {
return x.RevokedAt
}
return nil
}
type DeleteCertRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
Mount string `protobuf:"bytes,1,opt,name=mount,proto3" json:"mount,omitempty"`
Serial string `protobuf:"bytes,2,opt,name=serial,proto3" json:"serial,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteCertRequest) Reset() {
*x = DeleteCertRequest{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[26]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteCertRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteCertRequest) ProtoMessage() {}
func (x *DeleteCertRequest) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[26]
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 DeleteCertRequest.ProtoReflect.Descriptor instead.
func (*DeleteCertRequest) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{26}
}
func (x *DeleteCertRequest) GetMount() string {
if x != nil {
return x.Mount
}
return ""
}
func (x *DeleteCertRequest) GetSerial() string {
if x != nil {
return x.Serial
}
return ""
}
type DeleteCertResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *DeleteCertResponse) Reset() {
*x = DeleteCertResponse{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[27]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *DeleteCertResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteCertResponse) ProtoMessage() {}
func (x *DeleteCertResponse) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[27]
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 DeleteCertResponse.ProtoReflect.Descriptor instead.
func (*DeleteCertResponse) Descriptor() ([]byte, []int) {
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{27}
}
// CertRecord is the full certificate record including the PEM-encoded cert.
type CertRecord struct {
state protoimpl.MessageState `protogen:"open.v1"`
@@ -1496,14 +1688,20 @@ type CertRecord struct {
IssuedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=issued_at,json=issuedAt,proto3" json:"issued_at,omitempty"`
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
// cert_pem is the PEM-encoded certificate.
CertPem []byte `protobuf:"bytes,9,opt,name=cert_pem,json=certPem,proto3" json:"cert_pem,omitempty"`
CertPem []byte `protobuf:"bytes,9,opt,name=cert_pem,json=certPem,proto3" json:"cert_pem,omitempty"`
// revoked indicates whether the certificate has been revoked.
Revoked bool `protobuf:"varint,10,opt,name=revoked,proto3" json:"revoked,omitempty"`
// revoked_at is the time the certificate was revoked, if applicable.
RevokedAt *timestamppb.Timestamp `protobuf:"bytes,11,opt,name=revoked_at,json=revokedAt,proto3" json:"revoked_at,omitempty"`
// revoked_by is the username of the admin who revoked the certificate.
RevokedBy string `protobuf:"bytes,12,opt,name=revoked_by,json=revokedBy,proto3" json:"revoked_by,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *CertRecord) Reset() {
*x = CertRecord{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[24]
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[28]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1515,7 +1713,7 @@ func (x *CertRecord) String() string {
func (*CertRecord) ProtoMessage() {}
func (x *CertRecord) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[24]
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[28]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1528,7 +1726,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{24}
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{28}
}
func (x *CertRecord) GetSerial() string {
@@ -1594,6 +1792,27 @@ func (x *CertRecord) GetCertPem() []byte {
return nil
}
func (x *CertRecord) GetRevoked() bool {
if x != nil {
return x.Revoked
}
return false
}
func (x *CertRecord) GetRevokedAt() *timestamppb.Timestamp {
if x != nil {
return x.RevokedAt
}
return nil
}
func (x *CertRecord) GetRevokedBy() string {
if x != nil {
return x.RevokedBy
}
return ""
}
// CertSummary is a lightweight certificate record without the PEM data,
// suitable for list responses.
type CertSummary struct {
@@ -1611,7 +1830,7 @@ type CertSummary struct {
func (x *CertSummary) Reset() {
*x = CertSummary{}
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[25]
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[29]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1623,7 +1842,7 @@ func (x *CertSummary) String() string {
func (*CertSummary) ProtoMessage() {}
func (x *CertSummary) ProtoReflect() protoreflect.Message {
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[25]
mi := &file_proto_metacrypt_v2_ca_proto_msgTypes[29]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1636,7 +1855,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{25}
return file_proto_metacrypt_v2_ca_proto_rawDescGZIP(), []int{29}
}
func (x *CertSummary) GetSerial() string {
@@ -1798,7 +2017,18 @@ const file_proto_metacrypt_v2_ca_proto_rawDesc = "" +
"\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" +
"\tchain_pem\x18\a \x01(\fR\bchainPem\"A\n" +
"\x11RevokeCertRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\x12\x16\n" +
"\x06serial\x18\x02 \x01(\tR\x06serial\"g\n" +
"\x12RevokeCertResponse\x12\x16\n" +
"\x06serial\x18\x01 \x01(\tR\x06serial\x129\n" +
"\n" +
"revoked_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\trevokedAt\"A\n" +
"\x11DeleteCertRequest\x12\x14\n" +
"\x05mount\x18\x01 \x01(\tR\x05mount\x12\x16\n" +
"\x06serial\x18\x02 \x01(\tR\x06serial\"\x14\n" +
"\x12DeleteCertResponse\"\xab\x03\n" +
"\n" +
"CertRecord\x12\x16\n" +
"\x06serial\x18\x01 \x01(\tR\x06serial\x12\x16\n" +
@@ -1811,7 +2041,13 @@ const file_proto_metacrypt_v2_ca_proto_rawDesc = "" +
"\tissued_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\bissuedAt\x129\n" +
"\n" +
"expires_at\x18\b \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt\x12\x19\n" +
"\bcert_pem\x18\t \x01(\fR\acertPem\"\x89\x02\n" +
"\bcert_pem\x18\t \x01(\fR\acertPem\x12\x18\n" +
"\arevoked\x18\n" +
" \x01(\bR\arevoked\x129\n" +
"\n" +
"revoked_at\x18\v \x01(\v2\x1a.google.protobuf.TimestampR\trevokedAt\x12\x1d\n" +
"\n" +
"revoked_by\x18\f \x01(\tR\trevokedBy\"\x89\x02\n" +
"\vCertSummary\x12\x16\n" +
"\x06serial\x18\x01 \x01(\tR\x06serial\x12\x16\n" +
"\x06issuer\x18\x02 \x01(\tR\x06issuer\x12\x1f\n" +
@@ -1821,7 +2057,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\xcb\a\n" +
"expires_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt2\xed\b\n" +
"\tCAService\x12O\n" +
"\n" +
"ImportRoot\x12\x1f.metacrypt.v2.ImportRootRequest\x1a .metacrypt.v2.ImportRootResponse\x12F\n" +
@@ -1835,7 +2071,11 @@ const file_proto_metacrypt_v2_ca_proto_rawDesc = "" +
"\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.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"
"\aSignCSR\x12\x1c.metacrypt.v2.SignCSRRequest\x1a\x1d.metacrypt.v2.SignCSRResponse\x12O\n" +
"\n" +
"RevokeCert\x12\x1f.metacrypt.v2.RevokeCertRequest\x1a .metacrypt.v2.RevokeCertResponse\x12O\n" +
"\n" +
"DeleteCert\x12\x1f.metacrypt.v2.DeleteCertRequest\x1a .metacrypt.v2.DeleteCertResponseB>Z<git.wntrmute.dev/kyle/metacrypt/gen/metacrypt/v2;metacryptv2b\x06proto3"
var (
file_proto_metacrypt_v2_ca_proto_rawDescOnce sync.Once
@@ -1849,7 +2089,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, 26)
var file_proto_metacrypt_v2_ca_proto_msgTypes = make([]protoimpl.MessageInfo, 30)
var file_proto_metacrypt_v2_ca_proto_goTypes = []any{
(*ImportRootRequest)(nil), // 0: metacrypt.v2.ImportRootRequest
(*ImportRootResponse)(nil), // 1: metacrypt.v2.ImportRootResponse
@@ -1875,50 +2115,60 @@ var file_proto_metacrypt_v2_ca_proto_goTypes = []any{
(*RenewCertResponse)(nil), // 21: metacrypt.v2.RenewCertResponse
(*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
(*RevokeCertRequest)(nil), // 24: metacrypt.v2.RevokeCertRequest
(*RevokeCertResponse)(nil), // 25: metacrypt.v2.RevokeCertResponse
(*DeleteCertRequest)(nil), // 26: metacrypt.v2.DeleteCertRequest
(*DeleteCertResponse)(nil), // 27: metacrypt.v2.DeleteCertResponse
(*CertRecord)(nil), // 28: metacrypt.v2.CertRecord
(*CertSummary)(nil), // 29: metacrypt.v2.CertSummary
(*timestamppb.Timestamp)(nil), // 30: google.protobuf.Timestamp
}
var file_proto_metacrypt_v2_ca_proto_depIdxs = []int32{
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
30, // 0: metacrypt.v2.ImportRootResponse.expires_at:type_name -> google.protobuf.Timestamp
30, // 1: metacrypt.v2.IssueCertResponse.expires_at:type_name -> google.protobuf.Timestamp
28, // 2: metacrypt.v2.GetCertResponse.cert:type_name -> metacrypt.v2.CertRecord
29, // 3: metacrypt.v2.ListCertsResponse.certs:type_name -> metacrypt.v2.CertSummary
30, // 4: metacrypt.v2.RenewCertResponse.expires_at:type_name -> google.protobuf.Timestamp
30, // 5: metacrypt.v2.SignCSRResponse.expires_at:type_name -> google.protobuf.Timestamp
30, // 6: metacrypt.v2.RevokeCertResponse.revoked_at:type_name -> google.protobuf.Timestamp
30, // 7: metacrypt.v2.CertRecord.issued_at:type_name -> google.protobuf.Timestamp
30, // 8: metacrypt.v2.CertRecord.expires_at:type_name -> google.protobuf.Timestamp
30, // 9: metacrypt.v2.CertRecord.revoked_at:type_name -> google.protobuf.Timestamp
30, // 10: metacrypt.v2.CertSummary.issued_at:type_name -> google.protobuf.Timestamp
30, // 11: metacrypt.v2.CertSummary.expires_at:type_name -> google.protobuf.Timestamp
0, // 12: metacrypt.v2.CAService.ImportRoot:input_type -> metacrypt.v2.ImportRootRequest
2, // 13: metacrypt.v2.CAService.GetRoot:input_type -> metacrypt.v2.GetRootRequest
4, // 14: metacrypt.v2.CAService.CreateIssuer:input_type -> metacrypt.v2.CreateIssuerRequest
6, // 15: metacrypt.v2.CAService.DeleteIssuer:input_type -> metacrypt.v2.DeleteIssuerRequest
8, // 16: metacrypt.v2.CAService.ListIssuers:input_type -> metacrypt.v2.ListIssuersRequest
10, // 17: metacrypt.v2.CAService.GetIssuer:input_type -> metacrypt.v2.GetIssuerRequest
12, // 18: metacrypt.v2.CAService.GetChain:input_type -> metacrypt.v2.CAServiceGetChainRequest
14, // 19: metacrypt.v2.CAService.IssueCert:input_type -> metacrypt.v2.IssueCertRequest
16, // 20: metacrypt.v2.CAService.GetCert:input_type -> metacrypt.v2.GetCertRequest
18, // 21: metacrypt.v2.CAService.ListCerts:input_type -> metacrypt.v2.ListCertsRequest
20, // 22: metacrypt.v2.CAService.RenewCert:input_type -> metacrypt.v2.RenewCertRequest
22, // 23: metacrypt.v2.CAService.SignCSR:input_type -> metacrypt.v2.SignCSRRequest
24, // 24: metacrypt.v2.CAService.RevokeCert:input_type -> metacrypt.v2.RevokeCertRequest
26, // 25: metacrypt.v2.CAService.DeleteCert:input_type -> metacrypt.v2.DeleteCertRequest
1, // 26: metacrypt.v2.CAService.ImportRoot:output_type -> metacrypt.v2.ImportRootResponse
3, // 27: metacrypt.v2.CAService.GetRoot:output_type -> metacrypt.v2.GetRootResponse
5, // 28: metacrypt.v2.CAService.CreateIssuer:output_type -> metacrypt.v2.CreateIssuerResponse
7, // 29: metacrypt.v2.CAService.DeleteIssuer:output_type -> metacrypt.v2.DeleteIssuerResponse
9, // 30: metacrypt.v2.CAService.ListIssuers:output_type -> metacrypt.v2.ListIssuersResponse
11, // 31: metacrypt.v2.CAService.GetIssuer:output_type -> metacrypt.v2.GetIssuerResponse
13, // 32: metacrypt.v2.CAService.GetChain:output_type -> metacrypt.v2.CAServiceGetChainResponse
15, // 33: metacrypt.v2.CAService.IssueCert:output_type -> metacrypt.v2.IssueCertResponse
17, // 34: metacrypt.v2.CAService.GetCert:output_type -> metacrypt.v2.GetCertResponse
19, // 35: metacrypt.v2.CAService.ListCerts:output_type -> metacrypt.v2.ListCertsResponse
21, // 36: metacrypt.v2.CAService.RenewCert:output_type -> metacrypt.v2.RenewCertResponse
23, // 37: metacrypt.v2.CAService.SignCSR:output_type -> metacrypt.v2.SignCSRResponse
25, // 38: metacrypt.v2.CAService.RevokeCert:output_type -> metacrypt.v2.RevokeCertResponse
27, // 39: metacrypt.v2.CAService.DeleteCert:output_type -> metacrypt.v2.DeleteCertResponse
26, // [26:40] is the sub-list for method output_type
12, // [12:26] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
12, // [12:12] is the sub-list for extension extendee
0, // [0:12] is the sub-list for field type_name
}
func init() { file_proto_metacrypt_v2_ca_proto_init() }
@@ -1932,7 +2182,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: 26,
NumMessages: 30,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -31,6 +31,8 @@ const (
CAService_ListCerts_FullMethodName = "/metacrypt.v2.CAService/ListCerts"
CAService_RenewCert_FullMethodName = "/metacrypt.v2.CAService/RenewCert"
CAService_SignCSR_FullMethodName = "/metacrypt.v2.CAService/SignCSR"
CAService_RevokeCert_FullMethodName = "/metacrypt.v2.CAService/RevokeCert"
CAService_DeleteCert_FullMethodName = "/metacrypt.v2.CAService/DeleteCert"
)
// CAServiceClient is the client API for CAService service.
@@ -40,8 +42,8 @@ const (
// CAService provides typed, authenticated access to CA engine operations.
// All RPCs require the service to be unsealed. Write operations (CreateIssuer,
// DeleteIssuer, ImportRoot, IssueCert, RenewCert) require authentication.
// Admin-only operations (CreateIssuer, DeleteIssuer, ImportRoot) additionally
// require the caller to have admin privileges.
// Admin-only operations (CreateIssuer, DeleteIssuer, ImportRoot, RevokeCert,
// DeleteCert) additionally require the caller to have admin privileges.
type CAServiceClient interface {
// ImportRoot imports an existing root CA certificate and private key.
// Admin only. Only allowed when no valid root exists.
@@ -72,6 +74,11 @@ type CAServiceClient interface {
// 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)
// RevokeCert marks a certificate as revoked by serial number. Admin only.
RevokeCert(ctx context.Context, in *RevokeCertRequest, opts ...grpc.CallOption) (*RevokeCertResponse, error)
// DeleteCert permanently removes a certificate record by serial number.
// Admin only.
DeleteCert(ctx context.Context, in *DeleteCertRequest, opts ...grpc.CallOption) (*DeleteCertResponse, error)
}
type cAServiceClient struct {
@@ -202,6 +209,26 @@ func (c *cAServiceClient) SignCSR(ctx context.Context, in *SignCSRRequest, opts
return out, nil
}
func (c *cAServiceClient) RevokeCert(ctx context.Context, in *RevokeCertRequest, opts ...grpc.CallOption) (*RevokeCertResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(RevokeCertResponse)
err := c.cc.Invoke(ctx, CAService_RevokeCert_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *cAServiceClient) DeleteCert(ctx context.Context, in *DeleteCertRequest, opts ...grpc.CallOption) (*DeleteCertResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(DeleteCertResponse)
err := c.cc.Invoke(ctx, CAService_DeleteCert_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.
@@ -209,8 +236,8 @@ func (c *cAServiceClient) SignCSR(ctx context.Context, in *SignCSRRequest, opts
// CAService provides typed, authenticated access to CA engine operations.
// All RPCs require the service to be unsealed. Write operations (CreateIssuer,
// DeleteIssuer, ImportRoot, IssueCert, RenewCert) require authentication.
// Admin-only operations (CreateIssuer, DeleteIssuer, ImportRoot) additionally
// require the caller to have admin privileges.
// Admin-only operations (CreateIssuer, DeleteIssuer, ImportRoot, RevokeCert,
// DeleteCert) additionally require the caller to have admin privileges.
type CAServiceServer interface {
// ImportRoot imports an existing root CA certificate and private key.
// Admin only. Only allowed when no valid root exists.
@@ -241,6 +268,11 @@ type CAServiceServer interface {
// 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)
// RevokeCert marks a certificate as revoked by serial number. Admin only.
RevokeCert(context.Context, *RevokeCertRequest) (*RevokeCertResponse, error)
// DeleteCert permanently removes a certificate record by serial number.
// Admin only.
DeleteCert(context.Context, *DeleteCertRequest) (*DeleteCertResponse, error)
mustEmbedUnimplementedCAServiceServer()
}
@@ -287,6 +319,12 @@ func (UnimplementedCAServiceServer) RenewCert(context.Context, *RenewCertRequest
func (UnimplementedCAServiceServer) SignCSR(context.Context, *SignCSRRequest) (*SignCSRResponse, error) {
return nil, status.Error(codes.Unimplemented, "method SignCSR not implemented")
}
func (UnimplementedCAServiceServer) RevokeCert(context.Context, *RevokeCertRequest) (*RevokeCertResponse, error) {
return nil, status.Error(codes.Unimplemented, "method RevokeCert not implemented")
}
func (UnimplementedCAServiceServer) DeleteCert(context.Context, *DeleteCertRequest) (*DeleteCertResponse, error) {
return nil, status.Error(codes.Unimplemented, "method DeleteCert not implemented")
}
func (UnimplementedCAServiceServer) mustEmbedUnimplementedCAServiceServer() {}
func (UnimplementedCAServiceServer) testEmbeddedByValue() {}
@@ -524,6 +562,42 @@ func _CAService_SignCSR_Handler(srv interface{}, ctx context.Context, dec func(i
return interceptor(ctx, in, info, handler)
}
func _CAService_RevokeCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RevokeCertRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).RevokeCert(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_RevokeCert_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).RevokeCert(ctx, req.(*RevokeCertRequest))
}
return interceptor(ctx, in, info, handler)
}
func _CAService_DeleteCert_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeleteCertRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(CAServiceServer).DeleteCert(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: CAService_DeleteCert_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(CAServiceServer).DeleteCert(ctx, req.(*DeleteCertRequest))
}
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)
@@ -579,6 +653,14 @@ var CAService_ServiceDesc = grpc.ServiceDesc{
MethodName: "SignCSR",
Handler: _CAService_SignCSR_Handler,
},
{
MethodName: "RevokeCert",
Handler: _CAService_RevokeCert_Handler,
},
{
MethodName: "DeleteCert",
Handler: _CAService_DeleteCert_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "proto/metacrypt/v2/ca.proto",