diff --git a/ra/proto/ra.pb.go b/ra/proto/ra.pb.go index cbe1c487c70..d2da05fcc67 100644 --- a/ra/proto/ra.pb.go +++ b/ra/proto/ra.pb.go @@ -358,16 +358,17 @@ type AdministrativelyRevokeCertificateRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // The `cert` field may be omitted. If it is omitted, - // the revocation reason (`code`) must not be keyCompromise, - // and purging the Akamai cache will not happen because the - // base URL for the certificate's OCSP server is not known. + // Deprecated: this field is ignored. Cert []byte `protobuf:"bytes,1,opt,name=cert,proto3" json:"cert,omitempty"` // The `serial` field is required. Serial string `protobuf:"bytes,4,opt,name=serial,proto3" json:"serial,omitempty"` Code int64 `protobuf:"varint,2,opt,name=code,proto3" json:"code,omitempty"` AdminName string `protobuf:"bytes,3,opt,name=adminName,proto3" json:"adminName,omitempty"` SkipBlockKey bool `protobuf:"varint,5,opt,name=skipBlockKey,proto3" json:"skipBlockKey,omitempty"` + // If the malformed flag is set, the RA will not attempt to parse the + // certificate in question. In this case, the keyCompromise reason cannot be + // specified, because the key cannot be blocked. + Malformed bool `protobuf:"varint,6,opt,name=malformed,proto3" json:"malformed,omitempty"` } func (x *AdministrativelyRevokeCertificateRequest) Reset() { @@ -437,6 +438,13 @@ func (x *AdministrativelyRevokeCertificateRequest) GetSkipBlockKey() bool { return false } +func (x *AdministrativelyRevokeCertificateRequest) GetMalformed() bool { + if x != nil { + return x.Malformed + } + return false +} + type NewOrderRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -591,7 +599,7 @@ var file_ra_proto_rawDesc = []byte{ 0x44, 0x22, 0x32, 0x0a, 0x16, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x63, 0x65, 0x72, 0x74, 0x4a, - 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xac, 0x01, 0x0a, 0x28, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, + 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xca, 0x01, 0x0a, 0x28, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, @@ -602,71 +610,73 @@ var file_ra_proto_rawDesc = []byte{ 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x42, 0x6c, 0x6f, 0x63, - 0x6b, 0x4b, 0x65, 0x79, 0x22, 0x4f, 0x0a, 0x0f, 0x4e, 0x65, 0x77, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, - 0x14, 0x0a, 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x14, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, - 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, - 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, - 0x12, 0x10, 0x0a, 0x03, 0x63, 0x73, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, - 0x73, 0x72, 0x32, 0xad, 0x06, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x0f, - 0x4e, 0x65, 0x77, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x1a, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x12, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x1d, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, - 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x11, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x56, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, 0x72, 0x61, 0x2e, 0x50, - 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x46, - 0x0a, 0x16, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, - 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x17, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, - 0x76, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x13, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, - 0x12, 0x53, 0x0a, 0x15, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, - 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x72, 0x61, 0x2e, 0x52, - 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, - 0x63, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0f, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, - 0x65, 0x72, 0x74, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x2e, 0x72, 0x61, 0x2e, 0x52, 0x65, - 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x6b, - 0x0a, 0x21, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, - 0x6c, 0x79, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x12, 0x2c, 0x2e, 0x72, 0x61, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, - 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, - 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x08, 0x4e, - 0x65, 0x77, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x13, 0x2e, 0x72, 0x61, 0x2e, 0x4e, 0x65, 0x77, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x63, - 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x0d, 0x46, - 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x72, - 0x61, 0x2e, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0c, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x4f, 0x43, 0x53, 0x50, 0x12, 0x17, 0x2e, 0x72, 0x61, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, - 0x61, 0x74, 0x65, 0x4f, 0x43, 0x53, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, - 0x2e, 0x63, 0x61, 0x2e, 0x4f, 0x43, 0x53, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x00, 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x6c, 0x65, 0x74, 0x73, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2f, 0x62, 0x6f, 0x75, - 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x72, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6b, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x6d, 0x65, + 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6d, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x6d, + 0x65, 0x64, 0x22, 0x4f, 0x0a, 0x0f, 0x4e, 0x65, 0x77, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0e, 0x72, + 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x44, 0x12, 0x14, 0x0a, + 0x05, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x61, + 0x6d, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x14, 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x05, 0x6f, + 0x72, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x05, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x10, + 0x0a, 0x03, 0x63, 0x73, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x73, 0x72, + 0x32, 0xad, 0x06, 0x0a, 0x15, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3b, 0x0a, 0x0f, 0x4e, 0x65, + 0x77, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x2e, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x1a, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x49, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x2e, + 0x72, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x63, + 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x22, 0x00, 0x12, 0x48, 0x0a, 0x11, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, + 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, 0x72, 0x61, 0x2e, 0x50, 0x65, 0x72, + 0x66, 0x6f, 0x72, 0x6d, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x16, + 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x52, 0x65, + 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x22, 0x00, 0x12, 0x48, 0x0a, 0x17, 0x44, 0x65, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, + 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x13, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x53, + 0x0a, 0x15, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x41, 0x70, + 0x70, 0x6c, 0x69, 0x63, 0x61, 0x6e, 0x74, 0x12, 0x20, 0x2e, 0x72, 0x61, 0x2e, 0x52, 0x65, 0x76, + 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x22, 0x00, 0x12, 0x47, 0x0a, 0x0f, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, + 0x74, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x2e, 0x72, 0x61, 0x2e, 0x52, 0x65, 0x76, 0x6f, + 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x42, 0x79, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x6b, 0x0a, 0x21, + 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, + 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x12, 0x2c, 0x2e, 0x72, 0x61, 0x2e, 0x41, 0x64, 0x6d, 0x69, 0x6e, 0x69, 0x73, 0x74, 0x72, + 0x61, 0x74, 0x69, 0x76, 0x65, 0x6c, 0x79, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x2e, 0x0a, 0x08, 0x4e, 0x65, 0x77, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x13, 0x2e, 0x72, 0x61, 0x2e, 0x4e, 0x65, 0x77, 0x4f, 0x72, + 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x63, 0x6f, 0x72, + 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x00, 0x12, 0x38, 0x0a, 0x0d, 0x46, 0x69, 0x6e, + 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x72, 0x61, 0x2e, + 0x46, 0x69, 0x6e, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0b, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, + 0x72, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x0c, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4f, + 0x43, 0x53, 0x50, 0x12, 0x17, 0x2e, 0x72, 0x61, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x4f, 0x43, 0x53, 0x50, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x63, + 0x61, 0x2e, 0x4f, 0x43, 0x53, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x42, 0x29, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, + 0x65, 0x74, 0x73, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x2f, 0x62, 0x6f, 0x75, 0x6c, 0x64, + 0x65, 0x72, 0x2f, 0x72, 0x61, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/ra/proto/ra.proto b/ra/proto/ra.proto index cd2db5e26ba..4f5f1093db4 100644 --- a/ra/proto/ra.proto +++ b/ra/proto/ra.proto @@ -54,16 +54,17 @@ message RevokeCertByKeyRequest { } message AdministrativelyRevokeCertificateRequest { - // The `cert` field may be omitted. If it is omitted, - // the revocation reason (`code`) must not be keyCompromise, - // and purging the Akamai cache will not happen because the - // base URL for the certificate's OCSP server is not known. + // Deprecated: this field is ignored. bytes cert = 1; // The `serial` field is required. string serial = 4; int64 code = 2; string adminName = 3; bool skipBlockKey = 5; + // If the malformed flag is set, the RA will not attempt to parse the + // certificate in question. In this case, the keyCompromise reason cannot be + // specified, because the key cannot be blocked. + bool malformed = 6; } message NewOrderRequest { diff --git a/ra/ra.go b/ra/ra.go index 369ac011a14..8e94d8c745f 100644 --- a/ra/ra.go +++ b/ra/ra.go @@ -2207,48 +2207,28 @@ func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx conte } reasonCode := revocation.Reason(req.Code) - if reasonCode == ocsp.KeyCompromise && req.Cert == nil && !req.SkipBlockKey { - return nil, fmt.Errorf("cannot revoke and block for KeyCompromise by serial alone") + if _, present := revocation.AdminAllowedReasons[reasonCode]; !present { + return nil, fmt.Errorf("cannot revoke for reason %d", reasonCode) } if req.SkipBlockKey && reasonCode != ocsp.KeyCompromise { return nil, fmt.Errorf("cannot skip key blocking for reasons other than KeyCompromise") } - - if _, present := revocation.AdminAllowedReasons[reasonCode]; !present { - return nil, fmt.Errorf("cannot revoke for reason %d", reasonCode) - } - - // If we weren't passed a cert in the request, find IssuerID from the db. - // We could instead look up and parse the certificate itself, but we avoid - // that in case we are administratively revoking the certificate because it is - // so badly malformed that it can't be parsed. - var cert *x509.Certificate - var issuerID issuance.NameID - var err error - if req.Cert == nil { - status, err := ra.SA.GetCertificateStatus(ctx, &sapb.Serial{Serial: req.Serial}) - if err != nil { - return nil, fmt.Errorf("unable to confirm that serial %q was ever issued: %w", req.Serial, err) - } - issuerID = issuance.NameID(status.IssuerID) - } else { - cert, err = x509.ParseCertificate(req.Cert) - if err != nil { - return nil, err - } - issuerID = issuance.IssuerNameID(cert) + if reasonCode == ocsp.KeyCompromise && req.Malformed { + return nil, fmt.Errorf("cannot revoke malformed certificate for KeyCompromise") } logEvent := certificateRevocationEvent{ ID: core.NewToken(), - Method: "key", - AdminName: req.AdminName, SerialNumber: req.Serial, + Reason: req.Code, + Method: "admin", + AdminName: req.AdminName, } // Below this point, do not re-declare `err` (i.e. type `err :=`) in a // nested scope. Doing so will create a new `err` variable that is not // captured by this closure. + var err error defer func() { if err != nil { logEvent.Error = err.Error() @@ -2256,6 +2236,44 @@ func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx conte ra.log.AuditObject("Revocation request:", logEvent) }() + var cert *x509.Certificate + var issuerID issuance.NameID + if req.Cert != nil { + // If the incoming request includes a certificate body, just use that and + // avoid doing any database queries. This code path is deprecated and will + // be removed when req.Cert is removed. + cert, err = x509.ParseCertificate(req.Cert) + if err != nil { + return nil, err + } + issuerID = issuance.IssuerNameID(cert) + } else if !req.Malformed { + // As long as we don't believe the cert will be malformed, we should + // get the precertificate so we can block its pubkey if necessary and purge + // the akamai OCSP cache. + var certPB *corepb.Certificate + certPB, err = ra.SA.GetLintPrecertificate(ctx, &sapb.Serial{Serial: req.Serial}) + if err != nil { + return nil, err + } + // Note that, although the thing we're parsing here is actually a linting + // precertificate, it has identical issuer info (and therefore an identical + // issuer NameID) to the real thing. + cert, err = x509.ParseCertificate(certPB.Der) + if err != nil { + return nil, err + } + issuerID = issuance.IssuerNameID(cert) + } else { + // But if the cert is malformed, we at least still need its IssuerID. + var status *corepb.CertificateStatus + status, err = ra.SA.GetCertificateStatus(ctx, &sapb.Serial{Serial: req.Serial}) + if err != nil { + return nil, fmt.Errorf("unable to confirm that serial %q was ever issued: %w", req.Serial, err) + } + issuerID = issuance.NameID(status.IssuerID) + } + var serialInt *big.Int serialInt, err = core.StringToSerial(req.Serial) if err != nil { diff --git a/ra/ra_test.go b/ra/ra_test.go index ef2d090642f..783159df7d1 100644 --- a/ra/ra_test.go +++ b/ra/ra_test.go @@ -3652,53 +3652,79 @@ rA== type mockSARevocation struct { mocks.StorageAuthority - known *corepb.CertificateStatus + known map[string]*x509.Certificate + revoked map[string]*corepb.CertificateStatus blocked []*sapb.AddBlockedKeyRequest - revoked map[string]int64 } func newMockSARevocation(known *x509.Certificate, clk clock.Clock) *mockSARevocation { return &mockSARevocation{ StorageAuthority: *mocks.NewStorageAuthority(clk), - known: &corepb.CertificateStatus{ - Serial: core.SerialToString(known.SerialNumber), - IssuerID: int64(issuance.IssuerNameID(known)), - }, - blocked: make([]*sapb.AddBlockedKeyRequest, 0), - revoked: make(map[string]int64), + known: map[string]*x509.Certificate{core.SerialToString(known.SerialNumber): known}, + revoked: make(map[string]*corepb.CertificateStatus), + blocked: make([]*sapb.AddBlockedKeyRequest, 0), } } +func (msar *mockSARevocation) reset() { + msar.revoked = make(map[string]*corepb.CertificateStatus) + msar.blocked = make([]*sapb.AddBlockedKeyRequest, 0) +} + func (msar *mockSARevocation) AddBlockedKey(_ context.Context, req *sapb.AddBlockedKeyRequest, _ ...grpc.CallOption) (*emptypb.Empty, error) { msar.blocked = append(msar.blocked, req) return &emptypb.Empty{}, nil } +func (msar *mockSARevocation) GetLintPrecertificate(_ context.Context, req *sapb.Serial, _ ...grpc.CallOption) (*corepb.Certificate, error) { + if cert, present := msar.known[req.Serial]; present { + return &corepb.Certificate{Der: cert.Raw}, nil + } + return nil, berrors.UnknownSerialError() +} + func (msar *mockSARevocation) GetCertificateStatus(_ context.Context, req *sapb.Serial, _ ...grpc.CallOption) (*corepb.CertificateStatus, error) { - if msar.known != nil && req.Serial == msar.known.Serial { - return msar.known, nil + if status, present := msar.revoked[req.Serial]; present { + return status, nil + } + if cert, present := msar.known[req.Serial]; present { + return &corepb.CertificateStatus{ + Serial: core.SerialToString(cert.SerialNumber), + IssuerID: int64(issuance.IssuerNameID(cert)), + }, nil } - return nil, fmt.Errorf("unknown certificate status") + return nil, berrors.UnknownSerialError() } func (msar *mockSARevocation) RevokeCertificate(_ context.Context, req *sapb.RevokeCertificateRequest, _ ...grpc.CallOption) (*emptypb.Empty, error) { if _, present := msar.revoked[req.Serial]; present { return nil, berrors.AlreadyRevokedError("already revoked") } - msar.revoked[req.Serial] = req.Reason - msar.known.Status = string(core.OCSPStatusRevoked) + cert, present := msar.known[req.Serial] + if !present { + return nil, berrors.UnknownSerialError() + } + msar.revoked[req.Serial] = &corepb.CertificateStatus{ + Serial: req.Serial, + IssuerID: int64(issuance.IssuerNameID(cert)), + Status: string(core.OCSPStatusRevoked), + RevokedReason: req.Reason, + } return &emptypb.Empty{}, nil } func (msar *mockSARevocation) UpdateRevokedCertificate(_ context.Context, req *sapb.RevokeCertificateRequest, _ ...grpc.CallOption) (*emptypb.Empty, error) { - reason, present := msar.revoked[req.Serial] + status, present := msar.revoked[req.Serial] if !present { return nil, errors.New("not already revoked") } - if present && reason == ocsp.KeyCompromise { + if req.Reason != ocsp.KeyCompromise { + return nil, errors.New("cannot re-revoke except for keyCompromise") + } + if present && status.RevokedReason == ocsp.KeyCompromise { return nil, berrors.AlreadyRevokedError("already revoked for keyCompromise") } - msar.revoked[req.Serial] = req.Reason + msar.revoked[req.Serial].RevokedReason = req.Reason return &emptypb.Empty{}, nil } @@ -3904,7 +3930,7 @@ func TestRevokeCertByApplicant_Controller(t *testing.T) { RegID: 5, }) test.AssertNotError(t, err, "should have succeeded") - test.AssertEquals(t, mockSA.revoked[core.SerialToString(cert.SerialNumber)], int64(ocsp.CessationOfOperation)) + test.AssertEquals(t, mockSA.revoked[core.SerialToString(cert.SerialNumber)].RevokedReason, int64(ocsp.CessationOfOperation)) } func TestRevokeCertByKey(t *testing.T) { @@ -3936,7 +3962,7 @@ func TestRevokeCertByKey(t *testing.T) { test.Assert(t, bytes.Equal(digest[:], mockSA.blocked[0].KeyHash), "key hash mismatch") test.AssertEquals(t, mockSA.blocked[0].Source, "API") test.AssertEquals(t, len(mockSA.blocked[0].Comment), 0) - test.AssertEquals(t, mockSA.revoked[core.SerialToString(cert.SerialNumber)], int64(ocsp.KeyCompromise)) + test.AssertEquals(t, mockSA.revoked[core.SerialToString(cert.SerialNumber)].RevokedReason, int64(ocsp.KeyCompromise)) // Re-revoking should fail, because it is already revoked for keyCompromise. _, err = ra.RevokeCertByKey(context.Background(), &rapb.RevokeCertByKeyRequest{ @@ -3946,7 +3972,7 @@ func TestRevokeCertByKey(t *testing.T) { // Reset and have the Subscriber revoke for a different reason. // Then re-revoking using the key should work. - mockSA.revoked = make(map[string]int64) + mockSA.revoked = make(map[string]*corepb.CertificateStatus) _, err = ra.RevokeCertByApplicant(context.Background(), &rapb.RevokeCertByApplicantRequest{ Cert: cert.Raw, Code: ocsp.Unspecified, @@ -3983,33 +4009,26 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) { _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{}) test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed for nil request object") - // Revoking with neither a cert nor a serial should fail immediately. + // Revoking with no serial should fail immediately. + mockSA.reset() _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ Code: ocsp.Unspecified, AdminName: "root", }) test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed with no cert or serial") - // Revoking with a nil cert and no serial should fail immediately. - _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ - Cert: []byte{}, - Code: ocsp.KeyCompromise, - AdminName: "", - }) - test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed for nil `Cert`") - // Revoking without an admin name should fail immediately. + mockSA.reset() _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ - Cert: cert.Raw, Serial: serial, - Code: ocsp.KeyCompromise, + Code: ocsp.Unspecified, AdminName: "", }) test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed with empty string for `AdminName`") // Revoking for a forbidden reason should fail immediately. + mockSA.reset() _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ - Cert: cert.Raw, Serial: serial, Code: ocsp.CertificateHold, AdminName: "root", @@ -4017,8 +4036,8 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) { test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed with forbidden revocation reason") // Revoking a cert for an unspecified reason should work but not block the key. + mockSA.reset() _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ - Cert: cert.Raw, Serial: serial, Code: ocsp.Unspecified, AdminName: "root", @@ -4029,9 +4048,9 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) { t, ra.revocationReasonCounter, prometheus.Labels{"reason": "unspecified"}, 1) // Revoking a serial for an unspecified reason should work but not block the key. - mockSA.revoked = make(map[string]int64) + mockSA.reset() _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ - Serial: core.SerialToString(cert.SerialNumber), + Serial: serial, Code: ocsp.Unspecified, AdminName: "root", }) @@ -4041,11 +4060,27 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) { t, ra.revocationReasonCounter, prometheus.Labels{"reason": "unspecified"}, 2) // Duplicate administrative revocation of a serial for an unspecified reason - // should fail and not block the key + // should succeed because the akamai cache purge succeeds. + // Note that we *don't* call reset() here, so it recognizes the duplicate. _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ - Serial: core.SerialToString(cert.SerialNumber), + Serial: serial, + Code: ocsp.Unspecified, + AdminName: "root", + }) + test.AssertNotError(t, err, "AdministrativelyRevokeCertificate failed") + test.AssertEquals(t, len(mockSA.blocked), 0) + test.AssertMetricWithLabelsEquals( + t, ra.revocationReasonCounter, prometheus.Labels{"reason": "unspecified"}, 2) + + // Duplicate administrative revocation of a serial for a *malformed* cert for + // an unspecified reason should fail because we can't attempt an akamai cache + // purge so the underlying AlreadyRevoked error gets propagated upwards. + // Note that we *don't* call reset() here, so it recognizes the duplicate. + _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ + Serial: serial, Code: ocsp.Unspecified, AdminName: "root", + Malformed: true, }) test.AssertError(t, err, "Should be revoked") test.AssertContains(t, err.Error(), "already revoked") @@ -4053,10 +4088,23 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) { test.AssertMetricWithLabelsEquals( t, ra.revocationReasonCounter, prometheus.Labels{"reason": "unspecified"}, 2) + // Revoking a cert for key compromise with skipBlockKey set should work but + // not block the key. + mockSA.reset() + _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ + Serial: serial, + Code: ocsp.KeyCompromise, + AdminName: "root", + SkipBlockKey: true, + }) + test.AssertNotError(t, err, "AdministrativelyRevokeCertificate failed") + test.AssertEquals(t, len(mockSA.blocked), 0) + test.AssertMetricWithLabelsEquals( + t, ra.revocationReasonCounter, prometheus.Labels{"reason": "keyCompromise"}, 1) + // Revoking a cert for key compromise should work and block the key. - mockSA.revoked = make(map[string]int64) + mockSA.reset() _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ - Cert: cert.Raw, Serial: serial, Code: ocsp.KeyCompromise, AdminName: "root", @@ -4068,14 +4116,16 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) { test.AssertEquals(t, mockSA.blocked[0].Comment, "revoked by root") test.AssertEquals(t, mockSA.blocked[0].Added.AsTime(), clk.Now()) test.AssertMetricWithLabelsEquals( - t, ra.revocationReasonCounter, prometheus.Labels{"reason": "keyCompromise"}, 1) + t, ra.revocationReasonCounter, prometheus.Labels{"reason": "keyCompromise"}, 2) - // Revoking a serial for key compromise should fail because we don't have the pubkey to block. - mockSA.revoked = make(map[string]int64) + // Revoking a malformed cert for key compromise should fail because we don't + // have the pubkey to block. + mockSA.reset() _, err = ra.AdministrativelyRevokeCertificate(context.Background(), &rapb.AdministrativelyRevokeCertificateRequest{ Serial: core.SerialToString(cert.SerialNumber), Code: ocsp.KeyCompromise, AdminName: "root", + Malformed: true, }) test.AssertError(t, err, "AdministrativelyRevokeCertificate should have failed with just serial for keyCompromise") } diff --git a/test/inmem/sa/sa.go b/test/inmem/sa/sa.go index cd248de4a2a..5ae7cc5a6bf 100644 --- a/test/inmem/sa/sa.go +++ b/test/inmem/sa/sa.go @@ -117,6 +117,10 @@ func (sa SA) RevokeCertificate(ctx context.Context, req *sapb.RevokeCertificateR return sa.Impl.RevokeCertificate(ctx, req) } +func (sa SA) GetLintPrecertificate(ctx context.Context, req *sapb.Serial, _ ...grpc.CallOption) (*corepb.Certificate, error) { + return sa.Impl.GetLintPrecertificate(ctx, req) +} + func (sa SA) GetCertificateStatus(ctx context.Context, req *sapb.Serial, _ ...grpc.CallOption) (*corepb.CertificateStatus, error) { return sa.Impl.GetCertificateStatus(ctx, req) }