Revert "Remove StoreIssuerInfo flag in CA (#4850)" (#4868)

This reverts commit 6454513ded.

We actually need to wait 90 days to ensure the issuerID field of the
certificateStatus table is non-nil for all extant certificates.
This commit is contained in:
Jacob Hoffman-Andrews 2020-06-12 12:50:24 -07:00 committed by GitHub
parent 325bba3a6f
commit 0b0917cea6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 202 additions and 561 deletions

121
ca/ca.go
View File

@ -7,6 +7,7 @@ import (
"crypto/ecdsa"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/x509"
"encoding/asn1"
"encoding/hex"
@ -36,8 +37,8 @@ import (
corepb "github.com/letsencrypt/boulder/core/proto"
csrlib "github.com/letsencrypt/boulder/csr"
berrors "github.com/letsencrypt/boulder/errors"
"github.com/letsencrypt/boulder/features"
"github.com/letsencrypt/boulder/goodkey"
"github.com/letsencrypt/boulder/issuercerts"
blog "github.com/letsencrypt/boulder/log"
sapb "github.com/letsencrypt/boulder/sa/proto"
)
@ -115,9 +116,11 @@ const (
type CertificateAuthorityImpl struct {
rsaProfile string
ecdsaProfile string
// A map from issuer cert common name to an internalIssuer struct
issuers map[string]*internalIssuer
// A map from issuer ID to internalIssuer
idToIssuer map[issuercerts.ID]*internalIssuer
// The issuer that will be used for issuance (as opposed to OCSP signing)
idToIssuer map[int64]*internalIssuer
// The common name of the default issuer cert
defaultIssuer *internalIssuer
sa certificateStorage
pa core.PolicyAuthority
@ -163,12 +166,11 @@ func makeInternalIssuers(
issuers []Issuer,
policy *cfsslConfig.Signing,
lifespanOCSP time.Duration,
) (map[issuercerts.ID]*internalIssuer, error) {
) (map[string]*internalIssuer, error) {
if len(issuers) == 0 {
return nil, errors.New("No issuers specified.")
}
internalIssuers := make(map[issuercerts.ID]*internalIssuer)
cns := make(map[string]bool)
internalIssuers := make(map[string]*internalIssuer)
for _, iss := range issuers {
if iss.Cert == nil || iss.Signer == nil {
return nil, errors.New("Issuer with nil cert or signer specified.")
@ -179,11 +181,10 @@ func makeInternalIssuers(
}
cn := iss.Cert.Subject.CommonName
if cns[cn] {
if internalIssuers[cn] != nil {
return nil, errors.New("Multiple issuer certs with the same CommonName are not supported")
}
id := issuercerts.FromCert(iss.Cert).ID()
internalIssuers[id] = &internalIssuer{
internalIssuers[cn] = &internalIssuer{
cert: iss.Cert,
eeSigner: eeSigner,
ocspSigner: iss.Signer,
@ -192,8 +193,16 @@ func makeInternalIssuers(
return internalIssuers, nil
}
// idForIssuer generates a stable ID for an issuer certificate. This
// is used for identifying which issuer issued a certificate in the
// certificateStatus table.
func idForIssuer(cert *x509.Certificate) int64 {
h := sha256.Sum256(cert.Raw)
return big.NewInt(0).SetBytes(h[:4]).Int64()
}
// NewCertificateAuthorityImpl creates a CA instance that can sign certificates
// from a single issuer (the first in the issuers slice), and can sign OCSP
// from a single issuer (the first first in the issuers slice), and can sign OCSP
// for any of the issuer certificates provided.
func NewCertificateAuthorityImpl(
config ca_config.CAConfig,
@ -242,7 +251,7 @@ func NewCertificateAuthorityImpl(
if err != nil {
return nil, err
}
defaultIssuer := internalIssuers[issuercerts.FromCert(issuers[0].Cert).ID()]
defaultIssuer := internalIssuers[issuers[0].Cert.Subject.CommonName]
rsaProfile := config.RSAProfile
ecdsaProfile := config.ECDSAProfile
@ -292,6 +301,7 @@ func NewCertificateAuthorityImpl(
ca = &CertificateAuthorityImpl{
sa: sa,
pa: pa,
issuers: internalIssuers,
defaultIssuer: defaultIssuer,
rsaProfile: rsaProfile,
ecdsaProfile: ecdsaProfile,
@ -309,9 +319,9 @@ func NewCertificateAuthorityImpl(
signErrorCounter: signErrorCounter,
}
ca.idToIssuer = make(map[issuercerts.ID]*internalIssuer)
for _, ii := range internalIssuers {
id := issuercerts.FromCert(ii.cert).ID()
ca.idToIssuer = make(map[int64]*internalIssuer)
for _, ii := range ca.issuers {
id := idForIssuer(ii.cert)
ca.idToIssuer[id] = ii
}
@ -423,33 +433,48 @@ var ocspStatusToCode = map[string]int{
func (ca *CertificateAuthorityImpl) GenerateOCSP(ctx context.Context, req *caPB.GenerateOCSPRequest) (*caPB.OCSPResponse, error) {
var issuer *internalIssuer
var serial *big.Int
if req.IssuerID == nil {
return nil, fmt.Errorf("no issuerID provided")
}
if req.Serial == nil {
return nil, fmt.Errorf("no serial provided")
}
// Once the feature is enabled we need to support both RPCs that include
// IssuerID and those that don't as we still need to be able to update rows
// that didn't have an IssuerID set when they were created. Once this feature
// has been enabled for a full OCSP lifetime cycle we can remove this
// functionality.
serialInt, err := core.StringToSerial(*req.Serial)
if err != nil {
return nil, err
}
serial = serialInt
var ok bool
issuer, ok = ca.idToIssuer[issuercerts.ID(*req.IssuerID)]
if !ok {
return nil, fmt.Errorf("This CA doesn't have an issuer cert with ID %d", *req.IssuerID)
}
exists, err := ca.sa.SerialExists(ctx, &sapb.Serial{Serial: req.Serial})
if err != nil {
return nil, err
}
if !*exists.Exists {
return nil, fmt.Errorf("GenerateOCSP was asked to sign OCSP for certification with unknown serial %q", *req.Serial)
if features.Enabled(features.StoreIssuerInfo) && req.IssuerID != nil {
serialInt, err := core.StringToSerial(*req.Serial)
if err != nil {
return nil, err
}
serial = serialInt
var ok bool
issuer, ok = ca.idToIssuer[*req.IssuerID]
if !ok {
return nil, fmt.Errorf("This CA doesn't have an issuer cert with ID %d", *req.IssuerID)
}
exists, err := ca.sa.SerialExists(ctx, &sapb.Serial{Serial: req.Serial})
if err != nil {
return nil, err
}
if !*exists.Exists {
return nil, fmt.Errorf("GenerateOCSP was asked to sign OCSP for certification with unknown serial %q", *req.Serial)
}
} else {
cert, err := x509.ParseCertificate(req.CertDER)
if err != nil {
ca.log.AuditErr(err.Error())
return nil, err
}
serial = cert.SerialNumber
cn := cert.Issuer.CommonName
issuer = ca.issuers[cn]
if issuer == nil {
return nil, fmt.Errorf("This CA doesn't have an issuer cert with CommonName %q", cn)
}
err = cert.CheckSignatureFrom(issuer.cert)
if err != nil {
return nil, fmt.Errorf("GenerateOCSP was asked to sign OCSP for cert "+
"%s from %q, but the cert's signature was not valid: %s.",
core.SerialToString(cert.SerialNumber), cn, err)
}
}
now := ca.clk.Now().Truncate(time.Hour)
@ -498,16 +523,10 @@ func (ca *CertificateAuthorityImpl) IssuePrecertificate(ctx context.Context, iss
return nil, err
}
// we currently only use one issuer, in the future when we support multiple
// the issuer will need to be derived from issueReq
issuerID := int64(issuercerts.FromCert(ca.defaultIssuer.cert).ID())
status := string(core.OCSPStatusGood)
ocspResp, err := ca.GenerateOCSP(ctx, &caPB.GenerateOCSPRequest{
Serial: &serialHex,
CertDER: precertDER,
Status: &status,
IssuerID: &issuerID,
CertDER: precertDER,
Status: &status,
})
if err != nil {
err = berrors.InternalServerError(err.Error())
@ -516,13 +535,17 @@ func (ca *CertificateAuthorityImpl) IssuePrecertificate(ctx context.Context, iss
}
req := &sapb.AddCertificateRequest{
Der: precertDER,
RegID: &regID,
Ocsp: ocspResp.Response,
Issued: &nowNanos,
IssuerID: &issuerID,
Der: precertDER,
RegID: &regID,
Ocsp: ocspResp.Response,
Issued: &nowNanos,
}
// we currently only use one issuer, in the future when we support multiple
// the issuer will need to be derived from issueReq
issuerID := idForIssuer(ca.defaultIssuer.cert)
req.IssuerID = &issuerID
_, err = ca.sa.AddPrecertificate(ctx, req)
if err != nil {
ca.orphanCount.With(prometheus.Labels{"type": "precert"}).Inc()

View File

@ -39,7 +39,6 @@ import (
berrors "github.com/letsencrypt/boulder/errors"
"github.com/letsencrypt/boulder/features"
"github.com/letsencrypt/boulder/goodkey"
"github.com/letsencrypt/boulder/issuercerts"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/metrics"
"github.com/letsencrypt/boulder/policy"
@ -493,16 +492,10 @@ func TestOCSP(t *testing.T) {
test.AssertNotError(t, err, "Failed to issue")
parsedCert, err := x509.ParseCertificate(cert.DER)
test.AssertNotError(t, err, "Failed to parse cert")
caCertIssuerID := int64(issuercerts.FromCert(caCert).ID())
serial := core.SerialToString(parsedCert.SerialNumber)
status := string(core.OCSPStatusGood)
ocspResp, err := ca.GenerateOCSP(ctx, &caPB.GenerateOCSPRequest{
IssuerID: &caCertIssuerID,
Serial: &serial,
CertDER: cert.DER,
Status: &status,
CertDER: cert.DER,
Status: &status,
})
test.AssertNotError(t, err, "Failed to generate OCSP")
parsed, err := ocsp.ParseResponse(ocspResp.Response, caCert)
@ -511,6 +504,13 @@ func TestOCSP(t *testing.T) {
test.AssertEquals(t, parsed.RevocationReason, 0)
test.AssertEquals(t, parsed.SerialNumber.Cmp(parsedCert.SerialNumber), 0)
// Test that signatures are checked.
_, err = ca.GenerateOCSP(ctx, &caPB.GenerateOCSPRequest{
CertDER: append(cert.DER, byte(0)),
Status: &status,
})
test.AssertError(t, err, "Generated OCSP for cert with bad signature")
// Load multiple issuers, including the old issuer, and ensure OCSP is still
// signed correctly.
newIssuerCert, err := core.LoadCert("../test/test-ca2.pem")
@ -543,16 +543,14 @@ func TestOCSP(t *testing.T) {
parsedNewCert, err := x509.ParseCertificate(newCert.DER)
test.AssertNotError(t, err, "Failed to parse newCert")
newIssuerID := int64(issuercerts.FromCert(newIssuers[0].Cert).ID())
newSerial := core.SerialToString(parsedNewCert.SerialNumber)
err = parsedNewCert.CheckSignatureFrom(newIssuerCert)
t.Logf("check sig: %s", err)
// ocspResp2 is a second OCSP response for `cert` (issued by caCert), and
// should be signed by caCert.
ocspResp2, err := ca.GenerateOCSP(ctx, &caPB.GenerateOCSPRequest{
IssuerID: &newIssuerID,
Serial: &newSerial,
CertDER: append([]byte(nil), cert.DER...),
Status: &status,
CertDER: append([]byte(nil), cert.DER...),
Status: &status,
})
test.AssertNotError(t, err, "Failed to sign second OCSP response")
_, err = ocsp.ParseResponse(ocspResp2.Response, caCert)
@ -561,10 +559,8 @@ func TestOCSP(t *testing.T) {
// newCertOcspResp is an OCSP response for `newCert` (issued by newIssuer),
// and should be signed by newIssuer.
newCertOcspResp, err := ca.GenerateOCSP(ctx, &caPB.GenerateOCSPRequest{
IssuerID: &newIssuerID,
Serial: &newSerial,
CertDER: newCert.DER,
Status: &status,
CertDER: newCert.DER,
Status: &status,
})
test.AssertNotError(t, err, "Failed to generate OCSP")
parsedNewCertOcspResp, err := ocsp.ParseResponse(newCertOcspResp.Response, newIssuerCert)
@ -1257,6 +1253,7 @@ func TestIssuePrecertificateLinting(t *testing.T) {
func TestGenerateOCSPWithIssuerID(t *testing.T) {
testCtx := setup(t)
sa := &mockSA{}
_ = features.Set(map[string]bool{"StoreIssuerInfo": true})
ca, err := NewCertificateAuthorityImpl(
testCtx.caConfig,
sa,
@ -1269,7 +1266,7 @@ func TestGenerateOCSPWithIssuerID(t *testing.T) {
nil)
test.AssertNotError(t, err, "Failed to create CA")
// req contains bad IssuerID
// GenerateOCSP with feature enabled + req contains bad IssuerID
issuerID := int64(666)
serial := "DEADDEADDEADDEADDEADDEADDEADDEADDEAD"
status := string(core.OCSPStatusGood)
@ -1280,8 +1277,8 @@ func TestGenerateOCSPWithIssuerID(t *testing.T) {
})
test.AssertError(t, err, "GenerateOCSP didn't fail with invalid IssuerID")
// req contains good IssuerID
issuerID = int64(issuercerts.FromCert(ca.defaultIssuer.cert).ID())
// GenerateOCSP with feature enabled + req contains good IssuerID
issuerID = idForIssuer(ca.defaultIssuer.cert)
_, err = ca.GenerateOCSP(context.Background(), &caPB.GenerateOCSPRequest{
IssuerID: &issuerID,
Serial: &serial,
@ -1289,7 +1286,7 @@ func TestGenerateOCSPWithIssuerID(t *testing.T) {
})
test.AssertNotError(t, err, "GenerateOCSP failed")
// req doesn't contain IssuerID or Serial
// GenerateOCSP with feature enabled + req doesn't contain IssuerID
issueReq := caPB.IssueCertificateRequest{Csr: CNandSANCSR, RegistrationID: &arbitraryRegID}
cert, err := ca.IssuePrecertificate(ctx, &issueReq)
test.AssertNotError(t, err, "Failed to issue")
@ -1297,5 +1294,5 @@ func TestGenerateOCSPWithIssuerID(t *testing.T) {
CertDER: cert.DER,
Status: &status,
})
test.AssertError(t, err, "Expected error from GenerateOCSP")
test.AssertNotError(t, err, "GenerateOCSP failed")
}

View File

@ -20,11 +20,9 @@ import (
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/core"
corepb "github.com/letsencrypt/boulder/core/proto"
"github.com/letsencrypt/boulder/db"
berrors "github.com/letsencrypt/boulder/errors"
"github.com/letsencrypt/boulder/features"
bgrpc "github.com/letsencrypt/boulder/grpc"
"github.com/letsencrypt/boulder/issuercerts"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/metrics"
sapb "github.com/letsencrypt/boulder/sa/proto"
@ -53,15 +51,10 @@ type config struct {
// to the original issued date. It should match the value used in
// `test/config/ca.json` for the CA "backdate" value.
Backdate cmd.ConfigDuration
// A list of issuer certificates. Orphaned certificates from the logs will be
// matched against these when determining which issuer ID to enter into the
// certificateStatus table.
IssuerFiles []string
Features map[string]bool
Features map[string]bool
}
type certificateStorage interface {
AddSerial(context.Context, *sapb.AddSerialRequest) (*corepb.Empty, error)
AddCertificate(context.Context, []byte, int64, []byte, *time.Time) (string, error)
AddPrecertificate(ctx context.Context, req *sapb.AddCertificateRequest) (*corepb.Empty, error)
GetCertificate(ctx context.Context, serial string) (core.Certificate, error)
@ -82,28 +75,17 @@ const (
certOrphan
// precertOrphan indicates an orphaned precertificate type
precertOrphan
// certOrphanAlreadyExists indicates an orphaned final certificate that
// already exists in the DB.
certOrphanAlreadyExists
// precertOrphanAlreadyExists indicates an orphaned precertificate that
// already exists in the DB.
precertOrphanAlreadyExists
)
// String returns a human representation of the orphanType.
// This is used both for printing orphanTypes and (in the case of certOrphan and
// precertOrphan) to figure out what to search for when parsing logs.
// Invalid orphanTypes are stringified as "unknown."
// String returns a human representation of the orphanType and the expected
// label in the orphaning message for that type, or "unknown" if it isn't
// a known orphan type.
func (t orphanType) String() string {
switch t {
case certOrphan:
return "certificate"
case precertOrphan:
return "precertificate"
case certOrphanAlreadyExists:
return "certificate (already exists in DB)"
case precertOrphanAlreadyExists:
return "precertificate (already exists in DB)"
default:
return "unknown"
}
@ -115,6 +97,8 @@ var (
errAlreadyExists = fmt.Errorf("Certificate already exists in DB")
)
var backdateDuration time.Duration
// orphanTypeForCert returns precertOrphan if the certificate has the RFC 6962
// CT poison extension, or certOrphan if it does not. If the certificate is nil
// unknownOrphan is returned.
@ -149,16 +133,13 @@ func checkDER(sai certificateStorage, der []byte) (*x509.Certificate, orphanType
switch orphanTyp {
case certOrphan:
_, err = sai.GetCertificate(ctx, orphanSerial)
if err == nil {
return nil, certOrphanAlreadyExists, errAlreadyExists
}
case precertOrphan:
_, err = sai.GetPrecertificate(ctx, &sapb.Serial{Serial: &orphanSerial})
if err == nil {
return nil, precertOrphanAlreadyExists, errAlreadyExists
}
default:
return nil, unknownOrphan, errors.New("unknown orphan type")
err = errors.New("unknown orphan type")
}
if err == nil {
return nil, orphanTyp, errAlreadyExists
}
if berrors.Is(err, berrors.NotFound) {
return orphan, orphanTyp, nil
@ -172,7 +153,7 @@ func checkDER(sai certificateStorage, der []byte) (*x509.Certificate, orphanType
// is true if the orphan was successfully added to the DB. As part of adding an
// orphan to the DB, it requests a fresh OCSP response from the CA to store
// alongside the precertificate/certificate.
func (of *orphanFinder) storeParsedLogLine(line string) (found bool, added bool, typ orphanType) {
func storeParsedLogLine(sa certificateStorage, ca ocspGenerator, logger blog.Logger, line string) (found bool, added bool, typ orphanType) {
ctx := context.Background()
// The log line should contain a label indicating it is a cert or a precert
@ -189,77 +170,78 @@ func (of *orphanFinder) storeParsedLogLine(line string) (found bool, added bool,
// Extract and decode the orphan DER
derStr := derOrphan.FindStringSubmatch(line)
if len(derStr) <= 1 {
of.logger.AuditErrf("Didn't match regex for cert: %s", line)
logger.AuditErrf("Didn't match regex for cert: %s", line)
return true, false, unknownOrphan
}
der, err := hex.DecodeString(derStr[1])
if err != nil {
of.logger.AuditErrf("Couldn't decode hex: %s, [%s]", err, line)
logger.AuditErrf("Couldn't decode hex: %s, [%s]", err, line)
return true, false, unknownOrphan
}
// Parse the DER, determine the orphan type, and ensure it doesn't already
// exist in the DB
cert, typ, err := checkDER(sa, der)
if err != nil {
logFunc := logger.Errf
if err == errAlreadyExists {
logFunc = logger.Infof
}
logFunc("%s, [%s]", err, line)
return true, false, typ
}
// extract the regID
regStr := regOrphan.FindStringSubmatch(line)
if len(regStr) <= 1 {
of.logger.AuditErrf("regID variable is empty, [%s]", line)
logger.AuditErrf("regID variable is empty, [%s]", line)
return true, false, typ
}
regID, err := strconv.ParseInt(regStr[1], 10, 64)
if err != nil {
of.logger.AuditErrf("Couldn't parse regID: %s, [%s]", err, line)
logger.AuditErrf("Couldn't parse regID: %s, [%s]", err, line)
return true, false, typ
}
typ, err = of.storeDER(ctx, regID, der)
response, err := generateOCSP(ctx, ca, der)
if err != nil {
of.logger.AuditErrf("Failed to store certificate: %s, [%s]", err, line)
logger.AuditErrf("Couldn't generate OCSP: %s, [%s]", err, line)
return true, false, typ
}
if typ == certOrphanAlreadyExists || typ == precertOrphanAlreadyExists {
return true, false, typ
} else {
return true, true, typ
// We use `cert.NotBefore` as the issued date to avoid the SA tagging this
// certificate with an issued date of the current time when we know it was an
// orphan issued in the past. Because certificates are backdated we need to
// add the backdate duration to find the true issued time.
issuedDate := cert.NotBefore.Add(backdateDuration)
switch typ {
case certOrphan:
_, err = sa.AddCertificate(ctx, der, regID, response, &issuedDate)
case precertOrphan:
issued := issuedDate.UnixNano()
_, err = sa.AddPrecertificate(ctx, &sapb.AddCertificateRequest{
Der: der,
RegID: &regID,
Ocsp: response,
Issued: &issued,
})
default:
// Shouldn't happen but be defensive anyway
err = errors.New("unknown orphan type")
}
if err != nil {
logger.AuditErrf("Failed to store certificate: %s, [%s]", err, line)
return true, false, typ
}
return true, true, typ
}
func (of *orphanFinder) findIssuerID(der []byte) (issuercerts.ID, error) {
cert, err := x509.ParseCertificate(der)
if err != nil {
return 0, err
}
for _, issuer := range of.issuers {
if err := cert.CheckSignatureFrom(issuer.Cert); err == nil {
return issuer.ID(), nil
}
}
return 0, fmt.Errorf("no issuer found")
}
func (of *orphanFinder) generateOCSP(ctx context.Context, certDER []byte) ([]byte, error) {
func generateOCSP(ctx context.Context, ca ocspGenerator, certDER []byte) ([]byte, error) {
// generate a fresh OCSP response
statusGood := string(core.OCSPStatusGood)
zeroInt32 := int32(0)
zeroInt64 := int64(0)
cert, err := x509.ParseCertificate(certDER)
if err != nil {
return nil, err
}
issuerID, err := of.findIssuerID(certDER)
if err != nil {
return nil, err
}
issuerIDInt := int64(issuerID)
serial := core.SerialToString(cert.SerialNumber)
ocspResponse, err := of.ocspCA.GenerateOCSP(ctx, &capb.GenerateOCSPRequest{
ocspResponse, err := ca.GenerateOCSP(ctx, &capb.GenerateOCSPRequest{
CertDER: certDER,
Status: &statusGood,
Reason: &zeroInt32,
RevokedAt: &zeroInt64,
IssuerID: &issuerIDInt,
Serial: &serial,
})
if err != nil {
return nil, err
@ -267,70 +249,30 @@ func (of *orphanFinder) generateOCSP(ctx context.Context, certDER []byte) ([]byt
return ocspResponse.Response, nil
}
type orphanFinder struct {
logger blog.Logger
sa certificateStorage
ocspCA capb.OCSPGeneratorClient
issuers []*issuercerts.Issuer
backdateDuration time.Duration
}
func setup(configFile string) (*orphanFinder, error) {
func setup(configFile string) (blog.Logger, core.StorageAuthority, capb.OCSPGeneratorClient) {
configJSON, err := ioutil.ReadFile(configFile)
if err != nil {
return nil, fmt.Errorf("reading config: %s", err)
}
cmd.FailOnError(err, "Failed to read config file")
var conf config
err = json.Unmarshal(configJSON, &conf)
if err != nil {
return nil, fmt.Errorf("parsing config: %s", err)
}
cmd.FailOnError(err, "Failed to parse config file")
err = features.Set(conf.Features)
if err != nil {
return nil, fmt.Errorf("setting feature flags: %s", err)
}
cmd.FailOnError(err, "Failed to set feature flags")
logger := cmd.NewLogger(conf.Syslog)
tlsConfig, err := conf.TLS.Load()
if err != nil {
return nil, fmt.Errorf("loading TLS config: %s", err)
}
cmd.FailOnError(err, "TLS config")
clientMetrics := bgrpc.NewClientMetrics(metrics.NoopRegisterer)
saConn, err := bgrpc.ClientSetup(conf.SAService, tlsConfig, clientMetrics, cmd.Clock())
if err != nil {
return nil, fmt.Errorf("setting up SA connection: %s", err)
}
cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA")
sac := bgrpc.NewStorageAuthorityClient(sapb.NewStorageAuthorityClient(saConn))
caConn, err := bgrpc.ClientSetup(conf.OCSPGeneratorService, tlsConfig, clientMetrics, cmd.Clock())
if err != nil {
return nil, fmt.Errorf("setting up OCSP CA connection: %s", err)
}
caConn, err := bgrpc.ClientSetup(conf.OCSPGeneratorService, tlsConfig, clientMetrics, cmd.Clock())
cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to CA")
cac := capb.NewOCSPGeneratorClient(caConn)
issuers, err := loadIssuers(conf.IssuerFiles)
if err != nil {
return nil, err
}
return &orphanFinder{logger, sac, cac, issuers, conf.Backdate.Duration}, nil
}
func loadIssuers(filenames []string) ([]*issuercerts.Issuer, error) {
var issuers []*issuercerts.Issuer
for _, filename := range filenames {
issuer, err := issuercerts.FromFile(filename)
if err != nil {
return nil, fmt.Errorf("loading %s: %s", filename, err)
}
issuers = append(issuers, issuer)
}
return issuers, nil
backdateDuration = conf.Backdate.Duration
return logger, sac, cac
}
func main() {
@ -360,13 +302,11 @@ func main() {
switch command {
case "parse-ca-log":
logger, sa, ca := setup(*configFile)
if *logPath == "" {
usage()
}
orphanFinder, err := setup(*configFile)
cmd.FailOnError(err, "setup")
logData, err := ioutil.ReadFile(*logPath)
cmd.FailOnError(err, "Failed to read log file")
@ -375,7 +315,7 @@ func main() {
if line == "" {
continue
}
found, added, typ := orphanFinder.storeParsedLogLine(line)
found, added, typ := storeParsedLogLine(sa, ca, logger, line)
var foundStat, addStat *int64
switch typ {
case certOrphan:
@ -385,7 +325,7 @@ func main() {
foundStat = &precertOrphansFound
addStat = &precertOrphansAdded
default:
orphanFinder.logger.Errf("Found orphan type %s", typ)
logger.Errf("Found orphan type %s", typ)
continue
}
if found {
@ -395,85 +335,42 @@ func main() {
}
}
}
orphanFinder.logger.Infof("Found %d certificate orphans and added %d to the database", certOrphansFound, certOrphansAdded)
orphanFinder.logger.Infof("Found %d precertificate orphans and added %d to the database", precertOrphansFound, precertOrphansAdded)
logger.Infof("Found %d certificate orphans and added %d to the database", certOrphansFound, certOrphansAdded)
logger.Infof("Found %d precertificate orphans and added %d to the database", precertOrphansFound, precertOrphansAdded)
case "parse-der":
ctx := context.Background()
_, sa, ca := setup(*configFile)
if *derPath == "" || *regID == 0 {
usage()
}
orphanFinder, err := setup(*configFile)
cmd.FailOnError(err, "setup")
der, err := ioutil.ReadFile(*derPath)
cmd.FailOnError(err, "Failed to read DER file")
_, err = orphanFinder.storeDER(context.Background(), *regID, der)
cmd.FailOnError(err, "storing DER")
cert, typ, err := checkDER(sa, der)
cmd.FailOnError(err, "Pre-AddCertificate checks failed")
// Because certificates are backdated we need to add the backdate duration
// to find the true issued time.
issuedDate := cert.NotBefore.Add(1 * backdateDuration)
response, err := generateOCSP(ctx, ca, der)
cmd.FailOnError(err, "Generating OCSP")
switch typ {
case certOrphan:
_, err = sa.AddCertificate(ctx, der, *regID, response, &issuedDate)
case precertOrphan:
issued := issuedDate.UnixNano()
_, err = sa.AddPrecertificate(ctx, &sapb.AddCertificateRequest{
Der: der,
RegID: regID,
Ocsp: response,
Issued: &issued,
})
default:
err = errors.New("unknown orphan type")
}
cmd.FailOnError(err, "Failed to add certificate to database")
default:
usage()
}
}
func (of *orphanFinder) storeDER(ctx context.Context, regID int64, der []byte) (orphanType, error) {
cert, typ, err := checkDER(of.sa, der)
if err != nil {
if err == errAlreadyExists {
of.logger.Infof("%s", err)
return typ, nil
} else {
return unknownOrphan, err
}
}
// Because certificates are backdated we need to add the backdate duration
// to find the true issued time.
issuedDate := cert.NotBefore.Add(of.backdateDuration)
issuedDateNanos := issuedDate.UnixNano()
notAfter := cert.NotAfter.UnixNano()
serial := core.SerialToString(cert.SerialNumber)
// The CA's GenerateOCSP method will return error if the serial is not in the
// serials table, so add it in case it doesn't exist (for instance this
// happens during integration testing). However, if the serial already exists
// ignore the error.
_, err = of.sa.AddSerial(ctx, &sapb.AddSerialRequest{
RegID: &regID,
Serial: &serial,
Created: &issuedDateNanos,
Expires: &notAfter,
})
if err != nil && !db.IsDuplicate(err) {
return unknownOrphan, err
}
response, err := of.generateOCSP(ctx, der)
if err != nil {
return unknownOrphan, fmt.Errorf("generating OCSP: %s", err)
}
switch typ {
case certOrphan:
_, err = of.sa.AddCertificate(ctx, der, regID, response, &issuedDate)
if err != nil {
return unknownOrphan, fmt.Errorf("adding certificate: %s", err)
}
case precertOrphan:
issuerID, err := of.findIssuerID(der)
cmd.FailOnError(err, "finding issuerID")
issuerIDInt := int64(issuerID)
_, err = of.sa.AddPrecertificate(ctx, &sapb.AddCertificateRequest{
Der: der,
RegID: &regID,
Ocsp: response,
Issued: &issuedDateNanos,
IssuerID: &issuerIDInt,
})
if err != nil {
return unknownOrphan, fmt.Errorf("adding precertificate: %s", err)
}
default:
return unknownOrphan, errors.New("unknown orphan type")
}
return typ, nil
}

View File

@ -29,10 +29,6 @@ type mockSA struct {
clk clock.FakeClock
}
func (m *mockSA) AddSerial(ctx context.Context, req *sapb.AddSerialRequest) (*corepb.Empty, error) {
return nil, nil
}
func (m *mockSA) AddCertificate(ctx context.Context, der []byte, regID int64, _ []byte, issued *time.Time) (string, error) {
parsed, err := x509.ParseCertificate(der)
if err != nil {
@ -113,29 +109,18 @@ func checkNoErrors(t *testing.T) {
}
}
func mustLoadCert(filename string) *x509.Certificate {
cert, err := core.LoadCert(filename)
if err != nil {
panic(err)
}
return cert
}
func TestParseLine(t *testing.T) {
fc := clock.NewFake()
fc.Set(time.Date(2015, 3, 4, 5, 0, 0, 0, time.UTC))
sa := &mockSA{}
ca := &mockCA{}
issuers, err := loadIssuers([]string{"testdata/minica1.pem", "testdata/minica2.pem"})
test.AssertNotError(t, err, "loading issuers")
backdateDuration := time.Hour
of := orphanFinder{log, sa, ca, issuers, backdateDuration}
// Set an example backdate duration (this is normally read from config)
backdateDuration = time.Hour
testCert := mustLoadCert("testdata/example.com/cert.pem")
testCertDERHex := hex.EncodeToString(testCert.Raw)
testPreCert := mustLoadCert("testdata/example.com/precert.pem")
testPreCertDERHex := hex.EncodeToString(testPreCert.Raw)
testCertDER := "3082045b30820343a003020102021300ffa0160630d618b2eb5c0510824b14274856300d06092a864886f70d01010b0500301f311d301b06035504030c146861707079206861636b65722066616b65204341301e170d3135313030333035323130305a170d3136303130313035323130305a3018311630140603550403130d6578616d706c652e636f2e626e30820122300d06092a864886f70d01010105000382010f003082010a02820101009ea3f1d21fade5596e36a6a77095a94758e4b72466b7444ada4f7c4cf6fde9b1d470b93b65c1fdd896917f248ccae49b57c80dc21c64b010699432130d059d2d8392346e8a179c7c947835549c64a7a5680c518faf0a5cbea48e684fca6304775c8fa9239c34f1d5cb2d063b098bd1c17183c7521efc884641b2f0b41402ac87c7076848d4347cef59dd5a9c174ad25467db933c95ef48c578ba762f527b21666a198fb5e1fe2d8299b4dceb1791e96ad075e3ecb057c776d764fad8f0829d43c32ddf985a3a36fade6966cec89468721a1ec47ab38eac8da4514060ded51d283a787b7c69971bda01f49f76baa41b1f9b4348aa4279e0fa55645d6616441f0d0203010001a382019530820191300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff04023000301d0603551d0e04160414369d0c100452b9eb3ffe7ae852e9e839a3ae5adb301f0603551d23041830168014fb784f12f96015832c9f177f3419b32e36ea4189306a06082b06010505070101045e305c302606082b06010505073001861a687474703a2f2f6c6f63616c686f73743a343030322f6f637370303206082b060105050730028626687474703a2f2f6c6f63616c686f73743a343030302f61636d652f6973737565722d6365727430180603551d110411300f820d6578616d706c652e636f2e626e30270603551d1f0420301e301ca01aa0188616687474703a2f2f6578616d706c652e636f6d2f63726c30630603551d20045c305a300a060667810c0102013000304c06032a03043045302206082b060105050702011616687474703a2f2f6578616d706c652e636f6d2f637073301f06082b0601050507020230130c11446f20576861742054686f752057696c74300d06092a864886f70d01010b05000382010100bbb4b994971cafa2e56e2258db46d88bfb361d8bfcd75521c03174e471eaa9f3ff2e719059bb57cc064079496d8550577c127baa84a18e792ddd36bf4f7b874b6d40d1d14288c15d38e4d6be25eb7805b1c3756b3735702eb4585d1886bc8af2c14086d3ce506e55184913c83aaaa8dfe6160bd035e42cda6d97697ed3ee3124c9bf9620a9fe6602191c1b746533c1d4a30023bbe902cb4aa661901177ed924eb836c94cc062dd0ce439c4ece9ee1dfe0499a42cbbcb2ea7243c59f4df4fdd7058229bacf9a640632dbd776b21633137b2df1c41f0765a66f448777aeec7ed4c0cdeb9d8a2356ff813820a287e11d52efde1aa543b4ef2ee992a7a9d5ccf7da4"
testPreCertDER := "308204553082033da003020102021203e1dea6f3349009a90e0306dbb39c3e7ca2300d06092a864886f70d01010b0500304a310b300906035504061302555331163014060355040a130d4c6574277320456e6372797074312330210603550403131a4c6574277320456e637279707420417574686f72697479205833301e170d3139313031363132353431375a170d3230303131343132353431375a30133111300f060355040313086a756e74732e696f30820122300d06092a864886f70d01010105000382010f003082010a0282010100c91926403839aadbf2a73af4f85e3884df553880c7e9d11943121b941f284a2c805b6329a93d7fb2357c1298d811cfce61faa863c334149f948ff52a55a516e56b2d31d137b1d0319f2aabdea0e9d5e8630b54d7e53597e094c323e24a7ec1ab0db5d85651a641ec3fd7841fe5cbc675315c49b714238ead757e55409fd68c4b48d42f14c2124d381800fd2ec417ed7f363b00ab23aaddaf9113d5cf889bbf391431bffb91d425d11a1e79318b7007b8e75cc56633662c3d6c58175b5cab6225aa495361b1124642f19584820d215f23f46bd9fafa3341a0f7f387bf7cdecbccd7fcbcb3e917becb41562771e579884a0d8a1b170536f82ba90b398e9a6932150203010001a382016a30820166300e0603551d0f0101ff0404030205a0301d0603551d250416301406082b0601050507030106082b06010505070302300c0603551d130101ff04023000301d0603551d0e041604144d14d73117ca7f5a27394ed590b0d037eb5888a2301f0603551d23041830168014a84a6a63047dddbae6d139b7a64565eff3a8eca1306f06082b0601050507010104633061302e06082b060105050730018622687474703a2f2f6f6373702e696e742d78332e6c657473656e63727970742e6f7267302f06082b060105050730028623687474703a2f2f636572742e696e742d78332e6c657473656e63727970742e6f72672f30130603551d11040c300a82086a756e74732e696f304c0603551d20044530433008060667810c0102013037060b2b0601040182df130101013028302606082b06010505070201161a687474703a2f2f6370732e6c657473656e63727970742e6f72673013060a2b06010401d6790204030101ff04020500300d06092a864886f70d01010b0500038201010035f9d6620874966f2aa400f069c5f601dc11083f5859a15d20e9b1d2f9d87d3756a71a03cee0ab2a69b5173a4395b698163ba60394167c9eb4b66d20d9b3a76bf94995288e8d15c70bee969f77a71147718803e73df0a7832c1fcae1e3138601ebc61725bc7505c6d1e5b0eaf7797e09161d71e37d76370dc489312b1bf0600d1c952f846edb810c284c0d831f27481a8f2220ad178c87d8c4688023fa3798293dc9fdffa9e5b885a8107d8a2480226cd5f9121d6d7ea83b10292371ad6757e7729b27136a064f2901822b4f0ea52f8149a17860e37d3dc925488b1ba4aa26ef51e60de024e67e3d5e04ac97d8bd79a003e668ea2e1bd1c0b9d77c7cf7bfdc32"
logLine := func(typ orphanType, der, regID, orderID string) string {
return fmt.Sprintf(
@ -177,16 +162,16 @@ func TestParseLine(t *testing.T) {
},
{
Name: "Valid cert in line",
LogLine: logLine(certOrphan, testCertDERHex, "1001", "0"),
LogLine: logLine(certOrphan, testCertDER, "1001", "0"),
ExpectFound: true,
ExpectAdded: true,
ExpectAddedDER: testCertDERHex,
ExpectAddedDER: testCertDER,
ExpectRegID: 1001,
ExpectNoErrors: true,
},
{
Name: "Already inserted cert in line",
LogLine: logLine(certOrphan, testCertDERHex, "1001", "0"),
LogLine: logLine(certOrphan, testCertDER, "1001", "0"),
ExpectFound: true,
// ExpectAdded is false because we have already added this cert in the
// previous "Valid cert in line" test case.
@ -209,16 +194,16 @@ func TestParseLine(t *testing.T) {
},
{
Name: "Valid precert in line",
LogLine: logLine(precertOrphan, testPreCertDERHex, "9999", "0"),
LogLine: logLine(precertOrphan, testPreCertDER, "9999", "0"),
ExpectFound: true,
ExpectAdded: true,
ExpectAddedDER: testPreCertDERHex,
ExpectAddedDER: testPreCertDER,
ExpectRegID: 9999,
ExpectNoErrors: true,
},
{
Name: "Already inserted precert in line",
LogLine: logLine(precertOrphan, testPreCertDERHex, "1001", "0"),
LogLine: logLine(precertOrphan, testPreCertDER, "1001", "0"),
ExpectFound: true,
// ExpectAdded is false because we have already added this cert in the
// previous "Valid cert in line" test case.
@ -227,7 +212,7 @@ func TestParseLine(t *testing.T) {
},
{
Name: "Unknown orphan type",
LogLine: logLine(unknownOrphan, testPreCertDERHex, "1001", "0"),
LogLine: logLine(unknownOrphan, testPreCertDER, "1001", "0"),
ExpectFound: false,
ExpectAdded: false,
ExpectNoErrors: false,
@ -237,8 +222,7 @@ func TestParseLine(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
log.Clear()
found, added, typ := of.storeParsedLogLine(tc.LogLine)
t.Logf("%s", log.GetAllMatching(".*"))
found, added, typ := storeParsedLogLine(sa, ca, log, tc.LogLine)
test.AssertEquals(t, found, tc.ExpectFound)
test.AssertEquals(t, added, tc.ExpectAdded)
logs := log.GetAllMatching("ERR:")
@ -286,12 +270,9 @@ func TestNotOrphan(t *testing.T) {
fc.Set(time.Date(2015, 3, 4, 5, 0, 0, 0, time.UTC))
sa := &mockSA{}
ca := &mockCA{}
issuers, err := loadIssuers([]string{"../../test/test-ca.pem", "../../test/test-ca2.pem"})
test.AssertNotError(t, err, "loading issuers")
of := orphanFinder{log, sa, ca, issuers, time.Hour}
log.Clear()
found, added, typ := of.storeParsedLogLine("cert=fakeout")
found, added, typ := storeParsedLogLine(sa, ca, log, "cert=fakeout")
test.AssertEquals(t, found, false)
test.AssertEquals(t, added, false)
test.AssertEquals(t, typ, unknownOrphan)

View File

@ -1,20 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDMDCCAhigAwIBAgIIR8kD33NctSkwDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE
AxMVbWluaWNhIHJvb3QgY2EgNTU5MzdmMB4XDTIwMDYwNDIyMjY1NFoXDTIyMDcw
NDIyMjY1NFowFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDOxrD2fSEKlqiLEst5Ysg0qjrldebpcR7bFqS0fO2q
gwtJ6lo+kCwacnjoUKar2cWqC+FlqkGnW/Htdb7H0kFnMdXM26iMNMcLuN3SmWDw
JzqMmZ9OAB7zYxy0ePu5EOFMPSvx3tK/7LP3YAj32Xbmf/fCRuAqCwbEqxptzoCP
rUqAN/1jfcf0MKqojrBRN0iRgTw5DpjW3RhNew7ngzvcgqroqyEXUE5/BCwRGPqr
xluhW7OxVX4OGEboW4KOvDbrVpmnUe8VcKlNV9L5HwkL29xc/AJOrFsiElNGVAvW
kY60+wH5xf+dWSA1RBdAm4JWShg81R0gdes3KRreqW6RAgMBAAGjeDB2MA4GA1Ud
DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0T
AQH/BAIwADAfBgNVHSMEGDAWgBS5uijpDluYTxcU27MKGYqPixX8MDAWBgNVHREE
DzANggtleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAqZWk3H9yqwrKZQ/F
dbtIqrbp7dLEolhcBmyVLIjAFJc/CvaciRgzBMsDBfG3o2sspu/WIngUbHPGHXK+
yWmVHBOtB63U6hlXk7GFeMsoyomT/dNM6bET+1E8xpXHR0VnlF/YDytUzcglrNcu
VpGC56i5ZpyKl5+XQ+Q0pnpt3npymvkJcWXCUisSSGmOsCf5CA9O/A83nPAMlC1I
bM7hzOXdxrMYZFSbo1PQKPWuzsgToVNN5Vk22uphxaH9rWoKW2I3BAaVGKqvyoma
bI4oIj4aevoUiYOKVV+t1rKqvdgCcx9QMPWf85Od0n0Sg/8oTwydNtg7XQ0Sj90d
SWWW/Q==
-----END CERTIFICATE-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA41Af7nGW3cnU+ckGRCp/k9Ks0S8im7zLftuxnYLHXlgf1+Kr
PYxR+T5asULgUW7YDADVd5omUKjo3Lg6srTgBtpsynTrhBZOqANy/caM1CpE+Ao+
g6GYzIyzBozPi0+1mQ4q/5fxlAT+XROxsORwBr5Se6qaTyy6Da7NIjNndLQ6JeyL
uLRMCq9TjjYXmU/BiqbbWhnGuvztau938MVDKmYva2h2icmyQ5Y9rcgKbSrM29az
3lFM19xzdkgUVvEqJ3U6SDu8eH9dyfBFSwQZov+hAypzFeSahypugREmD6Iot23i
34+BnhMx6Y1ABBY951br6J36c/5yj4npwxngqwIDAQABAoIBAG6/iO8pVHG2dhdE
w9LOSd4BlMVOC7SI5TRnYT/2iaADm3AZNYkFJqMiqBkZFiVWtdgTR+2/os9FnD59
W8vZqBRusvZoxJ5UJ/pfw9S0ucRc28FlbFPBlaqDGm4kiLG9IiLx7i0dIEwXqr46
bCZdBd+jNpid5BSTHAqykasKFGucwBDOMXrUO92arPYwTdbGL3NorYzkcVLfkGgU
r4FiH4/3UwY/hLYy3/632305E+EFcbGfaRf/wB1lA3xMZ781K5GWqdjaicJeer5S
gamMyTFpxgLlvT8DQMSvOmiLSdTh2FF3+LwwZ8jJHQlldDkFhKkr7y7z2H56x/wJ
Sj6Bx1ECgYEA5AaT8f0P8KftytxhmRIuupyWyKI5tCZK+nqWnHcLVESLzjq73CWE
rlVKuLcFgw6WoQioxr7LeI/LVJd046pFXhsfnoTSFQiioAcZ6xtUlUioWONpeKv3
w7Dkua8KC6yKWdUnk4VfRhVJtKCJY9Z+a6QkbWeiUEPfiivsI2ckCXcCgYEA/zMp
0uwBkDTkLmTqafpv4sIPvqZZWBkvktPT9kDmpb7Ano9PFC4rqY92+Qh9eRC74mRJ
ua/1wM5Fe+1vDPvH4mEDh4frY5G59+G+MAN5Kw1M+c2n/o+STpJImZQigQa3rywI
nxPRPbCDyU2tZujmnsjL9okKW3w2hhJO6X5jL20CgYEAqaKnH2hnGl6jjb4jsU+Q
ie2CUyI0kWvHbc4TC7WYLQmNhE+3gBA9Q8BaBU7K//OzZXteq/Q2xKsc1gKSx+fd
ESRWgoRHEbTJ3wlJY9mCNEjITNBpn4c3nFKV5fltHMAwcKIdfibDeQzPN1wSub5R
cFy9aNKnMtU7kLwaQUAy1AMCgYEAzukcr/bKDbHUkAkiRmrW7HOLcHhPWC6Tc+hr
ou1cFGZkpiprY2FL5V58h81qbg4zR4soe3U/O+QCUkhgEZbSqakew3RgVYqBzYkq
OqOWSmGuV5t26d5eMXZJhrukfhiENXLuSow2yl2jfEOOpDGRSoxjUrApxaMgUfPm
J0piAMECgYBs9LWkADgigbjLmiHkyViAVXnjKC+C4U+G+lTlldIxaRKlmUl6iAeF
9mtQVtUm1fHPYE9NBiXb/GMddafOpoHIj1zfJbdWRLRQEevhk7PYfefO6mOK7b2g
oLNTG4WVgQKPQX+Q111wLvKWpIsOA03gOWEyZTLP45UroAGfh/N88Q==
-----END RSA PRIVATE KEY-----

View File

@ -1,20 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDRzCCAi+gAwIBAgIIfWdzK08iuGwwDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE
AxMVbWluaWNhIHJvb3QgY2EgNTU5MzdmMB4XDTIwMDYwNDIyMzI1N1oXDTIyMDcw
NDIyMzI1N1owFjEUMBIGA1UEAxMLZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQDjUB/ucZbdydT5yQZEKn+T0qzRLyKbvMt+27Gdgsde
WB/X4qs9jFH5PlqxQuBRbtgMANV3miZQqOjcuDqytOAG2mzKdOuEFk6oA3L9xozU
KkT4Cj6DoZjMjLMGjM+LT7WZDir/l/GUBP5dE7Gw5HAGvlJ7qppPLLoNrs0iM2d0
tDol7Iu4tEwKr1OONheZT8GKpttaGca6/O1q73fwxUMqZi9raHaJybJDlj2tyApt
Kszb1rPeUUzX3HN2SBRW8SondTpIO7x4f13J8EVLBBmi/6EDKnMV5JqHKm6BESYP
oii3beLfj4GeEzHpjUAEFj3nVuvonfpz/nKPienDGeCrAgMBAAGjgY4wgYswDgYD
VR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNV
HRMBAf8EAjAAMB8GA1UdIwQYMBaAFLm6KOkOW5hPFxTbswoZio+LFfwwMBYGA1Ud
EQQPMA2CC2V4YW1wbGUuY29tMBMGCisGAQQB1nkCBAMBAf8EAgUAMA0GCSqGSIb3
DQEBCwUAA4IBAQBULgckk9GWazkbu2eholA8ORoPx4d8kPHmoskIG7sz8sFxo87j
pIO0nbNN9iZABQ6v3JYMqc40Z+b2Sc4DJqkFQcoYOnZ8YVGQhNP/tjmKBcOM/eQb
/FFL1xqILFt/WofVXfnpgiyqVbQPwYeRsqBpwqnL/EMx7rtET+dmKDsqJSwUhtEw
vXvnkusxGnlvz8Eqj6WX2xWZfk1oBG+bUQJLBVirY4OX7eXMpKX66FXDBCMgPrdn
pf1yuULU69AbqDJBJ5N9q6w6H9KTJDzvM+EclxObuT84wcEoWpF0055EVnBKHKoG
7VAIWpdVUzibqgQEVX5FiqWMNEdzhfKVSHex
-----END CERTIFICATE-----

View File

@ -1,20 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDODCCAiCgAwIBAgIII8rbZbTIezIwDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE
AxMVbWluaWNhIHJvb3QgY2EgMjljMWM5MB4XDTIwMDYwNDIyMzMzOFoXDTIyMDcw
NDIyMzMzOFowGjEYMBYGA1UEAxMPbGV0c2VuY3J5cHQub3JnMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA684jaKhaEskHRr2pQ5ST7bFjBVx8jStcNZ2Y
NuF7qjLYfVFHhZqrshiyphm0V8k/clQFiVUpE+bY37Q/dzH4vPZw02OKIR2KR4kQ
Bi7wXY/HxiQ405PBbOmQhGbmsYnSatkPsgAWTXcE0cJGkSTkO1PX1Z/rFfEZvFac
JlBO6guwCjJZakAHKiUV9pfJ3CU/OeNW7ep3DLPtSP2dxBRXyMoMSObjv4dG3yD8
HDHiAPbRhvabV2PXSIi9WcGGacNwvCMgMMwjarkFTQGBQmXhIV/Eq2zT/r3IK69R
swc7BtUjHXtFoyhWRCRaX2u5Lhs2o9dc2OvPmAqeCvF0hNHfXwIDAQABo3wwejAO
BgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMAwG
A1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU43XymR5OQ/ghn7nvl2oiI/eOosMwGgYD
VR0RBBMwEYIPbGV0c2VuY3J5cHQub3JnMA0GCSqGSIb3DQEBCwUAA4IBAQBQUW/d
9hy4ZwKVbtyjm3/gbc8WwV/OqW9mG0Zg7nNUf0s107zathX4JEoodlDHKqTjV8+v
VJMJB4n3AwyVaUC3FmSnBieEEfDKhurk2dzY3qBGPdxZBfW1HAxvUEgn/0S8p4tr
WjR1nLLxObKxG58i9UhlSeOsKTefJl6oIC1ChgDq8hInUSrRPwROE5PMpmwAnAHM
yeaz6Tv4cBRMgB1TDUXKpgDKl1GZaegAqsptzMZSJkBwzv9ZmAcpDpeNqreA4D9+
vfGum/oZwLPRSOfitow5+jXc92jmZu2SHP45MdXZSX6RzfEe+Lb5BCYLJaDVJLrb
vCzz79LbGdPpawer
-----END CERTIFICATE-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA684jaKhaEskHRr2pQ5ST7bFjBVx8jStcNZ2YNuF7qjLYfVFH
hZqrshiyphm0V8k/clQFiVUpE+bY37Q/dzH4vPZw02OKIR2KR4kQBi7wXY/HxiQ4
05PBbOmQhGbmsYnSatkPsgAWTXcE0cJGkSTkO1PX1Z/rFfEZvFacJlBO6guwCjJZ
akAHKiUV9pfJ3CU/OeNW7ep3DLPtSP2dxBRXyMoMSObjv4dG3yD8HDHiAPbRhvab
V2PXSIi9WcGGacNwvCMgMMwjarkFTQGBQmXhIV/Eq2zT/r3IK69Rswc7BtUjHXtF
oyhWRCRaX2u5Lhs2o9dc2OvPmAqeCvF0hNHfXwIDAQABAoIBAFC+aF+I7jbqgURW
42PRt4m3qQmH7tpEE7IEQb/hHABeosTelRgJq2szi9DWkmtQ7RnP7YlmEMfQz0hi
pyzAfsTtuhqYRg8q11PBeiwz3HidKDIP6yl/ucb6f1LnDW2TnOqbYwV3hCuIaq0M
0i8XK9Oo1QpAVTZRNZfJLHTuIOeA6r0COQfGzbW69D8NbWoy7PvFEaTQKlnXSbUJ
NqjHO640KGRIWZXsd0S3UkX/DC/ZtqEi2RCgsMpXidogvfWE8Yzrms/0F/H7q1wG
fVu7kPbRowiAzZSQQsu/MmC0wvdQJSb5Tw4JOCXGsDXYQdigR2D7B001SP7LIyw/
yBzkhekCgYEA8J4uEgZeRmTfovTlks8ulMhFXB1oB2jEmxqyccwbgbwOhM+hPWQe
qfKTsH43ZtM00CwFz4HzT8dWCRUfORHcf6+iHsT76N/M8VIS/x4c0su93Po8xY+4
tJGvLag8U+oosTNl3uSuhNxl6TVx582PHp3/Vn1LLOj/dPbfo2pn2yMCgYEA+uEy
bCsnPjzZvPOCOp01vKGTDtBCvr3BK7AF1tsfiYWfJsbwRrNQ02TIQwju7E9ayHSU
ZEIFUKf4E+zm7gd0yLZ6DMbe44M0HRweTV4CV9pJHuRxwJhFmCiqS+bYaclIOR04
EalbahX5t3DP8ZruLVdBgi+KnccOJlA2IoAynJUCgYAZVF1/MkJsYKQWMHeWW88I
hIigqMvRs9q2hTnxts3Se2x/2KedodOEim+3raHBZkxx+aBm9sQZSt+otxuBU3sF
ygRj/tKR8jVN1hj/2DiqjB4hjAontfh4sbliMgqfvs+nz8RSkXo5rEXiJekmwMHn
NDSz8x6dzK1Pr8ldF491RwKBgH06NZoKvE7zvtfzUNkDKhSbLjWhvP9K5oZxGakS
vZ4+pZ+Mg9k2nqy2TMQxTFmGjtEqZ/vXfKGzBkCj6u17qU6azzdbeVxlXHj/VRzX
RSInIoKaEzHIkEyQV9kFRJchUry3mgou2COPDpQDari11hepy1g5dN6mwqhbN3pn
NVw1AoGBAOTiKFh94yEjHuqNSSyNFD1CFJqlG09+fQmNFXBe4mPmfVneWJ0+ZpwW
x3bOCVkPJo0/vnfEdo7GJnhSLHaEMj2SoPlqYJPV/J0LfWSLWflroQKlAIOLW80y
gjVKoceqaddS7OsxNx0aeVyvaSo1d+ygmucZD7htNsG86S+JoOtO
-----END RSA PRIVATE KEY-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA5m04f98iiXYlnX6JeYouJGcIgeuBamHFwfPUNymGFLCSh05S
Gww2YjhlMhahsSJiHGqIbowYrivKOoSJrYzMksxX6pjolg3MI35m86wYAg+pqEHh
ofeDcT+fPoTw5svsyO86fDWw2a4DLHX7znUS66pSJnaPHvXEErz6Npqt/9yjKbAw
hZxL15TSApJkj8PusDxZ9/C5X6Csy2HGn2rKd9tRUEQAYE1wBKU6aHQ4AhKtzQAQ
+FNu+Hd9IOvAKIo/DatL16k9k4gspbKcJp5nPwDr9JaSczfkU96uOkdL72+LxcaX
9q4sIusOXcvABBacpsnkmaam5fHORAcUEHGMSwIDAQABAoIBACnixrdvzy5fnJzR
aJoARTz2wbQkJCU7WqBT+0p/sNDH/Aq+cOxbvvMBv1tog8HYNy9lKiG2M7JNYXhb
qU8z3ef9XynU28qS/X2iN4Kp0L9nK3bbavFvNaR7ZS4PKl85yHQKEH6Nn/UhzY/i
boBsBaFzF3XIbWG6WQby9STB30k38N/QnDbsb2OJK03sJB9Buhz169gZ61oK/zs1
bd3hUDX3ZeI/XLZCKTbejj7+xe67u+HKvrRxjfJdPRBmb1ZPCb7YDLEegKvyPgun
SPhip0iAHLHpXZGem4dimfUrppyy2/Xi05aaZwbyyLIWumGPsEZa8FyF7isaVCla
VRqcZmECgYEA9FuP/+Qrz78VGdiAIEblLAeZ90ZVbzMiyKTVTG6WmK6jvaJreZZY
FdE2MTcAsn+m9MNhnJQn2tGo7jhca+kqkLWjAkMiG5xsJH4zm8n7471mLhQwt2lw
871kjjDzbm+8PTAIaGWAz9jucbgxbu3UxA1Td48MvqFsgDwVSDdeV3ECgYEA8We9
ueRHMon+FDNH1pL3yYq+ANTwl4OUZ+rhdxbzvRKRYhb8oQ6Ib254JRMAMN/XWT/N
E0yiUbr97rx5lnYItp6mahbw8xv8l+s2RM/TG5TfKK1RITjVopqZpG+Uz196Y7xX
iyUASMTznZhbPG3+7rX5XYQuMFzr8+QXDHILmXsCgYAICt9xb6QVgVeDc0G8TjkK
uvFRVypGr6ssaWhvzI/+VHklK6xX4x/hD/K1qfbG6Taoham3ypSJOi9SL96y2ojB
HIlR8L21pO9WQCUYsows0bYEPDviPYEvNIOTvn60ms7aQLN2JCkaLiyi54oQ+Zjw
HvQpUjb8Kznz+oZEyzW6sQKBgCTpjPwwqKZUrVIfaTupK1RY76am6MbyKq4dHy6b
hteBUFOkWiqyUzBevuZEWoIeqAoQlGYAEM3Yft2TWjAkij6KUb3lFiDGRcBhCeJJ
uOj9wYWxwrcGvrvnUdjv6twuqEM52FUBamK2It4VHtZFp3aOwruG650fiEC5vsB7
a8SjAoGBALlUvePHaZs0/dUluJv2wwkgpy9fmc8hnvwopOpRDcujB6mW16bw80qe
EKMJSx3z7R3mNYnbtujn8xAIxpO4AVX1glZImp0C45PGNw2Kvry7FB3coy26YTJp
hcACUhfVkl9vJkje7sJZyyv9hIOaX+fVhQeZrTOoSHmz9vkH0Uir
-----END RSA PRIVATE KEY-----

View File

@ -1,20 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDSzCCAjOgAwIBAgIIVZN/5ReT87wwDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE
AxMVbWluaWNhIHJvb3QgY2EgNTU5MzdmMCAXDTIwMDYwNDIyMjY1NFoYDzIxMjAw
NjA0MjMyNjU0WjAgMR4wHAYDVQQDExVtaW5pY2Egcm9vdCBjYSA1NTkzN2YwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDmbTh/3yKJdiWdfol5ii4kZwiB
64FqYcXB89Q3KYYUsJKHTlIbDDZiOGUyFqGxImIcaohujBiuK8o6hImtjMySzFfq
mOiWDcwjfmbzrBgCD6moQeGh94NxP58+hPDmy+zI7zp8NbDZrgMsdfvOdRLrqlIm
do8e9cQSvPo2mq3/3KMpsDCFnEvXlNICkmSPw+6wPFn38LlfoKzLYcafasp321FQ
RABgTXAEpTpodDgCEq3NABD4U274d30g68Aoij8Nq0vXqT2TiCylspwmnmc/AOv0
lpJzN+RT3q46R0vvb4vFxpf2riwi6w5dy8AEFpymyeSZpqbl8c5EBxQQcYxLAgMB
AAGjgYYwgYMwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr
BgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS5uijpDluYTxcU
27MKGYqPixX8MDAfBgNVHSMEGDAWgBS5uijpDluYTxcU27MKGYqPixX8MDANBgkq
hkiG9w0BAQsFAAOCAQEAkRHRKnSQ4+c5cfJxqJ+FtivRfAgKEgGUN1RwW6Dwbe2t
ndIqlw9IODxVxAnTCKe30g77SSormxeNIw9BALFR7gFAU5QsU6KtC8qwSwlOz4BZ
EYGmPDIn8f+uhiwo1GRlGPko3hksWeimw+wkwKJVKGDnCr7fxqqJrfb3eit07KIx
IVqSqH3aby92Q9owK74JJBXN8FnNoCYwRNQ3qI2ViDj+fQQpQDSJp2BDCQ2196hB
DcPAgECC6AyxiGEvSeXNrTgWYtAjLqxTiGbshULdbDop8AMFCzf6ALRC3rMfKvNR
Z8AM2ohnwVlfiz6G19JFKp3lNqLegVGemLjLyX2d8A==
-----END CERTIFICATE-----

View File

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAp3i+84dsjNu8JwAk5j6zcfzZzhmI647NdNOK/iA8+0ycsuUu
Hf32NkOrFoWpSfn7+Tt2kKxM8/qbG75QFDfV7tU5V96BllqGz6Kv+Gv8GWOPipHO
qgt1HAq1nWz8OliiM/MyI+UEYQgSJlJjO6p1UnRhvSimtN3KAw+KwrRaaABpUf1E
eBqHksKlq+TQIlr8E/+qxCmYkPUVhIPi2tiIiLLIuKopzioHqTSI8ltUYxHtuHD4
TfFcTNvTVxYI3KN+WqUxZ2fXAPsmEjWQwrtoNioZL/OVdr0dPLtdkIgFl857OBRK
BMnHvXmYE/ycAwUpZg4JApDZA6wQnOb3drxbDQIDAQABAoIBAB+kqffby7/luOxp
k49Jo6BTFVhi7MMNbXa4jdesgbk95ZHLyeXy2XWxXX9Y6/7FVD3oZWO6mqOy42Hf
mMPpNOv2r+oRaczd+AD9jWBUDwNBE5ssJ69rkMomn+BJ+nKP0r4cIoozuJsY6k0B
Xiyk7ZwRz3HtX2pnScdARYi6iSaDNv3svzNqSpiTrThxDSCOhzbDwWxpSga+z9QM
iIhnmX7OSsdgVAx7kAjqzqUNYBUmhHQ6dPsSXpCB/FZna3fMmaZbxZiqNtxt9nLl
tI+9Vchg4NEg4gezTNno95708OIoenS1Dn7pYug/yJpVFxWCsg30LBrhyTOTLJl1
iAm3rGUCgYEA3DwBnoXAK5lnha3l1wr5de/D3mL4y/GyEzP34e6WcRU9OU433+cD
+mNpPH7DCyUlHTm+uCEnMBfLUmTCA7m4ixEnafuYOcgZF0K+s0ep1EY2H7hAMsB/
OVTdEv3PRwarVMCazyEpqRGwwo36f7B3XxmZEhxKKV2doa7+UPYsDvMCgYEAwqsw
Z4ewLLzhXLp9yw8+Iry+HsfhwWVL7ZpIJCGSiMZX/CpQpOQTidIRLyOw/PdqfzD3
O90rOLzrW0rGQ7XnrLVl9su4I4uZ84DsKDoYDv3vcWT6C1qxUdfUVhxKzla6KFLP
T+4mlYKGzlOiHW0qTDKRqHaPCqqop3AGbj6Ubf8CgYBlCtLjXBIS7srkNiihRNO3
HE4NFfN3/mfpD4rHCaPUNh5k0FIqU98rXbjGnJH35w7kHb421F8aXZBXOQsaknbs
tu4SXfA1cmywk1rS/ioYzi2+19X8cvzr3NehAvm6aIDq3YMpTNnES+2BFYq8UsYx
x5jHClusJttPdu4PTyJfqQKBgB3t6/c+6Vs3fv6evZBmu4rjsedRm+f8Bvx05/qG
Ht1ggU6HwvZXCpn57iJtPlzmPT1o7doKWwbSJO1YRbtLUF9BVHfpQlpUsEq725Mj
u2cyq4mnmLn+K50FreO/XdDzjJN+h9kmKFB8TPWT7izQB9zHOZXJBJ0DOALmOlbg
0DlJAoGAQrz+uu+nBwWZBhx7EGJpsbfAuwPGyxI71EIEh1A7HMv0AxvbDcy6PvFn
eAuMBRJYqmWi/oAaXoxDgfhJBnSHD/vP+YZW7mmG07npOs8/C7CGsswwEDgf/ZtS
ukD2mdcu4zXBnyKwkXqBZTDL5a++5QXbPYfFDtbzO8UbC5wqBM4=
-----END RSA PRIVATE KEY-----

View File

@ -1,20 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDSzCCAjOgAwIBAgIIKcHJulXb3YMwDQYJKoZIhvcNAQELBQAwIDEeMBwGA1UE
AxMVbWluaWNhIHJvb3QgY2EgMjljMWM5MCAXDTIwMDYwNDIyMzMzN1oYDzIxMjAw
NjA0MjMzMzM3WjAgMR4wHAYDVQQDExVtaW5pY2Egcm9vdCBjYSAyOWMxYzkwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCneL7zh2yM27wnACTmPrNx/NnO
GYjrjs1004r+IDz7TJyy5S4d/fY2Q6sWhalJ+fv5O3aQrEzz+psbvlAUN9Xu1TlX
3oGWWobPoq/4a/wZY4+Kkc6qC3UcCrWdbPw6WKIz8zIj5QRhCBImUmM7qnVSdGG9
KKa03coDD4rCtFpoAGlR/UR4GoeSwqWr5NAiWvwT/6rEKZiQ9RWEg+La2IiIssi4
qinOKgepNIjyW1RjEe24cPhN8VxM29NXFgjco35apTFnZ9cA+yYSNZDCu2g2Khkv
85V2vR08u12QiAWXzns4FEoEyce9eZgT/JwDBSlmDgkCkNkDrBCc5vd2vFsNAgMB
AAGjgYYwgYMwDgYDVR0PAQH/BAQDAgKEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr
BgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBTjdfKZHk5D+CGf
ue+XaiIj946iwzAfBgNVHSMEGDAWgBTjdfKZHk5D+CGfue+XaiIj946iwzANBgkq
hkiG9w0BAQsFAAOCAQEAFHfBaqEujbVCHt3NnuO/MDVs7ZU8qDpImdzTjnB50IQ1
YM7mfK887Nm0e7Qw+hHQcZqyVMr/lwVCxXln4s7nd4gWscniicklw0mLYYKxJZfi
sh0kxvfzRP2ohquA6g0K6gyA06xfWbar6Q4Ww8DltX+Bn5UDlE4oryVFWx8uZoNP
49A0U0nkoaApzSKRkxTb0H/yVG6w6twr9ONT7eGHlrYaN1K/znxo4/jOgaTrzjwj
PdWtvyxXnpe02JGAQtVp2Iw6Zfa7xxLY+c6wZrtgSKf/UPx9w7dCpsGPLK9Q2pNn
7T6S1Kpnwq8Ko5ND3oCecW4LoRxy349vEuWEHWFeKw==
-----END CERTIFICATE-----

View File

@ -1,37 +0,0 @@
// Package issuercerts defines types representing a certificate that issue other
// certificates.
package issuercerts
import (
"crypto/sha256"
"crypto/x509"
"math/big"
"github.com/letsencrypt/boulder/core"
)
type Issuer struct {
Cert *x509.Certificate
}
type ID int64
// New reads an issuer certificate from a file and returns an Issuer.
func FromFile(filename string) (*Issuer, error) {
cert, err := core.LoadCert(filename)
if err != nil {
return nil, err
}
return &Issuer{cert}, nil
}
func FromCert(cert *x509.Certificate) *Issuer {
return &Issuer{cert}
}
// idForIssuer generates a stable ID for an issuer certificate, based on a hash
// of the issuer certificate's bytes. This is used for identifying which issuer
// issued a certificate in the certificateStatus table.
func (issuer *Issuer) ID() ID {
h := sha256.Sum256(issuer.Cert.Raw)
return ID(big.NewInt(0).SetBytes(h[:4]).Int64())
}

View File

@ -26,7 +26,6 @@ import (
"github.com/letsencrypt/boulder/goodkey"
bgrpc "github.com/letsencrypt/boulder/grpc"
"github.com/letsencrypt/boulder/identifier"
"github.com/letsencrypt/boulder/issuercerts"
blog "github.com/letsencrypt/boulder/log"
"github.com/letsencrypt/boulder/metrics"
"github.com/letsencrypt/boulder/policy"
@ -1655,11 +1654,7 @@ func (ra *RegistrationAuthorityImpl) revokeCertificate(ctx context.Context, cert
status := string(core.OCSPStatusRevoked)
reason := int32(code)
revokedAt := ra.clk.Now().UnixNano()
serial := core.SerialToString(cert.SerialNumber)
issuerID := int64(issuercerts.FromCert(ra.issuer).ID())
ocspResponse, err := ra.CA.GenerateOCSP(ctx, &caPB.GenerateOCSPRequest{
Serial: &serial,
IssuerID: &issuerID,
CertDER: cert.Raw,
Status: &status,
Reason: &reason,
@ -1668,6 +1663,7 @@ func (ra *RegistrationAuthorityImpl) revokeCertificate(ctx context.Context, cert
if err != nil {
return err
}
serial := core.SerialToString(cert.SerialNumber)
// for some reason we use int32 and int64 for the reason in different
// protobuf messages, so we have to re-cast it here.
reason64 := int64(reason)

View File

@ -5,10 +5,6 @@
"stdoutlevel": 7,
"stdoutlevel": 7
},
"issuerFiles": [
"/tmp/intermediate-cert-rsa-a.pem",
"/tmp/intermediate-cert-rsa-b.pem"
],
"tls": {
"caCertFile": "test/grpc-creds/minica.pem",

View File

@ -5,10 +5,6 @@
"stdoutlevel": 7,
"stdoutlevel": 7
},
"issuerFiles": [
"/tmp/intermediate-cert-rsa-a.pem",
"/tmp/intermediate-cert-rsa-b.pem"
],
"tls": {
"caCertFile": "test/grpc-creds/minica.pem",