ra: revoke with explicit CRL shard (#7944)
In RA.RevokedCertificate, if the certificate being revoked has a crlDistributionPoints extension, parse the URL and pass the appropriate shard to the SA. This required some changes to the `admin` tool. When a malformed certificate is revoked, we don't have a parsed copy of the certificate to extract a CRL URL from. So, specifically when a malformed certificate is being revoked, allow specifying a CRL shard. Because different certificates will have different shards, require one-at-a-time revocation for malformed certificates. To support that refactoring, move the serial-cleaning functionality earlier in the `admin` tool's flow. Also, split out one of the cases handled by the `revokeCertificate` helper in the RA. For admin malformed revocations, we need to accept a human-specified ShardIdx, so call the SA directly in that case (and skip stat increment since admin revocations aren't useful for metrics). This allows `revokeCertificate` to be a more helpful helper, by extracting serial, issuer ID, and CRL shard automatically from an `*x509.Certificate`. Note: we don't yet issue certificates with the crlDistributionPoints extension, so this code will not be active until we start doing so. Part of #7094.
This commit is contained in:
parent
c971a053a2
commit
a9080705b4
|
|
@ -44,6 +44,7 @@ type subcommandRevokeCert struct {
|
|||
privKey string
|
||||
regID uint
|
||||
certFile string
|
||||
crlShard int64
|
||||
}
|
||||
|
||||
var _ subcommand = (*subcommandRevokeCert)(nil)
|
||||
|
|
@ -58,6 +59,7 @@ func (s *subcommandRevokeCert) Flags(flag *flag.FlagSet) {
|
|||
flag.StringVar(&s.reasonStr, "reason", "unspecified", "Revocation reason (unspecified, keyCompromise, superseded, cessationOfOperation, or privilegeWithdrawn)")
|
||||
flag.BoolVar(&s.skipBlock, "skip-block-key", false, "Skip blocking the key, if revoked for keyCompromise - use with extreme caution")
|
||||
flag.BoolVar(&s.malformed, "malformed", false, "Indicates that the cert cannot be parsed - use with caution")
|
||||
flag.Int64Var(&s.crlShard, "crl-shard", 0, "For malformed certs, the CRL shard the certificate belongs to")
|
||||
|
||||
// Flags specifying the input method for the certificates to be revoked.
|
||||
flag.StringVar(&s.serial, "serial", "", "Revoke the certificate with this hex serial")
|
||||
|
|
@ -134,12 +136,22 @@ func (s *subcommandRevokeCert) Run(ctx context.Context, a *admin) error {
|
|||
return fmt.Errorf("collecting serials to revoke: %w", err)
|
||||
}
|
||||
|
||||
serials, err = cleanSerials(serials)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(serials) == 0 {
|
||||
return errors.New("no serials to revoke found")
|
||||
}
|
||||
|
||||
a.log.Infof("Found %d certificates to revoke", len(serials))
|
||||
|
||||
err = a.revokeSerials(ctx, serials, reasonCode, s.malformed, s.skipBlock, s.parallelism)
|
||||
if s.malformed {
|
||||
return s.revokeMalformed(ctx, a, serials, reasonCode)
|
||||
}
|
||||
|
||||
err = a.revokeSerials(ctx, serials, reasonCode, s.skipBlock, s.parallelism)
|
||||
if err != nil {
|
||||
return fmt.Errorf("revoking serials: %w", err)
|
||||
}
|
||||
|
|
@ -147,6 +159,31 @@ func (s *subcommandRevokeCert) Run(ctx context.Context, a *admin) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *subcommandRevokeCert) revokeMalformed(ctx context.Context, a *admin, serials []string, reasonCode revocation.Reason) error {
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting admin username: %w", err)
|
||||
}
|
||||
if s.crlShard == 0 {
|
||||
return errors.New("when revoking malformed certificates, a nonzero CRL shard must be specified")
|
||||
}
|
||||
if len(serials) > 1 {
|
||||
return errors.New("when revoking malformed certificates, only one cert at a time is allowed")
|
||||
}
|
||||
_, err = a.rac.AdministrativelyRevokeCertificate(
|
||||
ctx,
|
||||
&rapb.AdministrativelyRevokeCertificateRequest{
|
||||
Serial: serials[0],
|
||||
Code: int64(reasonCode),
|
||||
AdminName: u.Username,
|
||||
SkipBlockKey: s.skipBlock,
|
||||
Malformed: true,
|
||||
CrlShard: s.crlShard,
|
||||
},
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *admin) serialsFromIncidentTable(ctx context.Context, tableName string) ([]string, error) {
|
||||
stream, err := a.saroc.SerialsForIncident(ctx, &sapb.SerialsForIncidentRequest{IncidentTable: tableName})
|
||||
if err != nil {
|
||||
|
|
@ -248,7 +285,9 @@ func (a *admin) serialsFromCertPEM(_ context.Context, filename string) ([]string
|
|||
return []string{core.SerialToString(cert.SerialNumber)}, nil
|
||||
}
|
||||
|
||||
func cleanSerial(serial string) (string, error) {
|
||||
// cleanSerials removes non-alphanumeric characters from the serials and checks
|
||||
// that all resulting serials are valid (hex encoded, and the correct length).
|
||||
func cleanSerials(serials []string) ([]string, error) {
|
||||
serialStrip := func(r rune) rune {
|
||||
switch {
|
||||
case unicode.IsLetter(r):
|
||||
|
|
@ -258,14 +297,19 @@ func cleanSerial(serial string) (string, error) {
|
|||
}
|
||||
return rune(-1)
|
||||
}
|
||||
strippedSerial := strings.Map(serialStrip, serial)
|
||||
if !core.ValidSerial(strippedSerial) {
|
||||
return "", fmt.Errorf("cleaned serial %q is not valid", strippedSerial)
|
||||
|
||||
var ret []string
|
||||
for _, s := range serials {
|
||||
cleaned := strings.Map(serialStrip, s)
|
||||
if !core.ValidSerial(cleaned) {
|
||||
return nil, fmt.Errorf("cleaned serial %q is not valid", cleaned)
|
||||
}
|
||||
ret = append(ret, cleaned)
|
||||
}
|
||||
return strippedSerial, nil
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (a *admin) revokeSerials(ctx context.Context, serials []string, reason revocation.Reason, malformed bool, skipBlockKey bool, parallelism uint) error {
|
||||
func (a *admin) revokeSerials(ctx context.Context, serials []string, reason revocation.Reason, skipBlockKey bool, parallelism uint) error {
|
||||
u, err := user.Current()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting admin username: %w", err)
|
||||
|
|
@ -279,19 +323,17 @@ func (a *admin) revokeSerials(ctx context.Context, serials []string, reason revo
|
|||
go func() {
|
||||
defer wg.Done()
|
||||
for serial := range work {
|
||||
cleanedSerial, err := cleanSerial(serial)
|
||||
if err != nil {
|
||||
a.log.Errf("skipping serial %q: %s", serial, err)
|
||||
continue
|
||||
}
|
||||
_, err = a.rac.AdministrativelyRevokeCertificate(
|
||||
ctx,
|
||||
&rapb.AdministrativelyRevokeCertificateRequest{
|
||||
Serial: cleanedSerial,
|
||||
Serial: serial,
|
||||
Code: int64(reason),
|
||||
AdminName: u.Username,
|
||||
SkipBlockKey: skipBlockKey,
|
||||
Malformed: malformed,
|
||||
// This is a well-formed certificate so send CrlShard 0
|
||||
// to let the RA figure out the right shard from the cert.
|
||||
Malformed: false,
|
||||
CrlShard: 0,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"errors"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
|
|
@ -198,20 +199,20 @@ func (mra *mockRARecordingRevocations) reset() {
|
|||
func TestRevokeSerials(t *testing.T) {
|
||||
t.Parallel()
|
||||
serials := []string{
|
||||
"2a:18:59:2b:7f:4b:f5:96:fb:1a:1d:f1:35:56:7a:cd:82:5a",
|
||||
"03:8c:3f:63:88:af:b7:69:5d:d4:d6:bb:e3:d2:64:f1:e4:e2",
|
||||
"048c3f6388afb7695dd4d6bbe3d264f1e5e5!",
|
||||
"2a18592b7f4bf596fb1a1df135567acd825a",
|
||||
"038c3f6388afb7695dd4d6bbe3d264f1e4e2",
|
||||
"048c3f6388afb7695dd4d6bbe3d264f1e5e5",
|
||||
}
|
||||
mra := mockRARecordingRevocations{}
|
||||
log := blog.NewMock()
|
||||
a := admin{rac: &mra, log: log}
|
||||
|
||||
assertRequestsContain := func(reqs []*rapb.AdministrativelyRevokeCertificateRequest, code revocation.Reason, skipBlockKey bool, malformed bool) {
|
||||
assertRequestsContain := func(reqs []*rapb.AdministrativelyRevokeCertificateRequest, code revocation.Reason, skipBlockKey bool) {
|
||||
t.Helper()
|
||||
for _, req := range reqs {
|
||||
test.AssertEquals(t, len(req.Cert), 0)
|
||||
test.AssertEquals(t, req.Code, int64(code))
|
||||
test.AssertEquals(t, req.SkipBlockKey, skipBlockKey)
|
||||
test.AssertEquals(t, req.Malformed, malformed)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -219,49 +220,113 @@ func TestRevokeSerials(t *testing.T) {
|
|||
mra.reset()
|
||||
log.Clear()
|
||||
a.dryRun = false
|
||||
err := a.revokeSerials(context.Background(), serials, 0, false, false, 1)
|
||||
err := a.revokeSerials(context.Background(), serials, 0, false, 1)
|
||||
test.AssertEquals(t, len(log.GetAllMatching("invalid serial format")), 0)
|
||||
test.AssertNotError(t, err, "")
|
||||
test.AssertEquals(t, len(log.GetAll()), 0)
|
||||
test.AssertEquals(t, len(mra.revocationRequests), 3)
|
||||
assertRequestsContain(mra.revocationRequests, 0, false, false)
|
||||
assertRequestsContain(mra.revocationRequests, 0, false)
|
||||
|
||||
// Revoking an already-revoked serial should result in one log line.
|
||||
mra.reset()
|
||||
log.Clear()
|
||||
mra.alreadyRevoked = []string{"048c3f6388afb7695dd4d6bbe3d264f1e5e5"}
|
||||
err = a.revokeSerials(context.Background(), serials, 0, false, false, 1)
|
||||
err = a.revokeSerials(context.Background(), serials, 0, false, 1)
|
||||
t.Logf("error: %s", err)
|
||||
t.Logf("logs: %s", strings.Join(log.GetAll(), ""))
|
||||
test.AssertError(t, err, "already-revoked should result in error")
|
||||
test.AssertEquals(t, len(log.GetAllMatching("not revoking")), 1)
|
||||
test.AssertEquals(t, len(mra.revocationRequests), 3)
|
||||
assertRequestsContain(mra.revocationRequests, 0, false, false)
|
||||
assertRequestsContain(mra.revocationRequests, 0, false)
|
||||
|
||||
// Revoking a doomed-to-fail serial should also result in one log line.
|
||||
mra.reset()
|
||||
log.Clear()
|
||||
mra.doomedToFail = []string{"048c3f6388afb7695dd4d6bbe3d264f1e5e5"}
|
||||
err = a.revokeSerials(context.Background(), serials, 0, false, false, 1)
|
||||
err = a.revokeSerials(context.Background(), serials, 0, false, 1)
|
||||
test.AssertError(t, err, "gRPC error should result in error")
|
||||
test.AssertEquals(t, len(log.GetAllMatching("failed to revoke")), 1)
|
||||
test.AssertEquals(t, len(mra.revocationRequests), 3)
|
||||
assertRequestsContain(mra.revocationRequests, 0, false, false)
|
||||
assertRequestsContain(mra.revocationRequests, 0, false)
|
||||
|
||||
// Revoking with other parameters should get carried through.
|
||||
mra.reset()
|
||||
log.Clear()
|
||||
err = a.revokeSerials(context.Background(), serials, 1, true, true, 3)
|
||||
err = a.revokeSerials(context.Background(), serials, 1, true, 3)
|
||||
test.AssertNotError(t, err, "")
|
||||
test.AssertEquals(t, len(mra.revocationRequests), 3)
|
||||
assertRequestsContain(mra.revocationRequests, 1, true, true)
|
||||
assertRequestsContain(mra.revocationRequests, 1, true)
|
||||
|
||||
// Revoking in dry-run mode should result in no gRPC requests and three logs.
|
||||
mra.reset()
|
||||
log.Clear()
|
||||
a.dryRun = true
|
||||
a.rac = dryRunRAC{log: log}
|
||||
err = a.revokeSerials(context.Background(), serials, 0, false, false, 1)
|
||||
err = a.revokeSerials(context.Background(), serials, 0, false, 1)
|
||||
test.AssertNotError(t, err, "")
|
||||
test.AssertEquals(t, len(log.GetAllMatching("dry-run:")), 3)
|
||||
test.AssertEquals(t, len(mra.revocationRequests), 0)
|
||||
assertRequestsContain(mra.revocationRequests, 0, false, false)
|
||||
assertRequestsContain(mra.revocationRequests, 0, false)
|
||||
}
|
||||
|
||||
func TestRevokeMalformed(t *testing.T) {
|
||||
t.Parallel()
|
||||
mra := mockRARecordingRevocations{}
|
||||
log := blog.NewMock()
|
||||
a := &admin{
|
||||
rac: &mra,
|
||||
log: log,
|
||||
dryRun: false,
|
||||
}
|
||||
|
||||
s := subcommandRevokeCert{
|
||||
crlShard: 623,
|
||||
}
|
||||
serial := "0379c3dfdd518be45948f2dbfa6ea3e9b209"
|
||||
err := s.revokeMalformed(context.Background(), a, []string{serial}, 1)
|
||||
if err != nil {
|
||||
t.Errorf("revokedMalformed with crlShard 623: want success, got %s", err)
|
||||
}
|
||||
if len(mra.revocationRequests) != 1 {
|
||||
t.Errorf("revokeMalformed: want 1 revocation request to SA, got %v", mra.revocationRequests)
|
||||
}
|
||||
if mra.revocationRequests[0].Serial != serial {
|
||||
t.Errorf("revokeMalformed: want %s to be revoked, got %s", serial, mra.revocationRequests[0])
|
||||
}
|
||||
|
||||
s = subcommandRevokeCert{
|
||||
crlShard: 0,
|
||||
}
|
||||
err = s.revokeMalformed(context.Background(), a, []string{"038c3f6388afb7695dd4d6bbe3d264f1e4e2"}, 1)
|
||||
if err == nil {
|
||||
t.Errorf("revokedMalformed with crlShard 0: want error, got none")
|
||||
}
|
||||
|
||||
s = subcommandRevokeCert{
|
||||
crlShard: 623,
|
||||
}
|
||||
err = s.revokeMalformed(context.Background(), a, []string{"038c3f6388afb7695dd4d6bbe3d264f1e4e2", "28a94f966eae14e525777188512ddf5a0a3b"}, 1)
|
||||
if err == nil {
|
||||
t.Errorf("revokedMalformed with multiple serials: want error, got none")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanSerials(t *testing.T) {
|
||||
input := []string{
|
||||
"2a:18:59:2b:7f:4b:f5:96:fb:1a:1d:f1:35:56:7a:cd:82:5a",
|
||||
"03:8c:3f:63:88:af:b7:69:5d:d4:d6:bb:e3:d2:64:f1:e4:e2",
|
||||
"038c3f6388afb7695dd4d6bbe3d264f1e4e2",
|
||||
}
|
||||
expected := []string{
|
||||
"2a18592b7f4bf596fb1a1df135567acd825a",
|
||||
"038c3f6388afb7695dd4d6bbe3d264f1e4e2",
|
||||
"038c3f6388afb7695dd4d6bbe3d264f1e4e2",
|
||||
}
|
||||
output, err := cleanSerials(input)
|
||||
if err != nil {
|
||||
t.Errorf("cleanSerials(%s): %s, want %s", input, err, expected)
|
||||
}
|
||||
if !reflect.DeepEqual(output, expected) {
|
||||
t.Errorf("cleanSerials(%s)=%s, want %s", input, output, expected)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -424,6 +424,14 @@ type AdministrativelyRevokeCertificateRequest struct {
|
|||
// 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"`
|
||||
// The CRL shard to store the revocation in.
|
||||
//
|
||||
// This is used when revoking malformed certificates, to allow human judgement
|
||||
// in setting the CRL shard instead of automatically determining it by parsing
|
||||
// the certificate.
|
||||
//
|
||||
// Passing a nonzero crlShard with malformed=false returns error.
|
||||
CrlShard int64 `protobuf:"varint,7,opt,name=crlShard,proto3" json:"crlShard,omitempty"`
|
||||
}
|
||||
|
||||
func (x *AdministrativelyRevokeCertificateRequest) Reset() {
|
||||
|
|
@ -500,6 +508,13 @@ func (x *AdministrativelyRevokeCertificateRequest) GetMalformed() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (x *AdministrativelyRevokeCertificateRequest) GetCrlShard() int64 {
|
||||
if x != nil {
|
||||
return x.CrlShard
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type NewOrderRequest struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
|
@ -819,7 +834,7 @@ var file_ra_proto_rawDesc = []byte{
|
|||
0x49, 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, 0xca, 0x01, 0x0a, 0x28, 0x41, 0x64, 0x6d, 0x69, 0x6e,
|
||||
0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x22, 0xe6, 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,
|
||||
|
|
@ -832,103 +847,105 @@ var file_ra_proto_rawDesc = []byte{
|
|||
0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x6b, 0x69, 0x70, 0x42, 0x6c, 0x6f,
|
||||
0x63, 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, 0xc1, 0x01, 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,
|
||||
0x1a, 0x0a, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||
0x09, 0x52, 0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72,
|
||||
0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x18, 0x03, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x53, 0x65, 0x72,
|
||||
0x69, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65,
|
||||
0x50, 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10,
|
||||
0x05, 0x4a, 0x04, 0x08, 0x06, 0x10, 0x07, 0x22, 0x29, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x41, 0x75,
|
||||
0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02,
|
||||
0x69, 0x64, 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, 0x22,
|
||||
0x3f, 0x0a, 0x15, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 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,
|
||||
0x22, 0x2e, 0x0a, 0x16, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x32, 0x9f, 0x08, 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, 0x57, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e,
|
||||
0x74, 0x61, 0x63, 0x74, 0x12, 0x24, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74,
|
||||
0x61, 0x63, 0x74, 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, 0x4f, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74,
|
||||
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x2e, 0x72, 0x61, 0x2e, 0x55,
|
||||
0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x4b, 0x65, 0x79, 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, 0x46, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41,
|
||||
0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x72,
|
||||
0x61, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 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, 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, 0x12, 0x49, 0x0a, 0x0e, 0x55, 0x6e, 0x70, 0x61, 0x75,
|
||||
0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x72, 0x61, 0x2e, 0x55,
|
||||
0x6d, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x72, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x18,
|
||||
0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x63, 0x72, 0x6c, 0x53, 0x68, 0x61, 0x72, 0x64, 0x22,
|
||||
0xc1, 0x01, 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, 0x1a, 0x0a, 0x08, 0x64,
|
||||
0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x64,
|
||||
0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x72, 0x65, 0x70, 0x6c, 0x61,
|
||||
0x63, 0x65, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0e, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x73, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x12,
|
||||
0x36, 0x0a, 0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72,
|
||||
0x6f, 0x66, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x16, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x66,
|
||||
0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x4a, 0x04, 0x08,
|
||||
0x06, 0x10, 0x07, 0x22, 0x29, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
|
||||
0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e,
|
||||
0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 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, 0x22, 0x3f, 0x0a, 0x15, 0x55,
|
||||
0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73,
|
||||
0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 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,
|
||||
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, 0x22, 0x2e, 0x0a, 0x16,
|
||||
0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x32, 0x9f, 0x08, 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, 0x57, 0x0a, 0x19, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67,
|
||||
0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74,
|
||||
0x12, 0x24, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69,
|
||||
0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 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, 0x4f, 0x0a, 0x15,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x20, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79,
|
||||
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, 0x46, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f,
|
||||
0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x72, 0x61, 0x2e, 0x47, 0x65,
|
||||
0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 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, 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, 0x12, 0x49, 0x0a, 0x0e, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x75,
|
||||
0x73, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x1a, 0x2e, 0x72, 0x61, 0x2e, 0x55, 0x6e, 0x70, 0x61, 0x75, 0x73, 0x65, 0x41, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 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 (
|
||||
|
|
|
|||
|
|
@ -73,6 +73,14 @@ message AdministrativelyRevokeCertificateRequest {
|
|||
// certificate in question. In this case, the keyCompromise reason cannot be
|
||||
// specified, because the key cannot be blocked.
|
||||
bool malformed = 6;
|
||||
// The CRL shard to store the revocation in.
|
||||
//
|
||||
// This is used when revoking malformed certificates, to allow human judgement
|
||||
// in setting the CRL shard instead of automatically determining it by parsing
|
||||
// the certificate.
|
||||
//
|
||||
// Passing a nonzero crlShard with malformed=false returns error.
|
||||
int64 crlShard = 7;
|
||||
}
|
||||
|
||||
message NewOrderRequest {
|
||||
|
|
|
|||
104
ra/ra.go
104
ra/ra.go
|
|
@ -8,7 +8,6 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net"
|
||||
"net/url"
|
||||
"slices"
|
||||
|
|
@ -328,6 +327,7 @@ type certificateRevocationEvent struct {
|
|||
// RequesterID is the account ID of the requester.
|
||||
// Will be zero for admin revocations.
|
||||
RequesterID int64 `json:",omitempty"`
|
||||
CRLShard int64
|
||||
// AdminName is the name of the admin requester.
|
||||
// Will be zero for subscriber revocations.
|
||||
AdminName string `json:",omitempty"`
|
||||
|
|
@ -1545,14 +1545,20 @@ func (ra *RegistrationAuthorityImpl) PerformValidation(
|
|||
|
||||
// revokeCertificate updates the database to mark the certificate as revoked,
|
||||
// with the given reason and current timestamp.
|
||||
func (ra *RegistrationAuthorityImpl) revokeCertificate(ctx context.Context, serial *big.Int, issuerID issuance.NameID, reason revocation.Reason) error {
|
||||
serialString := core.SerialToString(serial)
|
||||
func (ra *RegistrationAuthorityImpl) revokeCertificate(ctx context.Context, cert *x509.Certificate, reason revocation.Reason) error {
|
||||
serialString := core.SerialToString(cert.SerialNumber)
|
||||
issuerID := issuance.IssuerNameID(cert)
|
||||
shardIdx, err := crlShard(cert)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := ra.SA.RevokeCertificate(ctx, &sapb.RevokeCertificateRequest{
|
||||
_, err = ra.SA.RevokeCertificate(ctx, &sapb.RevokeCertificateRequest{
|
||||
Serial: serialString,
|
||||
Reason: int64(reason),
|
||||
Date: timestamppb.New(ra.clk.Now()),
|
||||
IssuerID: int64(issuerID),
|
||||
ShardIdx: shardIdx,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -1566,9 +1572,7 @@ func (ra *RegistrationAuthorityImpl) revokeCertificate(ctx context.Context, seri
|
|||
// as revoked, with the given reason and current timestamp. This only works for
|
||||
// certificates that were previously revoked for a reason other than
|
||||
// keyCompromise, and which are now being updated to keyCompromise instead.
|
||||
func (ra *RegistrationAuthorityImpl) updateRevocationForKeyCompromise(ctx context.Context, serial *big.Int, issuerID issuance.NameID) error {
|
||||
serialString := core.SerialToString(serial)
|
||||
|
||||
func (ra *RegistrationAuthorityImpl) updateRevocationForKeyCompromise(ctx context.Context, serialString string, issuerID issuance.NameID) error {
|
||||
status, err := ra.SA.GetCertificateStatus(ctx, &sapb.Serial{Serial: serialString})
|
||||
if err != nil {
|
||||
return berrors.NotFoundError("unable to confirm that serial %q was ever issued: %s", serialString, err)
|
||||
|
|
@ -1709,11 +1713,9 @@ func (ra *RegistrationAuthorityImpl) RevokeCertByApplicant(ctx context.Context,
|
|||
logEvent.Reason = req.Code
|
||||
}
|
||||
|
||||
issuerID := issuance.IssuerNameID(cert)
|
||||
err = ra.revokeCertificate(
|
||||
ctx,
|
||||
cert.SerialNumber,
|
||||
issuerID,
|
||||
cert,
|
||||
revocation.Reason(req.Code),
|
||||
)
|
||||
if err != nil {
|
||||
|
|
@ -1721,11 +1723,50 @@ func (ra *RegistrationAuthorityImpl) RevokeCertByApplicant(ctx context.Context,
|
|||
}
|
||||
|
||||
// Don't propagate purger errors to the client.
|
||||
issuerID := issuance.IssuerNameID(cert)
|
||||
_ = ra.purgeOCSPCache(ctx, cert, issuerID)
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// crlShard extracts the CRL shard from a certificate's CRLDistributionPoint.
|
||||
//
|
||||
// If there is no CRLDistributionPoint, returns 0.
|
||||
//
|
||||
// If there is more than one CRLDistributionPoint, returns an error.
|
||||
//
|
||||
// Assumes the shard number is represented in the URL as an integer that
|
||||
// occurs in the last path component, optionally followed by ".crl".
|
||||
//
|
||||
// Note: This assumes (a) the CA is generating well-formed, correct
|
||||
// CRLDistributionPoints and (b) an earlier component has verified the signature
|
||||
// on this certificate comes from one of our issuers.
|
||||
func crlShard(cert *x509.Certificate) (int64, error) {
|
||||
if len(cert.CRLDistributionPoints) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
if len(cert.CRLDistributionPoints) > 1 {
|
||||
return 0, errors.New("too many crlDistributionPoints in certificate")
|
||||
}
|
||||
|
||||
url := strings.TrimSuffix(cert.CRLDistributionPoints[0], ".crl")
|
||||
lastIndex := strings.LastIndex(url, "/")
|
||||
if lastIndex == -1 {
|
||||
return 0, fmt.Errorf("malformed CRLDistributionPoint %q", url)
|
||||
}
|
||||
shardStr := url[lastIndex+1:]
|
||||
shardIdx, err := strconv.Atoi(shardStr)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("parsing CRLDistributionPoint: %s", err)
|
||||
}
|
||||
|
||||
if shardIdx <= 0 {
|
||||
return 0, fmt.Errorf("invalid shard in CRLDistributionPoint: %d", shardIdx)
|
||||
}
|
||||
|
||||
return int64(shardIdx), nil
|
||||
}
|
||||
|
||||
// addToBlockedKeys initiates a GRPC call to have the Base64-encoded SHA256
|
||||
// digest of a provided public key added to the blockedKeys table.
|
||||
func (ra *RegistrationAuthorityImpl) addToBlockedKeys(ctx context.Context, key crypto.PublicKey, src string, comment string) error {
|
||||
|
|
@ -1765,8 +1806,6 @@ func (ra *RegistrationAuthorityImpl) RevokeCertByKey(ctx context.Context, req *r
|
|||
return nil, err
|
||||
}
|
||||
|
||||
issuerID := issuance.IssuerNameID(cert)
|
||||
|
||||
logEvent := certificateRevocationEvent{
|
||||
ID: core.NewToken(),
|
||||
SerialNumber: core.SerialToString(cert.SerialNumber),
|
||||
|
|
@ -1791,8 +1830,7 @@ func (ra *RegistrationAuthorityImpl) RevokeCertByKey(ctx context.Context, req *r
|
|||
// since that addition needs to happen no matter what.
|
||||
revokeErr := ra.revokeCertificate(
|
||||
ctx,
|
||||
cert.SerialNumber,
|
||||
issuerID,
|
||||
cert,
|
||||
revocation.Reason(ocsp.KeyCompromise),
|
||||
)
|
||||
|
||||
|
|
@ -1804,6 +1842,8 @@ func (ra *RegistrationAuthorityImpl) RevokeCertByKey(ctx context.Context, req *r
|
|||
return nil, err
|
||||
}
|
||||
|
||||
issuerID := issuance.IssuerNameID(cert)
|
||||
|
||||
// Check the error returned from revokeCertificate itself.
|
||||
err = revokeErr
|
||||
if err == nil {
|
||||
|
|
@ -1815,7 +1855,7 @@ func (ra *RegistrationAuthorityImpl) RevokeCertByKey(ctx context.Context, req *r
|
|||
} else if errors.Is(err, berrors.AlreadyRevoked) {
|
||||
// If it was an AlreadyRevoked error, try to re-revoke the cert in case
|
||||
// it was revoked for a reason other than keyCompromise.
|
||||
err = ra.updateRevocationForKeyCompromise(ctx, cert.SerialNumber, issuerID)
|
||||
err = ra.updateRevocationForKeyCompromise(ctx, core.SerialToString(cert.SerialNumber), issuerID)
|
||||
|
||||
// Perform an Akamai cache purge to handle occurrences of a client
|
||||
// previously successfully revoking a certificate, but the cache purge had
|
||||
|
|
@ -1847,6 +1887,9 @@ func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx conte
|
|||
if req.Serial == "" {
|
||||
return nil, errIncompleteGRPCRequest
|
||||
}
|
||||
if req.CrlShard != 0 && !req.Malformed {
|
||||
return nil, errors.New("non-zero CRLShard is only allowed for malformed certificates (shard is automatic for well formed certificates)")
|
||||
}
|
||||
|
||||
reasonCode := revocation.Reason(req.Code)
|
||||
if _, present := revocation.AdminAllowedReasons[reasonCode]; !present {
|
||||
|
|
@ -1863,6 +1906,7 @@ func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx conte
|
|||
ID: core.NewToken(),
|
||||
SerialNumber: req.Serial,
|
||||
Reason: req.Code,
|
||||
CRLShard: req.CrlShard,
|
||||
Method: "admin",
|
||||
AdminName: req.AdminName,
|
||||
}
|
||||
|
|
@ -1880,6 +1924,7 @@ func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx conte
|
|||
|
||||
var cert *x509.Certificate
|
||||
var issuerID issuance.NameID
|
||||
var shard int64
|
||||
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
|
||||
|
|
@ -1889,6 +1934,10 @@ func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx conte
|
|||
return nil, err
|
||||
}
|
||||
issuerID = issuance.IssuerNameID(cert)
|
||||
shard, err = crlShard(cert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} 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
|
||||
|
|
@ -1906,6 +1955,10 @@ func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx conte
|
|||
return nil, err
|
||||
}
|
||||
issuerID = issuance.IssuerNameID(cert)
|
||||
shard, err = crlShard(cert)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// But if the cert is malformed, we at least still need its IssuerID.
|
||||
var status *corepb.CertificateStatus
|
||||
|
|
@ -1914,29 +1967,30 @@ func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx conte
|
|||
return nil, fmt.Errorf("unable to confirm that serial %q was ever issued: %w", req.Serial, err)
|
||||
}
|
||||
issuerID = issuance.NameID(status.IssuerID)
|
||||
shard = req.CrlShard
|
||||
}
|
||||
|
||||
var serialInt *big.Int
|
||||
serialInt, err = core.StringToSerial(req.Serial)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = ra.revokeCertificate(ctx, serialInt, issuerID, revocation.Reason(req.Code))
|
||||
_, err = ra.SA.RevokeCertificate(ctx, &sapb.RevokeCertificateRequest{
|
||||
Serial: req.Serial,
|
||||
Reason: req.Code,
|
||||
Date: timestamppb.New(ra.clk.Now()),
|
||||
IssuerID: int64(issuerID),
|
||||
ShardIdx: shard,
|
||||
})
|
||||
// Perform an Akamai cache purge to handle occurrences of a client
|
||||
// successfully revoking a certificate, but the initial cache purge failing.
|
||||
if errors.Is(err, berrors.AlreadyRevoked) {
|
||||
if cert != nil {
|
||||
err = ra.purgeOCSPCache(ctx, cert, issuerID)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("OCSP cache purge for already revoked serial %v failed: %w", serialInt, err)
|
||||
err = fmt.Errorf("OCSP cache purge for already revoked serial %v failed: %w", req.Serial, err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
if req.Code == ocsp.KeyCompromise && errors.Is(err, berrors.AlreadyRevoked) {
|
||||
err = ra.updateRevocationForKeyCompromise(ctx, serialInt, issuerID)
|
||||
err = ra.updateRevocationForKeyCompromise(ctx, req.Serial, issuerID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -1957,7 +2011,7 @@ func (ra *RegistrationAuthorityImpl) AdministrativelyRevokeCertificate(ctx conte
|
|||
if cert != nil {
|
||||
err = ra.purgeOCSPCache(ctx, cert, issuerID)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("OCSP cache purge for serial %v failed: %w", serialInt, err)
|
||||
err = fmt.Errorf("OCSP cache purge for serial %v failed: %w", req.Serial, err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3707,8 +3707,6 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) {
|
|||
})
|
||||
test.AssertNotError(t, err, "AdministrativelyRevokeCertificate failed")
|
||||
test.AssertEquals(t, len(mockSA.blocked), 0)
|
||||
test.AssertMetricWithLabelsEquals(
|
||||
t, ra.revocationReasonCounter, prometheus.Labels{"reason": "unspecified"}, 1)
|
||||
|
||||
// Revoking a serial for an unspecified reason should work but not block the key.
|
||||
mockSA.reset()
|
||||
|
|
@ -3719,8 +3717,6 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) {
|
|||
})
|
||||
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 an unspecified reason
|
||||
// should succeed because the akamai cache purge succeeds.
|
||||
|
|
@ -3732,8 +3728,6 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) {
|
|||
})
|
||||
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
|
||||
|
|
@ -3748,8 +3742,6 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) {
|
|||
test.AssertError(t, err, "Should be revoked")
|
||||
test.AssertContains(t, err.Error(), "already revoked")
|
||||
test.AssertEquals(t, len(mockSA.blocked), 0)
|
||||
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.
|
||||
|
|
@ -3762,8 +3754,6 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) {
|
|||
})
|
||||
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.reset()
|
||||
|
|
@ -3778,8 +3768,6 @@ func TestAdministrativelyRevokeCertificate(t *testing.T) {
|
|||
test.AssertEquals(t, mockSA.blocked[0].Source, "admin-revoker")
|
||||
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"}, 2)
|
||||
|
||||
// Revoking a malformed cert for key compromise should fail because we don't
|
||||
// have the pubkey to block.
|
||||
|
|
@ -4058,3 +4046,60 @@ func TestUpdateRegistrationKey(t *testing.T) {
|
|||
test.AssertContains(t, err.Error(), "failed to update registration key")
|
||||
test.AssertContains(t, err.Error(), "mocked to always error")
|
||||
}
|
||||
|
||||
func TestCRLShard(t *testing.T) {
|
||||
var cdp []string
|
||||
n, err := crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
|
||||
if err != nil || n != 0 {
|
||||
t.Errorf("crlShard(%+v) = %d, %s, want 0, nil", cdp, n, err)
|
||||
}
|
||||
|
||||
cdp = []string{
|
||||
"https://example.com/123.crl",
|
||||
"https://example.net/123.crl",
|
||||
}
|
||||
n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
|
||||
if err == nil {
|
||||
t.Errorf("crlShard(%+v) = %d, %s, want 0, some error", cdp, n, err)
|
||||
}
|
||||
|
||||
cdp = []string{
|
||||
"https://example.com/abc",
|
||||
}
|
||||
n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
|
||||
if err == nil {
|
||||
t.Errorf("crlShard(%+v) = %d, %s, want 0, some error", cdp, n, err)
|
||||
}
|
||||
|
||||
cdp = []string{
|
||||
"example",
|
||||
}
|
||||
n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
|
||||
if err == nil {
|
||||
t.Errorf("crlShard(%+v) = %d, %s, want 0, some error", cdp, n, err)
|
||||
}
|
||||
|
||||
cdp = []string{
|
||||
"https://example.com/abc/-77.crl",
|
||||
}
|
||||
n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
|
||||
if err == nil {
|
||||
t.Errorf("crlShard(%+v) = %d, %s, want 0, some error", cdp, n, err)
|
||||
}
|
||||
|
||||
cdp = []string{
|
||||
"https://example.com/abc/123",
|
||||
}
|
||||
n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
|
||||
if err != nil || n != 123 {
|
||||
t.Errorf("crlShard(%+v) = %d, %s, want 123, nil", cdp, n, err)
|
||||
}
|
||||
|
||||
cdp = []string{
|
||||
"https://example.com/abc/123.crl",
|
||||
}
|
||||
n, err = crlShard(&x509.Certificate{CRLDistributionPoints: cdp})
|
||||
if err != nil || n != 123 {
|
||||
t.Errorf("crlShard(%+v) = %d, %s, want 123, nil", cdp, n, err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
3
sa/sa.go
3
sa/sa.go
|
|
@ -902,6 +902,9 @@ func addRevokedCertificate(ctx context.Context, tx db.Executor, req *sapb.Revoke
|
|||
|
||||
// RevokeCertificate stores revocation information about a certificate. It will only store this
|
||||
// information if the certificate is not already marked as revoked.
|
||||
//
|
||||
// If ShardIdx is non-zero, RevokeCertificate also writes an entry for this certificate to
|
||||
// the revokedCertificates table, with the provided shard number.
|
||||
func (ssa *SQLStorageAuthority) RevokeCertificate(ctx context.Context, req *sapb.RevokeCertificateRequest) (*emptypb.Empty, error) {
|
||||
if core.IsAnyNilOrZero(req.Serial, req.IssuerID, req.Date) {
|
||||
return nil, errIncompleteRequest
|
||||
|
|
|
|||
Loading…
Reference in New Issue