Add SCT embedding (#3521)
Adds SCT embedding to the certificate issuance flow. When a issuance is requested a precertificate (the requested certificate but poisoned with the critical CT extension) is issued and submitted to the required CT logs. Once the SCTs for the precertificate have been collected a new certificate is issued with the poison extension replace with a SCT list extension containing the retrieved SCTs. Fixes #2244, fixes #3492 and fixes #3429.
This commit is contained in:
parent
6ad718a42e
commit
9c9e944759
76
ca/ca.go
76
ca/ca.go
|
@ -22,6 +22,8 @@ import (
|
|||
"github.com/cloudflare/cfssl/ocsp"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/cloudflare/cfssl/signer/local"
|
||||
"github.com/google/certificate-transparency-go"
|
||||
cttls "github.com/google/certificate-transparency-go/tls"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/miekg/pkcs11"
|
||||
"golang.org/x/net/context"
|
||||
|
@ -29,9 +31,9 @@ import (
|
|||
"github.com/letsencrypt/boulder/ca/config"
|
||||
caPB "github.com/letsencrypt/boulder/ca/proto"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
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"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
|
@ -99,6 +101,13 @@ type certificateStorage interface {
|
|||
AddCertificate(context.Context, []byte, int64, []byte) (string, error)
|
||||
}
|
||||
|
||||
type certificateType string
|
||||
|
||||
const (
|
||||
precertType = certificateType("precertificate")
|
||||
certType = certificateType("certificate")
|
||||
)
|
||||
|
||||
// CertificateAuthorityImpl represents a CA that signs certificates, CRLs, and
|
||||
// OCSP responses.
|
||||
type CertificateAuthorityImpl struct {
|
||||
|
@ -135,7 +144,7 @@ type Issuer struct {
|
|||
// issuer, including the cfssl signer and OCSP signer objects.
|
||||
type internalIssuer struct {
|
||||
cert *x509.Certificate
|
||||
eeSigner signer.Signer
|
||||
eeSigner *local.Signer
|
||||
ocspSigner ocsp.Signer
|
||||
}
|
||||
|
||||
|
@ -432,7 +441,7 @@ func (ca *CertificateAuthorityImpl) IssueCertificate(ctx context.Context, issueR
|
|||
return emptyCert, err
|
||||
}
|
||||
|
||||
certDER, err := ca.issueCertificateOrPrecertificate(ctx, issueReq, serialBigInt, validity, "cert", nil)
|
||||
certDER, err := ca.issueCertificateOrPrecertificate(ctx, issueReq, serialBigInt, validity, certType)
|
||||
if err != nil {
|
||||
return emptyCert, err
|
||||
}
|
||||
|
@ -445,29 +454,60 @@ func (ca *CertificateAuthorityImpl) IssuePrecertificate(ctx context.Context, iss
|
|||
return nil, berrors.InternalServerError("Precertificate flow is disabled")
|
||||
}
|
||||
|
||||
if issueReq.RegistrationID == nil {
|
||||
return nil, berrors.InternalServerError("RegistrationID is nil")
|
||||
}
|
||||
|
||||
serialBigInt, validity, err := ca.generateSerialNumberAndValidity()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
precertDER, err := ca.issueCertificateOrPrecertificate(ctx, issueReq, serialBigInt, validity, "cert", &ctPoisonExtension)
|
||||
precertDER, err := ca.issueCertificateOrPrecertificate(ctx, issueReq, serialBigInt, validity, precertType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &caPB.IssuePrecertificateResponse{
|
||||
Precert: &corePB.Precertificate{Der: precertDER},
|
||||
SctFetchingConfig: &corePB.SCTFetchingConfig{},
|
||||
DER: precertDER,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// IssueCertificateForPrecertificate takes a precertificate and a set of SCTs for that precertificate
|
||||
// and uses the signer to create and sign a certificate from them. The poison extension is removed
|
||||
// and a SCT list extension is inserted in its place. Except for this and the signature the certificate
|
||||
// exactly matches the precertificate. After the certificate is signed a OCSP response is generated
|
||||
// and the response and certificate are stored in the database.
|
||||
func (ca *CertificateAuthorityImpl) IssueCertificateForPrecertificate(ctx context.Context, req *caPB.IssueCertificateForPrecertificateRequest) (core.Certificate, error) {
|
||||
emptyCert := core.Certificate{}
|
||||
|
||||
return emptyCert, berrors.InternalServerError("IssueCertificateForPrecertificate is not implemented")
|
||||
if !features.Enabled(features.EmbedSCTs) {
|
||||
return emptyCert, berrors.InternalServerError("IssueCertificateForPrecertificate is not implemented")
|
||||
}
|
||||
precert, err := x509.ParseCertificate(req.DER)
|
||||
if err != nil {
|
||||
return emptyCert, err
|
||||
}
|
||||
var scts []ct.SignedCertificateTimestamp
|
||||
for _, sctBytes := range req.SCTs {
|
||||
var sct ct.SignedCertificateTimestamp
|
||||
_, err = cttls.Unmarshal(sctBytes, &sct)
|
||||
if err != nil {
|
||||
return emptyCert, err
|
||||
}
|
||||
scts = append(scts, sct)
|
||||
}
|
||||
certPEM, err := ca.defaultIssuer.eeSigner.SignFromPrecert(precert, scts)
|
||||
if err != nil {
|
||||
return emptyCert, err
|
||||
}
|
||||
serialHex := core.SerialToString(precert.SerialNumber)
|
||||
block, _ := pem.Decode(certPEM)
|
||||
if block == nil || block.Type != "CERTIFICATE" {
|
||||
err = berrors.InternalServerError("invalid certificate value returned")
|
||||
ca.log.AuditErr(fmt.Sprintf("PEM decode error, aborting: serial=[%s] pem=[%s] err=[%v]",
|
||||
serialHex, certPEM, err))
|
||||
return emptyCert, err
|
||||
}
|
||||
certDER := block.Bytes
|
||||
ca.log.AuditInfo(fmt.Sprintf("Signing success: serial=[%s] names=[%s] precertificate=[%s] certificate=[%s]",
|
||||
serialHex, strings.Join(precert.DNSNames, ", "), hex.EncodeToString(req.DER),
|
||||
hex.EncodeToString(certDER)))
|
||||
return ca.generateOCSPAndStoreCertificate(ctx, *req.RegistrationID, *req.OrderID, precert.SerialNumber, certDER)
|
||||
}
|
||||
|
||||
type validity struct {
|
||||
|
@ -498,7 +538,7 @@ func (ca *CertificateAuthorityImpl) generateSerialNumberAndValidity() (*big.Int,
|
|||
return serialBigInt, validity, nil
|
||||
}
|
||||
|
||||
func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context.Context, issueReq *caPB.IssueCertificateRequest, serialBigInt *big.Int, validity validity, certType string, addedExtension *signer.Extension) ([]byte, error) {
|
||||
func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context.Context, issueReq *caPB.IssueCertificateRequest, serialBigInt *big.Int, validity validity, certType certificateType) ([]byte, error) {
|
||||
csr, err := x509.ParseCertificateRequest(issueReq.Csr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -521,10 +561,6 @@ func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if addedExtension != nil {
|
||||
extensions = append(extensions, *addedExtension)
|
||||
}
|
||||
|
||||
issuer := ca.defaultIssuer
|
||||
|
||||
if issuer.cert.NotAfter.Before(validity.NotAfter) {
|
||||
|
@ -565,6 +601,10 @@ func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context
|
|||
NotAfter: validity.NotAfter,
|
||||
}
|
||||
|
||||
if certType == precertType {
|
||||
req.ReturnPrecert = true
|
||||
}
|
||||
|
||||
serialHex := core.SerialToString(serialBigInt)
|
||||
|
||||
if !ca.forceCNFromSAN {
|
||||
|
@ -581,7 +621,7 @@ func (ca *CertificateAuthorityImpl) issueCertificateOrPrecertificate(ctx context
|
|||
ca.log.AuditErr(fmt.Sprintf("Signing failed: serial=[%s] err=[%v]", serialHex, err))
|
||||
return nil, err
|
||||
}
|
||||
ca.signatureCount.With(prometheus.Labels{"purpose": certType}).Inc()
|
||||
ca.signatureCount.With(prometheus.Labels{"purpose": string(certType)}).Inc()
|
||||
|
||||
if len(certPEM) == 0 {
|
||||
err = berrors.InternalServerError("no certificate returned by server")
|
||||
|
|
103
ca/ca_test.go
103
ca/ca_test.go
|
@ -14,7 +14,11 @@ import (
|
|||
|
||||
cfsslConfig "github.com/cloudflare/cfssl/config"
|
||||
"github.com/cloudflare/cfssl/helpers"
|
||||
"github.com/cloudflare/cfssl/signer"
|
||||
"github.com/google/certificate-transparency-go"
|
||||
cttls "github.com/google/certificate-transparency-go/tls"
|
||||
"github.com/jmhodges/clock"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"golang.org/x/crypto/ocsp"
|
||||
"golang.org/x/net/context"
|
||||
|
||||
|
@ -23,12 +27,12 @@ import (
|
|||
"github.com/letsencrypt/boulder/cmd"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
berrors "github.com/letsencrypt/boulder/errors"
|
||||
"github.com/letsencrypt/boulder/features"
|
||||
"github.com/letsencrypt/boulder/goodkey"
|
||||
blog "github.com/letsencrypt/boulder/log"
|
||||
"github.com/letsencrypt/boulder/metrics"
|
||||
"github.com/letsencrypt/boulder/policy"
|
||||
"github.com/letsencrypt/boulder/test"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -361,15 +365,14 @@ func TestIssueCertificate(t *testing.T) {
|
|||
}
|
||||
|
||||
test.AssertNotError(t, err, "Failed to issue precertificate")
|
||||
certDER = response.Precert.Der
|
||||
certDER = response.DER
|
||||
precertDER = certDER
|
||||
} else {
|
||||
coreCert := core.Certificate{}
|
||||
if mode.issueCertificateForPrecertificate {
|
||||
coreCert, err = ca.IssueCertificateForPrecertificate(ctx,
|
||||
&caPB.IssueCertificateForPrecertificateRequest{
|
||||
IssueReq: issueReq,
|
||||
PrecertDER: precertDER,
|
||||
DER: precertDER,
|
||||
})
|
||||
|
||||
if true { // TODO(briansmith): !mode.enablePrecertificateFlow
|
||||
|
@ -816,9 +819,13 @@ func countMustStaple(t *testing.T, cert *x509.Certificate) (count int) {
|
|||
func issueCertificateSubTestMustStapleWhenDisabled(t *testing.T, i *TestCertificateIssuance) {
|
||||
// With ca.enableMustStaple = false, should issue successfully and not add
|
||||
// Must Staple.
|
||||
certType := "certificate"
|
||||
if i.mode.issuePrecertificate {
|
||||
certType = "precertificate"
|
||||
}
|
||||
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionTLSFeature, i.ca.csrExtensionCount), 1)
|
||||
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionTLSFeatureInvalid, i.ca.csrExtensionCount), 0)
|
||||
test.AssertEquals(t, signatureCountByPurpose("cert", i.ca.signatureCount), 1)
|
||||
test.AssertEquals(t, signatureCountByPurpose(certType, i.ca.signatureCount), 1)
|
||||
test.AssertEquals(t, countMustStaple(t, i.cert), 0)
|
||||
}
|
||||
|
||||
|
@ -826,9 +833,13 @@ func issueCertificateSubTestMustStapleWhenEnabled(t *testing.T, i *TestCertifica
|
|||
// With ca.enableMustStaple = true, a TLS feature extension should put a must-staple
|
||||
// extension into the cert. Even if there are multiple TLS Feature extensions, only
|
||||
// one extension should be included.
|
||||
certType := "certificate"
|
||||
if i.mode.issuePrecertificate {
|
||||
certType = "precertificate"
|
||||
}
|
||||
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionTLSFeature, i.ca.csrExtensionCount), 1)
|
||||
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionTLSFeatureInvalid, i.ca.csrExtensionCount), 0)
|
||||
test.AssertEquals(t, signatureCountByPurpose("cert", i.ca.signatureCount), 1)
|
||||
test.AssertEquals(t, signatureCountByPurpose(certType, i.ca.signatureCount), 1)
|
||||
test.AssertEquals(t, countMustStaple(t, i.cert), 1)
|
||||
}
|
||||
|
||||
|
@ -839,8 +850,12 @@ func issueCertificateSubTestTLSFeatureUnknown(t *testing.T, ca *CertificateAutho
|
|||
|
||||
func issueCertificateSubTestUnknownExtension(t *testing.T, i *TestCertificateIssuance) {
|
||||
// Unsupported extensions in the CSR should be silently ignored.
|
||||
certType := "certificate"
|
||||
if i.mode.issuePrecertificate {
|
||||
certType = "precertificate"
|
||||
}
|
||||
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionOther, i.ca.csrExtensionCount), 1)
|
||||
test.AssertEquals(t, signatureCountByPurpose("cert", i.ca.signatureCount), 1)
|
||||
test.AssertEquals(t, signatureCountByPurpose(certType, i.ca.signatureCount), 1)
|
||||
|
||||
// NOTE: The hard-coded value here will have to change over time as Boulder
|
||||
// adds new (unrequested) extensions to certificates.
|
||||
|
@ -856,8 +871,12 @@ func issueCertificateSubTestCTPoisonExtension(t *testing.T, i *TestCertificateIs
|
|||
// unknown extension, whether it has a valid or invalid value. The check
|
||||
// for whether or not the poison extension is present in the issued
|
||||
// certificate/precertificate is done in the caller.
|
||||
certType := "certificate"
|
||||
if i.mode.issuePrecertificate {
|
||||
certType = "precertificate"
|
||||
}
|
||||
test.AssertEquals(t, test.CountCounterVec(csrExtensionCategory, csrExtensionOther, i.ca.csrExtensionCount), 1)
|
||||
test.AssertEquals(t, signatureCountByPurpose("cert", i.ca.signatureCount), 1)
|
||||
test.AssertEquals(t, signatureCountByPurpose(certType, i.ca.signatureCount), 1)
|
||||
}
|
||||
|
||||
func findExtension(extensions []pkix.Extension, id asn1.ObjectIdentifier) *pkix.Extension {
|
||||
|
@ -872,3 +891,71 @@ func findExtension(extensions []pkix.Extension, id asn1.ObjectIdentifier) *pkix.
|
|||
func signatureCountByPurpose(signatureType string, signatureCount *prometheus.CounterVec) int {
|
||||
return test.CountCounterVec("purpose", signatureType, signatureCount)
|
||||
}
|
||||
|
||||
func TestIssueCertificateForPrecertificate(t *testing.T) {
|
||||
testCtx := setup(t)
|
||||
sa := &mockSA{}
|
||||
ca, err := NewCertificateAuthorityImpl(
|
||||
testCtx.caConfig,
|
||||
sa,
|
||||
testCtx.pa,
|
||||
testCtx.fc,
|
||||
testCtx.stats,
|
||||
testCtx.issuers,
|
||||
testCtx.keyPolicy,
|
||||
testCtx.logger)
|
||||
test.AssertNotError(t, err, "Failed to create CA")
|
||||
ca.enablePrecertificateFlow = true
|
||||
_ = features.Set(map[string]bool{"EmbedSCTs": true})
|
||||
defer features.Reset()
|
||||
|
||||
orderID := int64(0)
|
||||
issueReq := caPB.IssueCertificateRequest{Csr: CNandSANCSR, RegistrationID: &arbitraryRegID, OrderID: &orderID}
|
||||
precert, err := ca.IssuePrecertificate(ctx, &issueReq)
|
||||
test.AssertNotError(t, err, "Failed to issue precert")
|
||||
parsedPrecert, err := x509.ParseCertificate(precert.DER)
|
||||
test.AssertNotError(t, err, "Failed to parse precert")
|
||||
|
||||
// Check for poison extension
|
||||
poisoned := false
|
||||
for _, ext := range parsedPrecert.Extensions {
|
||||
if ext.Id.Equal(signer.CTPoisonOID) && ext.Critical {
|
||||
poisoned = true
|
||||
}
|
||||
}
|
||||
test.Assert(t, poisoned, "returned precert not poisoned")
|
||||
|
||||
sct := ct.SignedCertificateTimestamp{
|
||||
SCTVersion: 0,
|
||||
Timestamp: 2020,
|
||||
Signature: ct.DigitallySigned{
|
||||
Signature: []byte{0},
|
||||
},
|
||||
}
|
||||
sctBytes, err := cttls.Marshal(sct)
|
||||
test.AssertNotError(t, err, "Failed to marshal SCT")
|
||||
cert, err := ca.IssueCertificateForPrecertificate(ctx, &caPB.IssueCertificateForPrecertificateRequest{
|
||||
DER: precert.DER,
|
||||
SCTs: [][]byte{sctBytes},
|
||||
RegistrationID: &arbitraryRegID,
|
||||
OrderID: new(int64),
|
||||
})
|
||||
test.AssertNotError(t, err, "Failed to issue cert from precert")
|
||||
parsedCert, err := x509.ParseCertificate(cert.DER)
|
||||
test.AssertNotError(t, err, "Failed to parse cert")
|
||||
|
||||
// Check for SCT list extension
|
||||
list := false
|
||||
for _, ext := range parsedCert.Extensions {
|
||||
if ext.Id.Equal(signer.SCTListOID) && !ext.Critical {
|
||||
list = true
|
||||
var rawValue []byte
|
||||
_, err = asn1.Unmarshal(ext.Value, &rawValue)
|
||||
test.AssertNotError(t, err, "Failed to unmarshal extension value")
|
||||
sctList, err := helpers.DeserializeSCTList(rawValue)
|
||||
test.AssertNotError(t, err, "Failed to deserialize SCT list")
|
||||
test.Assert(t, len(*sctList) == 1, fmt.Sprintf("Wrong number of SCTs, wanted: 1, got: %d", len(*sctList)))
|
||||
}
|
||||
}
|
||||
test.Assert(t, list, "returned cert doesn't contain SCT list")
|
||||
}
|
||||
|
|
|
@ -72,9 +72,8 @@ func (m *IssueCertificateRequest) GetOrderID() int64 {
|
|||
}
|
||||
|
||||
type IssuePrecertificateResponse struct {
|
||||
Precert *core.Precertificate `protobuf:"bytes,1,opt,name=precert" json:"precert,omitempty"`
|
||||
SctFetchingConfig *core.SCTFetchingConfig `protobuf:"bytes,2,opt,name=sctFetchingConfig" json:"sctFetchingConfig,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
DER []byte `protobuf:"bytes,1,opt,name=DER,json=dER" json:"DER,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IssuePrecertificateResponse) Reset() { *m = IssuePrecertificateResponse{} }
|
||||
|
@ -82,25 +81,19 @@ func (m *IssuePrecertificateResponse) String() string { return proto1
|
|||
func (*IssuePrecertificateResponse) ProtoMessage() {}
|
||||
func (*IssuePrecertificateResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
|
||||
|
||||
func (m *IssuePrecertificateResponse) GetPrecert() *core.Precertificate {
|
||||
func (m *IssuePrecertificateResponse) GetDER() []byte {
|
||||
if m != nil {
|
||||
return m.Precert
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *IssuePrecertificateResponse) GetSctFetchingConfig() *core.SCTFetchingConfig {
|
||||
if m != nil {
|
||||
return m.SctFetchingConfig
|
||||
return m.DER
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type IssueCertificateForPrecertificateRequest struct {
|
||||
IssueReq *IssueCertificateRequest `protobuf:"bytes,1,opt,name=issueReq" json:"issueReq,omitempty"`
|
||||
PrecertDER []byte `protobuf:"bytes,2,opt,name=precertDER" json:"precertDER,omitempty"`
|
||||
SCTs [][]byte `protobuf:"bytes,3,rep,name=SCTs,json=sCTs" json:"SCTs,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
DER []byte `protobuf:"bytes,1,opt,name=DER,json=dER" json:"DER,omitempty"`
|
||||
SCTs [][]byte `protobuf:"bytes,2,rep,name=SCTs,json=sCTs" json:"SCTs,omitempty"`
|
||||
RegistrationID *int64 `protobuf:"varint,3,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
OrderID *int64 `protobuf:"varint,4,opt,name=orderID" json:"orderID,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *IssueCertificateForPrecertificateRequest) Reset() {
|
||||
|
@ -112,16 +105,9 @@ func (*IssueCertificateForPrecertificateRequest) Descriptor() ([]byte, []int) {
|
|||
return fileDescriptor0, []int{2}
|
||||
}
|
||||
|
||||
func (m *IssueCertificateForPrecertificateRequest) GetIssueReq() *IssueCertificateRequest {
|
||||
func (m *IssueCertificateForPrecertificateRequest) GetDER() []byte {
|
||||
if m != nil {
|
||||
return m.IssueReq
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *IssueCertificateForPrecertificateRequest) GetPrecertDER() []byte {
|
||||
if m != nil {
|
||||
return m.PrecertDER
|
||||
return m.DER
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -133,6 +119,20 @@ func (m *IssueCertificateForPrecertificateRequest) GetSCTs() [][]byte {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (m *IssueCertificateForPrecertificateRequest) GetRegistrationID() int64 {
|
||||
if m != nil && m.RegistrationID != nil {
|
||||
return *m.RegistrationID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *IssueCertificateForPrecertificateRequest) GetOrderID() int64 {
|
||||
if m != nil && m.OrderID != nil {
|
||||
return *m.OrderID
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GenerateOCSPRequest struct {
|
||||
CertDER []byte `protobuf:"bytes,1,opt,name=certDER" json:"certDER,omitempty"`
|
||||
Status *string `protobuf:"bytes,2,opt,name=status" json:"status,omitempty"`
|
||||
|
@ -404,34 +404,30 @@ var _OCSPGenerator_serviceDesc = grpc.ServiceDesc{
|
|||
func init() { proto1.RegisterFile("ca/proto/ca.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 458 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x53, 0xc1, 0x6e, 0xd3, 0x40,
|
||||
0x10, 0x4d, 0xe2, 0x94, 0xb4, 0x53, 0x83, 0x92, 0x69, 0x21, 0x56, 0x8a, 0x20, 0xf8, 0x80, 0x22,
|
||||
0x84, 0x5c, 0x29, 0x17, 0x0e, 0x9c, 0x8a, 0xd3, 0xa2, 0x48, 0x48, 0x54, 0x9b, 0x70, 0xe1, 0xb6,
|
||||
0xda, 0x4e, 0x52, 0x0b, 0xe1, 0x4d, 0x67, 0x37, 0x48, 0x1c, 0xf8, 0x0b, 0x24, 0x0e, 0xfc, 0x2c,
|
||||
0xf2, 0xda, 0x0e, 0xc6, 0xb8, 0xed, 0x6d, 0x67, 0xde, 0xec, 0xbe, 0xe7, 0xf7, 0xc6, 0x30, 0x50,
|
||||
0xf2, 0x74, 0xc3, 0xda, 0xea, 0x53, 0x25, 0x23, 0x77, 0xc0, 0x8e, 0x92, 0xa3, 0xc7, 0x4a, 0x33,
|
||||
0x95, 0x80, 0x66, 0xca, 0xa1, 0xf0, 0x2b, 0x0c, 0xe7, 0xc6, 0x6c, 0x29, 0x26, 0xb6, 0xc9, 0x2a,
|
||||
0x51, 0xd2, 0x92, 0xa0, 0x9b, 0x2d, 0x19, 0x8b, 0x7d, 0xf0, 0x94, 0xe1, 0xa0, 0x3d, 0x6e, 0x4f,
|
||||
0x7c, 0x91, 0x1d, 0xf1, 0x25, 0x3c, 0x62, 0x5a, 0x27, 0xc6, 0xb2, 0xb4, 0x89, 0x4e, 0xe7, 0xb3,
|
||||
0xa0, 0x33, 0x6e, 0x4f, 0x3c, 0x51, 0xeb, 0x62, 0x00, 0x3d, 0xcd, 0x57, 0xc4, 0xf3, 0x59, 0xe0,
|
||||
0xb9, 0x81, 0xb2, 0x0c, 0x7f, 0xb6, 0xe1, 0xc4, 0xf1, 0x5d, 0x32, 0xa9, 0x2a, 0xa5, 0xd9, 0xe8,
|
||||
0xd4, 0x10, 0x46, 0xd0, 0xdb, 0xe4, 0x88, 0xe3, 0x3d, 0x9c, 0x1e, 0x47, 0x4e, 0x6c, 0x6d, 0xbc,
|
||||
0x1c, 0xc2, 0x73, 0x18, 0x18, 0x65, 0x2f, 0xc8, 0xaa, 0xeb, 0x24, 0x5d, 0xc7, 0x3a, 0x5d, 0x25,
|
||||
0x6b, 0x27, 0xea, 0x70, 0x3a, 0xcc, 0x6f, 0x2e, 0xe2, 0xe5, 0xbf, 0xb0, 0xf8, 0xff, 0x46, 0xf8,
|
||||
0xab, 0x0d, 0x93, 0xba, 0x0d, 0x17, 0x9a, 0xeb, 0x22, 0x73, 0x5f, 0xde, 0xc0, 0x7e, 0x92, 0xcd,
|
||||
0x0a, 0xba, 0x29, 0x44, 0x9e, 0x44, 0x4a, 0x46, 0xb7, 0xd8, 0x28, 0x76, 0xc3, 0xf8, 0x0c, 0xa0,
|
||||
0xd0, 0x3d, 0x3b, 0x17, 0x4e, 0xa5, 0x2f, 0x2a, 0x1d, 0x44, 0xe8, 0x2e, 0xe2, 0xa5, 0x09, 0xbc,
|
||||
0xb1, 0x37, 0xf1, 0x45, 0xd7, 0xc4, 0x4b, 0x13, 0xfe, 0x80, 0xa3, 0xf7, 0x94, 0x12, 0x4b, 0x4b,
|
||||
0x1f, 0xe3, 0xc5, 0x65, 0xa9, 0x21, 0x80, 0x5e, 0xf9, 0x4e, 0x9e, 0x4f, 0x59, 0xe2, 0x13, 0x78,
|
||||
0x60, 0xac, 0xb4, 0x5b, 0xe3, 0x08, 0x0e, 0x44, 0x51, 0x65, 0x7d, 0x26, 0x69, 0x74, 0xea, 0x22,
|
||||
0xd9, 0x13, 0x45, 0x85, 0x4f, 0xe1, 0x80, 0xe9, 0x9b, 0xfe, 0x42, 0x57, 0x67, 0x36, 0xe8, 0xba,
|
||||
0xb4, 0xfe, 0x36, 0xc2, 0x57, 0xe0, 0xe7, 0xb4, 0x45, 0x3e, 0x23, 0xd8, 0xe7, 0xe2, 0x5c, 0x10,
|
||||
0xef, 0xea, 0xe9, 0xef, 0x0e, 0x1c, 0x57, 0xbe, 0xff, 0x6c, 0x6b, 0xaf, 0x35, 0x27, 0xf6, 0x3b,
|
||||
0xce, 0xa0, 0x5f, 0x37, 0x07, 0xef, 0xb2, 0x6c, 0x34, 0xc8, 0xa3, 0xab, 0x20, 0x61, 0x0b, 0x3f,
|
||||
0xc1, 0x51, 0xc3, 0xe6, 0xdc, 0xfd, 0xd0, 0xf3, 0x1d, 0xd8, 0xbc, 0x6f, 0x61, 0x0b, 0x57, 0xf0,
|
||||
0xe2, 0xde, 0xe4, 0xf1, 0x75, 0x13, 0xc9, 0x6d, 0x0b, 0xd2, 0x28, 0x7f, 0xfa, 0x01, 0x1e, 0x66,
|
||||
0x4e, 0x16, 0x61, 0x6a, 0xc6, 0xb7, 0xe0, 0x57, 0x93, 0xc5, 0x61, 0xc6, 0xd1, 0x90, 0xf5, 0xa8,
|
||||
0x9f, 0x01, 0xd5, 0x14, 0xc2, 0xd6, 0xbb, 0xde, 0xe7, 0x3d, 0xf7, 0xff, 0xfe, 0x09, 0x00, 0x00,
|
||||
0xff, 0xff, 0x8f, 0x23, 0xc4, 0x53, 0xee, 0x03, 0x00, 0x00,
|
||||
// 400 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x93, 0xcf, 0xaf, 0xd2, 0x40,
|
||||
0x10, 0xc7, 0x69, 0xcb, 0x13, 0xdf, 0xa4, 0x1a, 0xde, 0x3e, 0xf5, 0x35, 0xc5, 0x44, 0xec, 0xc1,
|
||||
0x34, 0xc6, 0x94, 0x84, 0xab, 0x27, 0x6c, 0xd1, 0x90, 0x98, 0x48, 0x16, 0xbc, 0x78, 0xdb, 0x2c,
|
||||
0x83, 0x36, 0xc6, 0x2e, 0xce, 0x6e, 0x4d, 0x3c, 0xf8, 0x4f, 0x78, 0xf5, 0x9f, 0x35, 0x2d, 0x2d,
|
||||
0x94, 0xa6, 0x3c, 0x6e, 0xf3, 0x83, 0xe5, 0xf3, 0x9d, 0xf9, 0x4e, 0xe1, 0x46, 0x8a, 0xc9, 0x8e,
|
||||
0x94, 0x51, 0x13, 0x29, 0xa2, 0x32, 0x60, 0xb6, 0x14, 0xfe, 0x53, 0xa9, 0x08, 0xeb, 0x86, 0x22,
|
||||
0xdc, 0xb7, 0x82, 0x1f, 0x70, 0xb7, 0xd0, 0x3a, 0xc7, 0x18, 0xc9, 0xa4, 0xdb, 0x54, 0x0a, 0x83,
|
||||
0x1c, 0x7f, 0xe6, 0xa8, 0x0d, 0x1b, 0x82, 0x23, 0x35, 0x79, 0xd6, 0xd8, 0x0a, 0x5d, 0x5e, 0x84,
|
||||
0xec, 0x15, 0x3c, 0x26, 0xfc, 0x9a, 0x6a, 0x43, 0xc2, 0xa4, 0x2a, 0x5b, 0x24, 0x9e, 0x3d, 0xb6,
|
||||
0x42, 0x87, 0xb7, 0xaa, 0xcc, 0x83, 0x81, 0xa2, 0x0d, 0xd2, 0x22, 0xf1, 0x9c, 0xf2, 0x07, 0x75,
|
||||
0x1a, 0x4c, 0x60, 0x54, 0xe2, 0x96, 0x84, 0xb2, 0x49, 0xd4, 0x3b, 0x95, 0x69, 0x2c, 0x90, 0xc9,
|
||||
0x9c, 0xd7, 0xc8, 0xcd, 0x9c, 0x07, 0x7f, 0x2d, 0x08, 0xdb, 0x02, 0xdf, 0x2b, 0x6a, 0xbf, 0x3f,
|
||||
0x28, 0x3e, 0x7d, 0xce, 0x18, 0xf4, 0x57, 0xf1, 0x5a, 0x7b, 0xf6, 0xd8, 0x09, 0x5d, 0xde, 0xd7,
|
||||
0xf1, 0x5a, 0x77, 0x4c, 0xe1, 0x5c, 0x9a, 0xa2, 0x7f, 0x3a, 0xc5, 0x1f, 0xb8, 0xfd, 0x80, 0x19,
|
||||
0x92, 0x30, 0xf8, 0x29, 0x5e, 0x2d, 0x6b, 0xbc, 0x07, 0x83, 0x42, 0xd4, 0x51, 0x42, 0x9d, 0xb2,
|
||||
0x67, 0xf0, 0x40, 0x1b, 0x61, 0x72, 0x5d, 0x2e, 0xec, 0x9a, 0x57, 0x59, 0x51, 0x27, 0x14, 0x5a,
|
||||
0x65, 0xa5, 0x84, 0x2b, 0x5e, 0x65, 0xec, 0x39, 0x5c, 0x13, 0xfe, 0x52, 0xdf, 0x71, 0x33, 0x33,
|
||||
0x15, 0xfc, 0x58, 0x08, 0x5e, 0x83, 0xbb, 0xc7, 0x56, 0x5b, 0xf3, 0xe1, 0x21, 0x55, 0x71, 0x05,
|
||||
0x3e, 0xe4, 0xd3, 0x7f, 0x36, 0x3c, 0x69, 0xac, 0x6e, 0x96, 0x9b, 0x6f, 0x8a, 0x52, 0xf3, 0x9b,
|
||||
0x25, 0x30, 0x6c, 0xef, 0x95, 0x8d, 0x22, 0x29, 0xa2, 0x33, 0xe7, 0xe0, 0xdf, 0x44, 0xe5, 0xd9,
|
||||
0x34, 0x3a, 0x41, 0x8f, 0x7d, 0x86, 0xdb, 0x0e, 0x3f, 0xef, 0xff, 0xa3, 0x17, 0x87, 0x66, 0xf7,
|
||||
0x15, 0x04, 0x3d, 0xb6, 0x85, 0x97, 0x17, 0x4d, 0x67, 0x6f, 0xba, 0x20, 0xe7, 0x6e, 0xa3, 0x53,
|
||||
0xfe, 0xf4, 0x23, 0x3c, 0x2a, 0x36, 0x59, 0x99, 0xa9, 0x88, 0xbd, 0x05, 0xb7, 0xe9, 0x2c, 0xbb,
|
||||
0x2b, 0x18, 0x1d, 0x5e, 0xfb, 0xc3, 0xa2, 0xd1, 0x74, 0x21, 0xe8, 0xbd, 0x1b, 0x7c, 0xb9, 0x2a,
|
||||
0x3f, 0xaa, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x09, 0x3d, 0x95, 0xee, 0x83, 0x03, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -27,14 +27,14 @@ message IssueCertificateRequest {
|
|||
}
|
||||
|
||||
message IssuePrecertificateResponse {
|
||||
optional core.Precertificate precert = 1;
|
||||
optional core.SCTFetchingConfig sctFetchingConfig = 2;
|
||||
optional bytes DER = 1;
|
||||
}
|
||||
|
||||
message IssueCertificateForPrecertificateRequest {
|
||||
optional IssueCertificateRequest issueReq = 1;
|
||||
optional bytes precertDER = 2;
|
||||
repeated bytes SCTs = 3;
|
||||
optional bytes DER = 1;
|
||||
repeated bytes SCTs = 2;
|
||||
optional int64 registrationID = 3;
|
||||
optional int64 orderID = 4;
|
||||
}
|
||||
|
||||
message GenerateOCSPRequest {
|
||||
|
|
|
@ -151,16 +151,6 @@ func newUpdater(
|
|||
failureBackoffFactor: config.SignFailureBackoffFactor,
|
||||
failureBackoffMax: config.SignFailureBackoffMax.Duration,
|
||||
},
|
||||
// The missing SCT loop doesn't need to know about failureBackoffFactor or
|
||||
// failureBackoffMax as it doesn't make any calls to the CA
|
||||
{
|
||||
clk: clk,
|
||||
stats: stats.NewScope("MissingSCTReceipts"),
|
||||
batchSize: config.MissingSCTBatchSize,
|
||||
tickDur: config.MissingSCTWindow.Duration,
|
||||
tickFunc: updater.missingReceiptsTick,
|
||||
name: "MissingSCTReceipts",
|
||||
},
|
||||
}
|
||||
if config.RevokedCertificateBatchSize != 0 &&
|
||||
config.RevokedCertificateWindow.Duration != 0 {
|
||||
|
@ -175,6 +165,18 @@ func newUpdater(
|
|||
failureBackoffMax: config.SignFailureBackoffMax.Duration,
|
||||
})
|
||||
}
|
||||
if !features.Enabled(features.EmbedSCTs) {
|
||||
// The missing SCT loop doesn't need to know about failureBackoffFactor or
|
||||
// failureBackoffMax as it doesn't make any calls to the CA
|
||||
updater.loops = append(updater.loops, &looper{
|
||||
clk: clk,
|
||||
stats: stats.NewScope("MissingSCTReceipts"),
|
||||
batchSize: config.MissingSCTBatchSize,
|
||||
tickDur: config.MissingSCTWindow.Duration,
|
||||
tickFunc: updater.missingReceiptsTick,
|
||||
name: "MissingSCTReceipts",
|
||||
})
|
||||
}
|
||||
|
||||
// TODO(#1050): Remove this gate and the nil ccu checks below
|
||||
if config.AkamaiBaseURL != "" {
|
||||
|
|
|
@ -586,9 +586,8 @@ type Order struct {
|
|||
Status AcmeStatus
|
||||
}
|
||||
|
||||
// SCTDER is a convenience type that helps differentiate what the
|
||||
// underlying byte slice contains
|
||||
type SCTDER []byte
|
||||
// SCTDER is a convenience type
|
||||
type SCTDERs [][]byte
|
||||
|
||||
// CertDER is a convenience type that helps differentiate what the
|
||||
// underlying byte slice contains
|
||||
|
|
|
@ -12,9 +12,6 @@ It has these top-level messages:
|
|||
Challenge
|
||||
ValidationRecord
|
||||
ProblemDetails
|
||||
Precertificate
|
||||
SCTFetchingConfig
|
||||
SCTFetchingLogSet
|
||||
Certificate
|
||||
Registration
|
||||
Authorization
|
||||
|
@ -212,57 +209,6 @@ func (m *ProblemDetails) GetHttpStatus() int32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
type Precertificate struct {
|
||||
Der []byte `protobuf:"bytes,1,opt,name=der" json:"der,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Precertificate) Reset() { *m = Precertificate{} }
|
||||
func (m *Precertificate) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Precertificate) ProtoMessage() {}
|
||||
func (*Precertificate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func (m *Precertificate) GetDer() []byte {
|
||||
if m != nil {
|
||||
return m.Der
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SCTFetchingConfig struct {
|
||||
LogSets []*SCTFetchingLogSet `protobuf:"bytes,1,rep,name=logSets" json:"logSets,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SCTFetchingConfig) Reset() { *m = SCTFetchingConfig{} }
|
||||
func (m *SCTFetchingConfig) String() string { return proto1.CompactTextString(m) }
|
||||
func (*SCTFetchingConfig) ProtoMessage() {}
|
||||
func (*SCTFetchingConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
|
||||
func (m *SCTFetchingConfig) GetLogSets() []*SCTFetchingLogSet {
|
||||
if m != nil {
|
||||
return m.LogSets
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SCTFetchingLogSet struct {
|
||||
LogURLs []string `protobuf:"bytes,1,rep,name=logURLs" json:"logURLs,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SCTFetchingLogSet) Reset() { *m = SCTFetchingLogSet{} }
|
||||
func (m *SCTFetchingLogSet) String() string { return proto1.CompactTextString(m) }
|
||||
func (*SCTFetchingLogSet) ProtoMessage() {}
|
||||
func (*SCTFetchingLogSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||
|
||||
func (m *SCTFetchingLogSet) GetLogURLs() []string {
|
||||
if m != nil {
|
||||
return m.LogURLs
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Certificate struct {
|
||||
RegistrationID *int64 `protobuf:"varint,1,opt,name=registrationID" json:"registrationID,omitempty"`
|
||||
Serial *string `protobuf:"bytes,2,opt,name=serial" json:"serial,omitempty"`
|
||||
|
@ -276,7 +222,7 @@ type Certificate struct {
|
|||
func (m *Certificate) Reset() { *m = Certificate{} }
|
||||
func (m *Certificate) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Certificate) ProtoMessage() {}
|
||||
func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
|
||||
func (*Certificate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
|
||||
|
||||
func (m *Certificate) GetRegistrationID() int64 {
|
||||
if m != nil && m.RegistrationID != nil {
|
||||
|
@ -335,7 +281,7 @@ type Registration struct {
|
|||
func (m *Registration) Reset() { *m = Registration{} }
|
||||
func (m *Registration) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Registration) ProtoMessage() {}
|
||||
func (*Registration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
||||
func (*Registration) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
|
||||
|
||||
func (m *Registration) GetId() int64 {
|
||||
if m != nil && m.Id != nil {
|
||||
|
@ -407,7 +353,7 @@ type Authorization struct {
|
|||
func (m *Authorization) Reset() { *m = Authorization{} }
|
||||
func (m *Authorization) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Authorization) ProtoMessage() {}
|
||||
func (*Authorization) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
|
||||
func (*Authorization) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
|
||||
|
||||
func (m *Authorization) GetId() string {
|
||||
if m != nil && m.Id != nil {
|
||||
|
@ -475,7 +421,7 @@ type Order struct {
|
|||
func (m *Order) Reset() { *m = Order{} }
|
||||
func (m *Order) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Order) ProtoMessage() {}
|
||||
func (*Order) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
|
||||
func (*Order) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
|
||||
|
||||
func (m *Order) GetId() int64 {
|
||||
if m != nil && m.Id != nil {
|
||||
|
@ -554,15 +500,12 @@ type Empty struct {
|
|||
func (m *Empty) Reset() { *m = Empty{} }
|
||||
func (m *Empty) String() string { return proto1.CompactTextString(m) }
|
||||
func (*Empty) ProtoMessage() {}
|
||||
func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
|
||||
func (*Empty) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
|
||||
|
||||
func init() {
|
||||
proto1.RegisterType((*Challenge)(nil), "core.Challenge")
|
||||
proto1.RegisterType((*ValidationRecord)(nil), "core.ValidationRecord")
|
||||
proto1.RegisterType((*ProblemDetails)(nil), "core.ProblemDetails")
|
||||
proto1.RegisterType((*Precertificate)(nil), "core.Precertificate")
|
||||
proto1.RegisterType((*SCTFetchingConfig)(nil), "core.SCTFetchingConfig")
|
||||
proto1.RegisterType((*SCTFetchingLogSet)(nil), "core.SCTFetchingLogSet")
|
||||
proto1.RegisterType((*Certificate)(nil), "core.Certificate")
|
||||
proto1.RegisterType((*Registration)(nil), "core.Registration")
|
||||
proto1.RegisterType((*Authorization)(nil), "core.Authorization")
|
||||
|
@ -573,55 +516,51 @@ func init() {
|
|||
func init() { proto1.RegisterFile("core/proto/core.proto", fileDescriptor0) }
|
||||
|
||||
var fileDescriptor0 = []byte{
|
||||
// 795 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x51, 0x8e, 0xdb, 0x36,
|
||||
0x10, 0x85, 0x2c, 0x2b, 0x5e, 0x8d, 0x55, 0xc7, 0x4b, 0x6c, 0x53, 0xa1, 0x28, 0x02, 0x41, 0x1f,
|
||||
0x81, 0x10, 0xb4, 0x59, 0x34, 0x37, 0x48, 0xbd, 0x0d, 0x10, 0x20, 0x40, 0x0d, 0x7a, 0xd3, 0x8f,
|
||||
0xfe, 0x69, 0xa5, 0x89, 0xcc, 0xae, 0x2c, 0x1a, 0x24, 0x1d, 0xd4, 0xbd, 0x43, 0x0f, 0xd2, 0xc3,
|
||||
0xf4, 0x1a, 0xfd, 0xec, 0x19, 0x0a, 0x0e, 0x65, 0x9b, 0xb2, 0x53, 0xf4, 0x6f, 0xde, 0xe3, 0x88,
|
||||
0x9c, 0x99, 0x37, 0x33, 0x82, 0x2f, 0x2b, 0xa9, 0xf0, 0x76, 0xab, 0xa4, 0x91, 0xb7, 0xd6, 0x7c,
|
||||
0x45, 0x26, 0x1b, 0x5b, 0x3b, 0xff, 0x63, 0x04, 0xf1, 0x62, 0x5d, 0xb6, 0x2d, 0x76, 0x0d, 0xb2,
|
||||
0x19, 0x8c, 0x44, 0x9d, 0x06, 0x59, 0x50, 0x84, 0x7c, 0x24, 0x6a, 0xc6, 0x60, 0x6c, 0xf6, 0x5b,
|
||||
0x4c, 0x47, 0x59, 0x50, 0xc4, 0x9c, 0x6c, 0xf6, 0x0c, 0x9e, 0x68, 0x53, 0x9a, 0x9d, 0x4e, 0x9f,
|
||||
0x10, 0xdb, 0x23, 0x36, 0x87, 0x70, 0xa7, 0x44, 0x1a, 0x13, 0x69, 0x4d, 0x76, 0x03, 0x91, 0x91,
|
||||
0x8f, 0xd8, 0xa5, 0x21, 0x71, 0x0e, 0xb0, 0x97, 0x30, 0x7f, 0xc4, 0xfd, 0x9b, 0x9d, 0x59, 0x4b,
|
||||
0x25, 0x7e, 0x2f, 0x8d, 0x90, 0x5d, 0x1a, 0x91, 0xc3, 0x05, 0xcf, 0xee, 0xe0, 0xfa, 0x53, 0xd9,
|
||||
0x8a, 0x9a, 0x90, 0xc2, 0x4a, 0xaa, 0x5a, 0xa7, 0x90, 0x85, 0xc5, 0xf4, 0xf5, 0xb3, 0x57, 0x94,
|
||||
0xcb, 0xcf, 0xc7, 0x63, 0x4e, 0xc7, 0xfc, 0xf2, 0x03, 0xf6, 0x12, 0x22, 0x54, 0x4a, 0xaa, 0x74,
|
||||
0x92, 0x05, 0xc5, 0xf4, 0xf5, 0x8d, 0xfb, 0x72, 0xa9, 0xe4, 0x43, 0x8b, 0x9b, 0x3b, 0x34, 0xa5,
|
||||
0x68, 0x35, 0x77, 0x2e, 0xf9, 0x3f, 0x01, 0xcc, 0xcf, 0xef, 0x64, 0x5f, 0xc3, 0xd5, 0x5a, 0x6a,
|
||||
0xd3, 0x95, 0x1b, 0xa4, 0xe2, 0xc4, 0xfc, 0x88, 0x6d, 0x89, 0xb6, 0x52, 0x99, 0x43, 0x89, 0xac,
|
||||
0xcd, 0xbe, 0x85, 0xeb, 0xb2, 0xae, 0x15, 0x6a, 0x8d, 0x9a, 0xa3, 0x96, 0xed, 0x27, 0xac, 0xd3,
|
||||
0x30, 0x0b, 0x8b, 0x84, 0x5f, 0x1e, 0xb0, 0x0c, 0xa6, 0x3d, 0xf9, 0x41, 0x63, 0x9d, 0x8e, 0xb3,
|
||||
0xa0, 0x48, 0xb8, 0x4f, 0x91, 0x87, 0xab, 0x8b, 0x11, 0xa8, 0xd3, 0x28, 0x0b, 0x8b, 0x98, 0xfb,
|
||||
0x94, 0x2b, 0x7e, 0xdb, 0x2b, 0x62, 0x4d, 0xf6, 0x02, 0x66, 0xc7, 0xa7, 0xee, 0x95, 0xc0, 0x3a,
|
||||
0x9d, 0x50, 0x00, 0x67, 0x6c, 0xfe, 0x2b, 0xcc, 0x86, 0x95, 0xb0, 0xaf, 0x6d, 0x1d, 0x73, 0x6f,
|
||||
0xb5, 0x77, 0x09, 0xfb, 0x94, 0x6d, 0x81, 0x9a, 0x9c, 0xfb, 0xac, 0x7b, 0xc4, 0x9e, 0x03, 0xac,
|
||||
0x8d, 0xd9, 0xae, 0x5c, 0x7b, 0x58, 0xd5, 0x23, 0xee, 0x31, 0x79, 0x6e, 0xdf, 0xc2, 0x0a, 0x95,
|
||||
0x11, 0x1f, 0x45, 0x55, 0x1a, 0xb4, 0x71, 0xd7, 0xa8, 0xe8, 0x8d, 0x84, 0x5b, 0x33, 0x7f, 0x0b,
|
||||
0xd7, 0xab, 0xc5, 0xfd, 0x5b, 0x34, 0xd5, 0x5a, 0x74, 0xcd, 0x42, 0x76, 0x1f, 0x45, 0xc3, 0xbe,
|
||||
0x87, 0x49, 0x2b, 0x9b, 0x15, 0x1a, 0x9d, 0x06, 0xa4, 0xfe, 0x57, 0x4e, 0x43, 0xcf, 0xf3, 0x3d,
|
||||
0x9d, 0xf3, 0x83, 0x5f, 0xfe, 0xdd, 0xe0, 0x1e, 0x77, 0xca, 0x52, 0xba, 0xe7, 0x03, 0x7f, 0xef,
|
||||
0xee, 0x89, 0xf9, 0x01, 0xe6, 0x7f, 0x06, 0x30, 0x5d, 0x78, 0x81, 0xbd, 0x80, 0x99, 0xc2, 0x46,
|
||||
0x68, 0xa3, 0xa8, 0x11, 0xde, 0xdd, 0xf5, 0x53, 0x71, 0xc6, 0xd2, 0x34, 0xa0, 0x12, 0xe5, 0xb1,
|
||||
0x14, 0x0e, 0x51, 0x89, 0x44, 0x83, 0xda, 0xf4, 0xcd, 0xdf, 0xa3, 0x43, 0xc2, 0xe3, 0x63, 0xc2,
|
||||
0xd6, 0x53, 0x68, 0xbd, 0xc3, 0x9a, 0xa6, 0x20, 0xe4, 0x3d, 0xb2, 0xb1, 0xe2, 0x6f, 0x5b, 0xa1,
|
||||
0xd0, 0x0d, 0x5a, 0xc8, 0x0f, 0x30, 0xff, 0x3b, 0x80, 0x84, 0x7b, 0x61, 0x5c, 0x8c, 0xed, 0x1c,
|
||||
0xc2, 0x47, 0xdc, 0x53, 0x44, 0x09, 0xb7, 0xa6, 0xbd, 0xac, 0x92, 0x9d, 0x29, 0x2b, 0x43, 0x7d,
|
||||
0x18, 0xf3, 0x03, 0x64, 0x05, 0x3c, 0xed, 0x4d, 0xbd, 0x54, 0xa8, 0xb1, 0x33, 0x14, 0xdc, 0x15,
|
||||
0x3f, 0xa7, 0xd9, 0x37, 0x10, 0x97, 0x8d, 0x42, 0xdc, 0x58, 0x1f, 0x37, 0xb1, 0x27, 0xc2, 0x9e,
|
||||
0x8a, 0x4e, 0x18, 0x51, 0xb6, 0xef, 0x96, 0x14, 0x70, 0xc2, 0x4f, 0x84, 0x3d, 0xad, 0x14, 0x96,
|
||||
0x06, 0xeb, 0x37, 0x86, 0xc6, 0x30, 0xe4, 0x27, 0xc2, 0x5b, 0x29, 0x57, 0xfe, 0x4a, 0xb1, 0xc3,
|
||||
0xf8, 0xc5, 0x70, 0x21, 0x9c, 0x32, 0x8d, 0x29, 0xd3, 0xe7, 0x00, 0xa2, 0xc6, 0xce, 0xca, 0x86,
|
||||
0xaa, 0x97, 0xc0, 0x63, 0x3e, 0x23, 0x63, 0xf8, 0x9f, 0x32, 0xba, 0x08, 0xc6, 0x83, 0xa5, 0xe6,
|
||||
0x89, 0x10, 0x0d, 0x44, 0x60, 0xb7, 0x00, 0xd5, 0x61, 0x6f, 0x5a, 0x85, 0x6c, 0x57, 0x3e, 0x75,
|
||||
0x5d, 0x79, 0xdc, 0xa7, 0xdc, 0x73, 0x61, 0x39, 0x24, 0x95, 0xdc, 0x3c, 0x88, 0x8e, 0xde, 0xd4,
|
||||
0x54, 0x85, 0x84, 0x0f, 0xb8, 0xfc, 0xaf, 0x11, 0x44, 0x3f, 0x29, 0xdb, 0x15, 0xe7, 0x92, 0x5e,
|
||||
0x26, 0x32, 0xfa, 0x6c, 0x22, 0x5e, 0xc0, 0xe1, 0x30, 0xe0, 0xe3, 0x16, 0x1c, 0xff, 0xef, 0x16,
|
||||
0xb4, 0x0b, 0xcc, 0x9b, 0xd2, 0x95, 0x6b, 0x70, 0x27, 0xf9, 0xe5, 0x01, 0xad, 0x1a, 0x5f, 0x25,
|
||||
0x57, 0x8e, 0x98, 0x9f, 0xb1, 0x5e, 0x91, 0x27, 0x83, 0x22, 0xdf, 0x40, 0x64, 0x57, 0xa9, 0x55,
|
||||
0xdf, 0x7e, 0xe6, 0x80, 0x6d, 0xcc, 0x07, 0x6c, 0xca, 0x6e, 0xa9, 0x64, 0x85, 0x5a, 0x8b, 0xae,
|
||||
0xa1, 0x7f, 0xcb, 0x15, 0x3f, 0xa7, 0xa9, 0xb9, 0x5d, 0x2f, 0xa5, 0xe0, 0x72, 0xee, 0x61, 0x3e,
|
||||
0x81, 0xe8, 0xc7, 0xcd, 0xd6, 0xec, 0x7f, 0x98, 0xfc, 0x12, 0xd1, 0x5f, 0xef, 0xdf, 0x00, 0x00,
|
||||
0x00, 0xff, 0xff, 0x1d, 0x63, 0xb4, 0xfe, 0x0d, 0x07, 0x00, 0x00,
|
||||
// 723 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x55, 0x41, 0x6e, 0xdb, 0x3a,
|
||||
0x10, 0x85, 0x2c, 0x2b, 0xb6, 0xc6, 0xfe, 0x89, 0x43, 0xe4, 0x07, 0xc2, 0xc7, 0x47, 0x20, 0x68,
|
||||
0x51, 0x08, 0x41, 0x91, 0x00, 0xb9, 0x41, 0x9a, 0x74, 0x91, 0x55, 0x0d, 0x26, 0xed, 0xa2, 0x3b,
|
||||
0x45, 0x9a, 0xda, 0x6c, 0x64, 0xc9, 0x20, 0xe9, 0xa0, 0xee, 0x1d, 0x7a, 0x90, 0x1e, 0xa6, 0xd7,
|
||||
0xe8, 0xb2, 0x67, 0x28, 0x66, 0x28, 0xdb, 0xb2, 0x9d, 0xa2, 0xbb, 0x99, 0x47, 0xca, 0x9c, 0x79,
|
||||
0xef, 0xcd, 0x18, 0xfe, 0xcd, 0x6b, 0x8d, 0x97, 0x73, 0x5d, 0xdb, 0xfa, 0x92, 0xc2, 0x0b, 0x0e,
|
||||
0x45, 0x97, 0xe2, 0xe4, 0x5b, 0x07, 0xc2, 0x9b, 0x69, 0x56, 0x96, 0x58, 0x4d, 0x50, 0x1c, 0x42,
|
||||
0x47, 0x15, 0x91, 0x17, 0x7b, 0xa9, 0x2f, 0x3b, 0xaa, 0x10, 0x02, 0xba, 0x76, 0x39, 0xc7, 0xa8,
|
||||
0x13, 0x7b, 0x69, 0x28, 0x39, 0x16, 0xa7, 0x70, 0x60, 0x6c, 0x66, 0x17, 0x26, 0x3a, 0x60, 0xb4,
|
||||
0xc9, 0xc4, 0x08, 0xfc, 0x85, 0x56, 0x51, 0xc8, 0x20, 0x85, 0xe2, 0x04, 0x02, 0x5b, 0x3f, 0x61,
|
||||
0x15, 0xf9, 0x8c, 0xb9, 0x44, 0x9c, 0xc3, 0xe8, 0x09, 0x97, 0xd7, 0x0b, 0x3b, 0xad, 0xb5, 0xfa,
|
||||
0x9a, 0x59, 0x55, 0x57, 0x51, 0xc0, 0x17, 0xf6, 0x70, 0x71, 0x0b, 0xc7, 0xcf, 0x59, 0xa9, 0x0a,
|
||||
0xce, 0x34, 0xe6, 0xb5, 0x2e, 0x4c, 0x04, 0xb1, 0x9f, 0x0e, 0xae, 0x4e, 0x2f, 0xb8, 0x97, 0x0f,
|
||||
0xeb, 0x63, 0xc9, 0xc7, 0x72, 0xff, 0x03, 0x71, 0x0e, 0x01, 0x6a, 0x5d, 0xeb, 0xa8, 0x17, 0x7b,
|
||||
0xe9, 0xe0, 0xea, 0xc4, 0x7d, 0x39, 0xd6, 0xf5, 0x63, 0x89, 0xb3, 0x5b, 0xb4, 0x99, 0x2a, 0x8d,
|
||||
0x74, 0x57, 0x92, 0x5f, 0x1e, 0x8c, 0x76, 0x7f, 0x53, 0xfc, 0x07, 0xfd, 0x69, 0x6d, 0x6c, 0x95,
|
||||
0xcd, 0x90, 0xc9, 0x09, 0xe5, 0x3a, 0x27, 0x8a, 0xe6, 0xb5, 0xb6, 0x2b, 0x8a, 0x28, 0x16, 0xaf,
|
||||
0xe1, 0x38, 0x2b, 0x0a, 0x8d, 0xc6, 0xa0, 0x91, 0x68, 0xea, 0xf2, 0x19, 0x8b, 0xc8, 0x8f, 0xfd,
|
||||
0x74, 0x28, 0xf7, 0x0f, 0x44, 0x0c, 0x83, 0x06, 0x7c, 0x6f, 0xb0, 0x88, 0xba, 0xb1, 0x97, 0x0e,
|
||||
0x65, 0x1b, 0xe2, 0x1b, 0x8e, 0x17, 0xab, 0xd0, 0x44, 0x41, 0xec, 0xa7, 0xa1, 0x6c, 0x43, 0x8e,
|
||||
0xfc, 0xb2, 0x51, 0x84, 0x42, 0xf1, 0x0a, 0x0e, 0xd7, 0x4f, 0x3d, 0x68, 0x85, 0x45, 0xd4, 0xe3,
|
||||
0x02, 0x76, 0xd0, 0xe4, 0x33, 0x1c, 0x6e, 0x33, 0x41, 0xaf, 0xcd, 0x1d, 0xf2, 0x40, 0xda, 0xbb,
|
||||
0x86, 0xdb, 0x10, 0x59, 0xa0, 0xe0, 0xcb, 0x4d, 0xd7, 0x4d, 0x26, 0xce, 0x00, 0xa6, 0xd6, 0xce,
|
||||
0xef, 0x9d, 0x3d, 0x48, 0xf5, 0x40, 0xb6, 0x90, 0xe4, 0xbb, 0x07, 0x83, 0x1b, 0xd4, 0x56, 0x7d,
|
||||
0x52, 0x79, 0x66, 0x91, 0x6a, 0xd4, 0x38, 0x51, 0xc6, 0x6a, 0x66, 0xfb, 0xee, 0xb6, 0xb1, 0xde,
|
||||
0x0e, 0xca, 0x96, 0x43, 0xad, 0xb2, 0xf5, 0x7b, 0x2e, 0xe3, 0x3a, 0xd4, 0x04, 0x8d, 0x6d, 0x1c,
|
||||
0xd6, 0x64, 0xc4, 0x46, 0x81, 0xba, 0x61, 0x92, 0x42, 0xba, 0xa9, 0x8c, 0x59, 0x60, 0xc1, 0x56,
|
||||
0xf3, 0x65, 0x93, 0x89, 0x08, 0x7a, 0xf8, 0x65, 0xae, 0x34, 0x3a, 0x37, 0xfb, 0x72, 0x95, 0x26,
|
||||
0x3f, 0x3d, 0x18, 0xca, 0x56, 0x19, 0x7b, 0xb3, 0x31, 0x02, 0xff, 0x09, 0x97, 0x5c, 0xd1, 0x50,
|
||||
0x52, 0x48, 0x3f, 0x96, 0xd7, 0x95, 0xcd, 0x72, 0xcb, 0x62, 0x87, 0x72, 0x95, 0x8a, 0x14, 0x8e,
|
||||
0x9a, 0xd0, 0x8c, 0x35, 0x1a, 0xac, 0x2c, 0x17, 0xd7, 0x97, 0xbb, 0xb0, 0xf8, 0x1f, 0xc2, 0x6c,
|
||||
0xa2, 0x11, 0x67, 0x74, 0xc7, 0x8d, 0xc5, 0x06, 0xa0, 0x53, 0x55, 0x29, 0xab, 0xb2, 0xf2, 0x6e,
|
||||
0xcc, 0x05, 0x0f, 0xe5, 0x06, 0xa0, 0xd3, 0x5c, 0x63, 0x66, 0xb1, 0xb8, 0xb6, 0xec, 0x75, 0x5f,
|
||||
0x6e, 0x80, 0xd6, 0xdc, 0xf6, 0xdb, 0x73, 0x4b, 0x8e, 0xff, 0x67, 0x7b, 0xea, 0x36, 0x9d, 0x86,
|
||||
0xdc, 0xe9, 0x19, 0x80, 0x2a, 0xb0, 0x22, 0xd9, 0x50, 0x37, 0x12, 0xb4, 0x90, 0x17, 0x64, 0xf4,
|
||||
0xff, 0x28, 0xa3, 0xab, 0xa0, 0xbb, 0xb5, 0x39, 0x5a, 0x22, 0x04, 0x5b, 0x22, 0x88, 0x4b, 0x80,
|
||||
0x7c, 0xb5, 0x9c, 0x48, 0x21, 0x1a, 0xfc, 0x23, 0x37, 0xbe, 0xeb, 0xa5, 0x25, 0x5b, 0x57, 0x44,
|
||||
0x02, 0xc3, 0xbc, 0x9e, 0x3d, 0xaa, 0x8a, 0xdf, 0x34, 0xcc, 0xc2, 0x50, 0x6e, 0x61, 0xc9, 0x8f,
|
||||
0x0e, 0x04, 0xef, 0x34, 0xb9, 0x62, 0x57, 0xd2, 0xfd, 0x46, 0x3a, 0x2f, 0x36, 0xd2, 0x2a, 0xd8,
|
||||
0xdf, 0x2e, 0x78, 0xbd, 0x6a, 0xba, 0x7f, 0x5d, 0x35, 0xb4, 0x25, 0xf2, 0xcd, 0x30, 0xdc, 0x3b,
|
||||
0x83, 0x3b, 0xc9, 0xf7, 0x0f, 0x78, 0x9e, 0xdb, 0x2a, 0x39, 0x3a, 0x42, 0xb9, 0x83, 0xb6, 0x48,
|
||||
0xee, 0x6d, 0x91, 0x7c, 0x02, 0x01, 0xed, 0x2b, 0x52, 0x9f, 0x3e, 0x73, 0x09, 0x19, 0xf3, 0x11,
|
||||
0x27, 0x59, 0x35, 0xd6, 0x75, 0x8e, 0xc6, 0xa8, 0x6a, 0xc2, 0x0b, 0xbc, 0x2f, 0x77, 0x61, 0x36,
|
||||
0xb7, 0xf3, 0x52, 0x04, 0xae, 0xe7, 0x26, 0x4d, 0x7a, 0x10, 0xbc, 0x9d, 0xcd, 0xed, 0xf2, 0x4d,
|
||||
0xef, 0x63, 0xc0, 0x7f, 0x2d, 0xbf, 0x03, 0x00, 0x00, 0xff, 0xff, 0xf6, 0x75, 0x46, 0x28, 0x72,
|
||||
0x06, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -34,18 +34,6 @@ message ProblemDetails {
|
|||
optional int32 httpStatus = 3;
|
||||
}
|
||||
|
||||
message Precertificate {
|
||||
optional bytes der = 1;
|
||||
}
|
||||
|
||||
message SCTFetchingConfig {
|
||||
repeated SCTFetchingLogSet logSets = 1;
|
||||
}
|
||||
|
||||
message SCTFetchingLogSet {
|
||||
repeated string logURLs = 1;
|
||||
}
|
||||
|
||||
message Certificate {
|
||||
optional int64 registrationID = 1;
|
||||
optional string serial = 2;
|
||||
|
|
|
@ -33,7 +33,7 @@ func New(pub core.Publisher, groups []cmd.CTGroup, informational []cmd.LogDescri
|
|||
}
|
||||
|
||||
type result struct {
|
||||
sct core.SCTDER
|
||||
sct []byte
|
||||
err error
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ type result struct {
|
|||
// once it has the first SCT it cancels all of the other submissions and returns.
|
||||
// It allows up to len(group)-1 of the submissions to fail as we only care about
|
||||
// getting a single SCT.
|
||||
func (ctp *CTPolicy) race(ctx context.Context, cert core.CertDER, group cmd.CTGroup) (core.SCTDER, error) {
|
||||
func (ctp *CTPolicy) race(ctx context.Context, cert core.CertDER, group cmd.CTGroup) ([]byte, error) {
|
||||
results := make(chan result, len(group.Logs))
|
||||
var subCtx context.Context
|
||||
var cancel func()
|
||||
|
@ -51,12 +51,14 @@ func (ctp *CTPolicy) race(ctx context.Context, cert core.CertDER, group cmd.CTGr
|
|||
subCtx, cancel = ctx, func() {}
|
||||
}
|
||||
defer cancel()
|
||||
isPrecert := features.Enabled(features.EmbedSCTs)
|
||||
for _, l := range group.Logs {
|
||||
go func(l cmd.LogDescription) {
|
||||
sct, err := ctp.pub.SubmitToSingleCTWithResult(subCtx, &pubpb.Request{
|
||||
LogURL: &l.URI,
|
||||
LogPublicKey: &l.Key,
|
||||
Der: cert,
|
||||
Precert: &isPrecert,
|
||||
})
|
||||
if err != nil {
|
||||
// Only log the error if it is not a result of canceling subCtx
|
||||
|
@ -90,7 +92,7 @@ func (ctp *CTPolicy) race(ctx context.Context, cert core.CertDER, group cmd.CTGr
|
|||
|
||||
// GetSCTs attempts to retrieve a SCT from each configured grouping of logs and returns
|
||||
// the set of SCTs to the caller.
|
||||
func (ctp *CTPolicy) GetSCTs(ctx context.Context, cert core.CertDER) ([]core.SCTDER, error) {
|
||||
func (ctp *CTPolicy) GetSCTs(ctx context.Context, cert core.CertDER) (core.SCTDERs, error) {
|
||||
results := make(chan result, len(ctp.groups))
|
||||
var subCtx context.Context
|
||||
var cancel func()
|
||||
|
@ -120,7 +122,7 @@ func (ctp *CTPolicy) GetSCTs(ctx context.Context, cert core.CertDER) ([]core.SCT
|
|||
}(log)
|
||||
}
|
||||
|
||||
var ret []core.SCTDER
|
||||
var ret core.SCTDERs
|
||||
for i := 0; i < len(ctp.groups); i++ {
|
||||
res := <-results
|
||||
// If any one group fails to get a SCT then we fail out immediately
|
||||
|
|
|
@ -43,7 +43,7 @@ func TestGetSCTs(t *testing.T) {
|
|||
mock core.Publisher
|
||||
groups []cmd.CTGroup
|
||||
ctx context.Context
|
||||
result []core.SCTDER
|
||||
result core.SCTDERs
|
||||
errRegexp *regexp.Regexp
|
||||
}{
|
||||
{
|
||||
|
@ -66,7 +66,7 @@ func TestGetSCTs(t *testing.T) {
|
|||
},
|
||||
},
|
||||
ctx: context.Background(),
|
||||
result: []core.SCTDER{[]byte{0}, []byte{0}},
|
||||
result: core.SCTDERs{[]byte{0}, []byte{0}},
|
||||
},
|
||||
{
|
||||
name: "basic failure case",
|
||||
|
|
|
@ -4,9 +4,9 @@ package features
|
|||
|
||||
import "strconv"
|
||||
|
||||
const _FeatureFlag_name = "unusedUseAIAIssuerURLReusePendingAuthzCountCertificatesExactIPv6FirstAllowRenewalFirstRLWildcardDomainsForceConsistentStatusEnforceChallengeDisableTLSSNIRevalidationCancelCTSubmissionsVAChecksGSBEnforceV2ContentType"
|
||||
const _FeatureFlag_name = "unusedUseAIAIssuerURLReusePendingAuthzCountCertificatesExactIPv6FirstAllowRenewalFirstRLWildcardDomainsForceConsistentStatusEnforceChallengeDisableTLSSNIRevalidationEmbedSCTsCancelCTSubmissionsVAChecksGSBEnforceV2ContentType"
|
||||
|
||||
var _FeatureFlag_index = [...]uint8{0, 6, 21, 38, 60, 69, 88, 103, 124, 147, 165, 184, 195, 215}
|
||||
var _FeatureFlag_index = [...]uint8{0, 6, 21, 38, 60, 69, 88, 103, 124, 147, 165, 174, 193, 204, 224}
|
||||
|
||||
func (i FeatureFlag) String() string {
|
||||
if i < 0 || i >= FeatureFlag(len(_FeatureFlag_index)-1) {
|
||||
|
|
|
@ -26,6 +26,7 @@ const (
|
|||
EnforceChallengeDisable
|
||||
// Allow TLS-SNI in new-authz that are revalidating for previous issuance
|
||||
TLSSNIRevalidation
|
||||
EmbedSCTs
|
||||
CancelCTSubmissions
|
||||
VAChecksGSB
|
||||
// Return errors to ACMEv2 clients that do not send the correct JWS
|
||||
|
@ -44,6 +45,7 @@ var features = map[FeatureFlag]bool{
|
|||
WildcardDomains: false,
|
||||
EnforceChallengeDisable: false, // deprecated
|
||||
TLSSNIRevalidation: false,
|
||||
EmbedSCTs: false,
|
||||
CancelCTSubmissions: true,
|
||||
VAChecksGSB: false,
|
||||
EnforceV2ContentType: false,
|
||||
|
|
|
@ -41,14 +41,21 @@ func (cac CertificateAuthorityClientWrapper) IssueCertificate(ctx context.Contex
|
|||
if err != nil {
|
||||
return core.Certificate{}, err
|
||||
}
|
||||
return pbToCert(res), nil
|
||||
return pbToCert(res)
|
||||
}
|
||||
|
||||
func (cac CertificateAuthorityClientWrapper) IssuePrecertificate(ctx context.Context, issueReq *caPB.IssueCertificateRequest) (*caPB.IssuePrecertificateResponse, error) {
|
||||
if cac.inner == nil {
|
||||
return nil, errors.New("this CA client does not support issuing precertificates")
|
||||
}
|
||||
return cac.inner.IssuePrecertificate(ctx, issueReq)
|
||||
resp, err := cac.inner.IssuePrecertificate(ctx, issueReq)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.DER == nil {
|
||||
return nil, errIncompleteResponse
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (cac CertificateAuthorityClientWrapper) IssueCertificateForPrecertificate(ctx context.Context, req *caPB.IssueCertificateForPrecertificateRequest) (core.Certificate, error) {
|
||||
|
@ -59,7 +66,7 @@ func (cac CertificateAuthorityClientWrapper) IssueCertificateForPrecertificate(c
|
|||
if err != nil {
|
||||
return core.Certificate{}, err
|
||||
}
|
||||
return pbToCert(res), nil
|
||||
return pbToCert(res)
|
||||
}
|
||||
|
||||
func (cac CertificateAuthorityClientWrapper) GenerateOCSP(ctx context.Context, ocspReq core.OCSPSigningRequest) ([]byte, error) {
|
||||
|
@ -98,10 +105,23 @@ func (cas *CertificateAuthorityServerWrapper) IssueCertificate(ctx context.Conte
|
|||
}
|
||||
|
||||
func (cas *CertificateAuthorityServerWrapper) IssuePrecertificate(ctx context.Context, request *caPB.IssueCertificateRequest) (*caPB.IssuePrecertificateResponse, error) {
|
||||
return cas.inner.IssuePrecertificate(ctx, request)
|
||||
if request == nil || request.Csr == nil || request.OrderID == nil || request.RegistrationID == nil {
|
||||
return nil, errIncompleteRequest
|
||||
}
|
||||
resp, err := cas.inner.IssuePrecertificate(ctx, request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.DER == nil {
|
||||
return nil, errIncompleteRequest
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (cas *CertificateAuthorityServerWrapper) IssueCertificateForPrecertificate(ctx context.Context, req *caPB.IssueCertificateForPrecertificateRequest) (*corepb.Certificate, error) {
|
||||
if req == nil || req.DER == nil || req.OrderID == nil || req.RegistrationID == nil || req.SCTs == nil {
|
||||
return nil, errIncompleteRequest
|
||||
}
|
||||
cert, err := cas.inner.IssueCertificateForPrecertificate(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -428,10 +428,6 @@ func authorizationValid(authz *corepb.Authorization) bool {
|
|||
return !(authz.Id == nil || authz.Identifier == nil || authz.RegistrationID == nil || authz.Status == nil || authz.Expires == nil)
|
||||
}
|
||||
|
||||
func certificateValid(cert *corepb.Certificate) bool {
|
||||
return !(cert.RegistrationID == nil || cert.Serial == nil || cert.Digest == nil || cert.Der == nil || cert.Issued == nil || cert.Expires == nil)
|
||||
}
|
||||
|
||||
func sctToPB(sct core.SignedCertificateTimestamp) *sapb.SignedCertificateTimestamp {
|
||||
id := int64(sct.ID)
|
||||
version := int64(sct.SCTVersion)
|
||||
|
@ -475,7 +471,10 @@ func certToPB(cert core.Certificate) *corepb.Certificate {
|
|||
}
|
||||
}
|
||||
|
||||
func pbToCert(pb *corepb.Certificate) core.Certificate {
|
||||
func pbToCert(pb *corepb.Certificate) (core.Certificate, error) {
|
||||
if pb == nil || pb.RegistrationID == nil || pb.Serial == nil || pb.Digest == nil || pb.Der == nil || pb.Issued == nil || pb.Expires == nil {
|
||||
return core.Certificate{}, errIncompleteResponse
|
||||
}
|
||||
return core.Certificate{
|
||||
RegistrationID: *pb.RegistrationID,
|
||||
Serial: *pb.Serial,
|
||||
|
@ -483,5 +482,5 @@ func pbToCert(pb *corepb.Certificate) core.Certificate {
|
|||
DER: pb.Der,
|
||||
Issued: time.Unix(0, *pb.Issued),
|
||||
Expires: time.Unix(0, *pb.Expires),
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -330,7 +330,7 @@ func TestCert(t *testing.T) {
|
|||
}
|
||||
|
||||
certPB := certToPB(cert)
|
||||
outCert := pbToCert(certPB)
|
||||
outCert, _ := pbToCert(certPB)
|
||||
|
||||
test.AssertDeepEquals(t, cert, outCert)
|
||||
}
|
||||
|
|
|
@ -69,11 +69,7 @@ func (rac RegistrationAuthorityClientWrapper) NewCertificate(ctx context.Context
|
|||
return core.Certificate{}, err
|
||||
}
|
||||
|
||||
if response == nil || !certificateValid(response) {
|
||||
return core.Certificate{}, errIncompleteResponse
|
||||
}
|
||||
|
||||
return pbToCert(response), nil
|
||||
return pbToCert(response)
|
||||
}
|
||||
|
||||
func (rac RegistrationAuthorityClientWrapper) UpdateRegistration(ctx context.Context, base, updates core.Registration) (core.Registration, error) {
|
||||
|
|
|
@ -108,11 +108,7 @@ func (sac StorageAuthorityClientWrapper) GetCertificate(ctx context.Context, ser
|
|||
return core.Certificate{}, err
|
||||
}
|
||||
|
||||
if response == nil || !certificateValid(response) {
|
||||
return core.Certificate{}, errIncompleteResponse
|
||||
}
|
||||
|
||||
return pbToCert(response), nil
|
||||
return pbToCert(response)
|
||||
}
|
||||
|
||||
func (sac StorageAuthorityClientWrapper) GetCertificateStatus(ctx context.Context, serial string) (core.CertificateStatus, error) {
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
corepb "github.com/letsencrypt/boulder/core/proto"
|
||||
berrors "github.com/letsencrypt/boulder/errors"
|
||||
"github.com/letsencrypt/boulder/probs"
|
||||
pubpb "github.com/letsencrypt/boulder/publisher/proto"
|
||||
"github.com/letsencrypt/boulder/revocation"
|
||||
sapb "github.com/letsencrypt/boulder/sa/proto"
|
||||
)
|
||||
|
@ -567,6 +568,11 @@ func (*Publisher) SubmitToSingleCT(_ context.Context, _, _ string, _ []byte) err
|
|||
return nil
|
||||
}
|
||||
|
||||
// SubmitToSingleCTWithResult is a mock
|
||||
func (*Publisher) SubmitToSingleCTWithResult(_ context.Context, _ *pubpb.Request) (*pubpb.Result, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Mailer is a mock
|
||||
type Mailer struct {
|
||||
Messages []MailerMessage
|
||||
|
|
54
ra/ra.go
54
ra/ra.go
|
@ -1056,18 +1056,37 @@ func (ra *RegistrationAuthorityImpl) issueCertificateInner(
|
|||
RegistrationID: &acctIDInt,
|
||||
OrderID: &orderIDInt,
|
||||
}
|
||||
cert, err := ra.CA.IssueCertificate(ctx, issueReq)
|
||||
if err != nil {
|
||||
return emptyCert, err
|
||||
}
|
||||
|
||||
if ra.ctpolicy != nil {
|
||||
ra.getSCTs(ctx, cert.DER)
|
||||
} else if ra.publisher != nil {
|
||||
go func() {
|
||||
// This context is limited by the gRPC timeout.
|
||||
_ = ra.publisher.SubmitToCT(context.Background(), cert.DER)
|
||||
}()
|
||||
var cert core.Certificate
|
||||
if features.Enabled(features.EmbedSCTs) {
|
||||
precert, err := ra.CA.IssuePrecertificate(ctx, issueReq)
|
||||
if err != nil {
|
||||
logEvent.Error = err.Error()
|
||||
return emptyCert, err
|
||||
}
|
||||
scts, err := ra.getSCTs(ctx, precert.DER)
|
||||
if err != nil {
|
||||
logEvent.Error = err.Error()
|
||||
return emptyCert, err
|
||||
}
|
||||
cert, err = ra.CA.IssueCertificateForPrecertificate(ctx, &caPB.IssueCertificateForPrecertificateRequest{
|
||||
DER: precert.DER,
|
||||
SCTs: scts,
|
||||
RegistrationID: &acctIDInt,
|
||||
OrderID: &orderIDInt,
|
||||
})
|
||||
if err != nil {
|
||||
logEvent.Error = err.Error()
|
||||
return emptyCert, err
|
||||
}
|
||||
} else {
|
||||
cert, err = ra.CA.IssueCertificate(ctx, issueReq)
|
||||
if err != nil {
|
||||
logEvent.Error = err.Error()
|
||||
return emptyCert, err
|
||||
}
|
||||
|
||||
_, _ = ra.getSCTs(ctx, cert.DER)
|
||||
}
|
||||
|
||||
parsedCertificate, err := x509.ParseCertificate([]byte(cert.DER))
|
||||
|
@ -1094,23 +1113,24 @@ func (ra *RegistrationAuthorityImpl) issueCertificateInner(
|
|||
return cert, nil
|
||||
}
|
||||
|
||||
func (ra *RegistrationAuthorityImpl) getSCTs(ctx context.Context, cert []byte) {
|
||||
func (ra *RegistrationAuthorityImpl) getSCTs(ctx context.Context, cert []byte) (core.SCTDERs, error) {
|
||||
started := ra.clk.Now()
|
||||
_, err := ra.ctpolicy.GetSCTs(ctx, cert)
|
||||
scts, err := ra.ctpolicy.GetSCTs(ctx, cert)
|
||||
took := ra.clk.Since(started)
|
||||
// The final cert has already been issued so actually return it to the
|
||||
// user even if this fails since we aren't actually doing anything with
|
||||
// the SCTs yet.
|
||||
state := "failure"
|
||||
if err != nil {
|
||||
state := "failure"
|
||||
if err == context.DeadlineExceeded {
|
||||
state = "deadlineExceeded"
|
||||
}
|
||||
ra.log.Warning(fmt.Sprintf("ctpolicy.GetSCTs failed: %s", err))
|
||||
} else if err == nil {
|
||||
state = "success"
|
||||
ra.ctpolicyResults.With(prometheus.Labels{"result": state}).Observe(took.Seconds())
|
||||
return nil, err
|
||||
}
|
||||
ra.ctpolicyResults.With(prometheus.Labels{"result": state}).Observe(took.Seconds())
|
||||
ra.ctpolicyResults.With(prometheus.Labels{"result": "success"}).Observe(took.Seconds())
|
||||
return scts, nil
|
||||
}
|
||||
|
||||
// domainsForRateLimiting transforms a list of FQDNs into a list of eTLD+1's
|
||||
|
|
|
@ -275,10 +275,12 @@ func initAuthorities(t *testing.T) (*DummyValidationAuthority, *sa.SQLStorageAut
|
|||
Status: core.StatusValid,
|
||||
})
|
||||
|
||||
ctp := ctpolicy.New(&mocks.Publisher{}, nil, nil, log)
|
||||
|
||||
ra := NewRegistrationAuthorityImpl(fc,
|
||||
log,
|
||||
stats,
|
||||
1, testKeyPolicy, 0, true, false, 300*24*time.Hour, 7*24*time.Hour, nil, noopCAA{}, 0, nil)
|
||||
1, testKeyPolicy, 0, true, false, 300*24*time.Hour, 7*24*time.Hour, nil, noopCAA{}, 0, ctp)
|
||||
ra.SA = ssa
|
||||
ra.VA = va
|
||||
ra.CA = ca
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
"doNotForceCN": true,
|
||||
"enableMustStaple": true,
|
||||
"hostnamePolicyFile": "test/hostname-policy.json",
|
||||
"enablePrecertificateFlow": true,
|
||||
"cfssl": {
|
||||
"signing": {
|
||||
"profiles": {
|
||||
|
@ -131,7 +132,8 @@
|
|||
},
|
||||
"maxConcurrentRPCServerRequests": 100000,
|
||||
"features": {
|
||||
"WildcardDomains": true
|
||||
"WildcardDomains": true,
|
||||
"EmbedSCTs": true
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
"ocspGeneratorService": {
|
||||
"serverAddresses": ["ca.boulder:9096"],
|
||||
"timeout": "15s"
|
||||
},
|
||||
"features": {
|
||||
"EmbedSCTs": true
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -45,8 +45,9 @@
|
|||
"WildcardDomains": true,
|
||||
"TLSSNIRevalidation": true,
|
||||
"ReusePendingAuthz": true,
|
||||
"VAChecksGSB": true,
|
||||
"CancelCTSubmissions": false
|
||||
"CancelCTSubmissions": false,
|
||||
"EmbedSCTs": true,
|
||||
"VAChecksGSB": true
|
||||
},
|
||||
"CTLogGroups2": [
|
||||
{
|
||||
|
|
|
@ -43,7 +43,35 @@
|
|||
"features": {
|
||||
"CountCertificatesExact": true,
|
||||
"ReusePendingAuthz": false
|
||||
}
|
||||
},
|
||||
"CTLogGroups2": [
|
||||
{
|
||||
"name": "a",
|
||||
"logs": [
|
||||
{
|
||||
"uri": "http://boulder:4500",
|
||||
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEYggOxPnPkzKBIhTacSYoIfnSL2jPugcbUKx83vFMvk5gKAz/AGe87w20riuPwEGn229hKVbEKHFB61NIqNHC3Q=="
|
||||
},
|
||||
{
|
||||
"uri": "http://boulder:4501",
|
||||
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKtnFevaXV/kB8dmhCNZHmxKVLcHX1plaAsY9LrKilhYxdmQZiu36LvAvosTsqMVqRK9a96nC8VaxAdaHUbM8EA=="
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "b",
|
||||
"logs": [
|
||||
{
|
||||
"uri": "http://boulder:4510",
|
||||
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyw1HymhJkuxSIgt3gqW3sVXqMqB3EFsXcMfPFo0vYwjNiRmCJDXKsR0Flp7MAK+wc3X/7Hpc8liUbMhPet7tEA=="
|
||||
},
|
||||
{
|
||||
"uri": "http://boulder:4511",
|
||||
"key": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFRu37ZRLg8lT4rVQwMwh4oAOpXb4Sx+9hgQ+JFCjmAv3oDV+sDOMsC7hULkGTn+LB5L1SRo/XIY4Kw5V+nFXgg=="
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
"pa": {
|
||||
|
|
|
@ -19,6 +19,9 @@ import os
|
|||
import OpenSSL
|
||||
import josepy as jose
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
|
||||
import startservers
|
||||
|
||||
import chisel2
|
||||
|
@ -45,6 +48,7 @@ def main():
|
|||
test_overlapping_wildcard()
|
||||
test_wildcard_exactblacklist()
|
||||
test_wildcard_authz_reuse()
|
||||
test_sct_embedding()
|
||||
test_order_reuse_failed_authz()
|
||||
test_revoke_by_issuer()
|
||||
test_revoke_by_authz()
|
||||
|
@ -280,6 +284,32 @@ def test_loadgeneration():
|
|||
shell=True,
|
||||
stderr=subprocess.STDOUT)
|
||||
|
||||
def test_sct_embedding():
|
||||
order = auth_and_issue([random_domain()])
|
||||
cert = x509.load_pem_x509_certificate(str(order.fullchain_pem), default_backend())
|
||||
|
||||
# make sure there is no poison extension
|
||||
try:
|
||||
cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3"))
|
||||
raise Exception("certificate contains CT poison extension")
|
||||
except x509.ExtensionNotFound:
|
||||
# do nothing
|
||||
pass
|
||||
|
||||
# make sure there is a SCT list extension
|
||||
try:
|
||||
sctList = cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2"))
|
||||
except x509.ExtensionNotFound:
|
||||
raise Exception("certificate doesn't contain SCT list extension")
|
||||
if len(sctList.value) != 2:
|
||||
raise Exception("SCT list contains wrong number of SCTs")
|
||||
for sct in sctList.value:
|
||||
if sct.version != x509.certificate_transparency.Version.v1:
|
||||
raise Exception("SCT contains wrong version")
|
||||
if sct.entry_type != x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE:
|
||||
raise Exception("SCT contains wrong entry type")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
|
|
|
@ -12,6 +12,7 @@ import requests
|
|||
import shutil
|
||||
import subprocess
|
||||
import signal
|
||||
import struct
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
|
@ -25,6 +26,9 @@ from chisel import auth_and_issue
|
|||
import requests
|
||||
import OpenSSL
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
|
||||
class ProcInfo:
|
||||
"""
|
||||
Args:
|
||||
|
@ -460,6 +464,32 @@ def test_stats():
|
|||
expect_stat(8002, '\ngrpc_client_handling_seconds_count{grpc_method="UpdatePendingAuthorization",grpc_service="sa.StorageAuthority",grpc_type="unary"} ')
|
||||
expect_stat(8001, "\ngo_goroutines ")
|
||||
|
||||
def test_sct_embedding():
|
||||
certr, authzs = auth_and_issue([random_domain()])
|
||||
certBytes = urllib2.urlopen(certr.uri).read()
|
||||
cert = x509.load_der_x509_certificate(certBytes, default_backend())
|
||||
|
||||
# make sure there is no poison extension
|
||||
try:
|
||||
cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3"))
|
||||
raise Exception("certificate contains CT poison extension")
|
||||
except x509.ExtensionNotFound:
|
||||
# do nothing
|
||||
pass
|
||||
|
||||
# make sure there is a SCT list extension
|
||||
try:
|
||||
sctList = cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2"))
|
||||
except x509.ExtensionNotFound:
|
||||
raise Exception("certificate doesn't contain SCT list extension")
|
||||
if len(sctList.value) != 2:
|
||||
raise Exception("SCT list contains wrong number of SCTs")
|
||||
for sct in sctList.value:
|
||||
if sct.version != x509.certificate_transparency.Version.v1:
|
||||
raise Exception("SCT contains wrong version")
|
||||
if sct.entry_type != x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE:
|
||||
raise Exception("SCT contains wrong entry type")
|
||||
|
||||
exit_status = 1
|
||||
tempdir = tempfile.mkdtemp()
|
||||
|
||||
|
@ -530,6 +560,8 @@ def run_chisel():
|
|||
test_expired_authzs_404()
|
||||
test_account_update()
|
||||
test_stats()
|
||||
if os.environ.get('BOULDER_CONFIG_DIR', '').startswith("test/config-next"):
|
||||
test_sct_embedding()
|
||||
|
||||
def run_loadtest():
|
||||
# Run the load generator
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/jmhodges/clock"
|
||||
"github.com/letsencrypt/boulder/core"
|
||||
corepb "github.com/letsencrypt/boulder/core/proto"
|
||||
"github.com/letsencrypt/boulder/ctpolicy"
|
||||
berrors "github.com/letsencrypt/boulder/errors"
|
||||
"github.com/letsencrypt/boulder/features"
|
||||
"github.com/letsencrypt/boulder/goodkey"
|
||||
|
@ -880,6 +881,7 @@ func TestIssueCertificate(t *testing.T) {
|
|||
// authorized, etc.
|
||||
stats := metrics.NewNoopScope()
|
||||
|
||||
ctp := ctpolicy.New(&mocks.Publisher{}, nil, nil, wfe.log)
|
||||
ra := ra.NewRegistrationAuthorityImpl(
|
||||
fc,
|
||||
wfe.log,
|
||||
|
@ -894,7 +896,7 @@ func TestIssueCertificate(t *testing.T) {
|
|||
nil,
|
||||
noopCAA{},
|
||||
0,
|
||||
nil,
|
||||
ctp,
|
||||
)
|
||||
ra.SA = mocks.NewStorageAuthority(fc)
|
||||
ra.CA = &mocks.MockCA{
|
||||
|
|
Loading…
Reference in New Issue