parent
0a367962d6
commit
8adf9d41cf
|
@ -2,7 +2,7 @@ Thanks for helping us build Boulder! This page contains requirements and guideli
|
||||||
|
|
||||||
# Patch Requirements
|
# Patch Requirements
|
||||||
* All new functionality and fixed bugs must be accompanied by tests.
|
* All new functionality and fixed bugs must be accompanied by tests.
|
||||||
* Boulder currently implements the ACME-01 draft as defined by [acme-spec](https://tools.ietf.org/html/draft-ietf-acme-acme-01). If a spec change is required for Boulder functionality, you should propose it on the ACME mailing list (acme@ietf.org), possibly accompanid by a pull request on the [spec repo](https://github.com/ietf-wg-acme/acme/).
|
* Boulder currently implements the ACME-01 draft as defined by [acme-spec](https://tools.ietf.org/html/draft-ietf-acme-acme-01). If a spec change is required for Boulder functionality, you should propose it on the ACME mailing list (acme@ietf.org), possibly accompanied by a pull request on the [spec repo](https://github.com/ietf-wg-acme/acme/).
|
||||||
* All patches must meet the deployability requirements listed below.
|
* All patches must meet the deployability requirements listed below.
|
||||||
* We prefer pull requests from external forks be created with the ["Allow edits from maintainers"](https://github.com/blog/2247-improving-collaboration-with-forks) checkbox selected.
|
* We prefer pull requests from external forks be created with the ["Allow edits from maintainers"](https://github.com/blog/2247-improving-collaboration-with-forks) checkbox selected.
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ Notes:
|
||||||
* Parse the challenge object (i.e., the response)
|
* Parse the challenge object (i.e., the response)
|
||||||
|
|
||||||
* 2-3: RA does the following:
|
* 2-3: RA does the following:
|
||||||
* Merge the response with the challenge in the authorzation object
|
* Merge the response with the challenge in the authorization object
|
||||||
* Store the updated authorization object
|
* Store the updated authorization object
|
||||||
|
|
||||||
* 3-4: VA does the following:
|
* 3-4: VA does the following:
|
||||||
|
@ -183,7 +183,7 @@ Notes:
|
||||||
* Verify that the CSR has a non-zero number of domain names
|
* Verify that the CSR has a non-zero number of domain names
|
||||||
* Verify that the public key in the CSR is different from the account key
|
* Verify that the public key in the CSR is different from the account key
|
||||||
* For each authorization referenced in the certificate request
|
* For each authorization referenced in the certificate request
|
||||||
* Retreive the authorization from the database
|
* Retrieve the authorization from the database
|
||||||
* Verify that the authorization corresponds to the account key
|
* Verify that the authorization corresponds to the account key
|
||||||
* Verify that the authorization is valid
|
* Verify that the authorization is valid
|
||||||
* Verify that the authorization is still valid
|
* Verify that the authorization is still valid
|
||||||
|
|
2
ca/ca.go
2
ca/ca.go
|
@ -174,7 +174,7 @@ func makeInternalIssuers(
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCertificateAuthorityImpl creates a CA instance that can sign certificates
|
// NewCertificateAuthorityImpl creates a CA instance that can sign certificates
|
||||||
// from a single issuer (the first first in the issers 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.
|
// for any of the issuer certificates provided.
|
||||||
func NewCertificateAuthorityImpl(
|
func NewCertificateAuthorityImpl(
|
||||||
config cmd.CAConfig,
|
config cmd.CAConfig,
|
||||||
|
|
|
@ -236,7 +236,7 @@ func (db mismatchedCountDB) SelectOne(output interface{}, _ string, _ ...interfa
|
||||||
}
|
}
|
||||||
|
|
||||||
// `getCerts` then calls `Select` to retrieve the Certificate rows. We pull
|
// `getCerts` then calls `Select` to retrieve the Certificate rows. We pull
|
||||||
// a dasterdly switch-a-roo here and return an empty set
|
// a dastardly switch-a-roo here and return an empty set
|
||||||
func (db mismatchedCountDB) Select(output interface{}, _ string, _ ...interface{}) ([]interface{}, error) {
|
func (db mismatchedCountDB) Select(output interface{}, _ string, _ ...interface{}) ([]interface{}, error) {
|
||||||
// But actually return nothing
|
// But actually return nothing
|
||||||
outputPtr, _ := output.(*[]core.Certificate)
|
outputPtr, _ := output.(*[]core.Certificate)
|
||||||
|
|
|
@ -200,7 +200,7 @@ type IssuerConfig struct {
|
||||||
NumSessions int
|
NumSessions int
|
||||||
}
|
}
|
||||||
|
|
||||||
// TLSConfig reprents certificates and a key for authenticated TLS.
|
// TLSConfig represents certificates and a key for authenticated TLS.
|
||||||
type TLSConfig struct {
|
type TLSConfig struct {
|
||||||
CertFile *string
|
CertFile *string
|
||||||
KeyFile *string
|
KeyFile *string
|
||||||
|
|
|
@ -220,7 +220,7 @@ func TestFindExpiringCertificates(t *testing.T) {
|
||||||
|
|
||||||
test.AssertEquals(t, mocks.MailerMessage{
|
test.AssertEquals(t, mocks.MailerMessage{
|
||||||
To: emailARaw,
|
To: emailARaw,
|
||||||
// A certificte with only one domain should have only one domain listed in
|
// A certificate with only one domain should have only one domain listed in
|
||||||
// the subject
|
// the subject
|
||||||
Subject: "Certificate expiration notice for domain \"example-a.com\"",
|
Subject: "Certificate expiration notice for domain \"example-a.com\"",
|
||||||
Body: "hi, cert for DNS names example-a.com is going to expire in 0 days (03 Jan 06 14:04 +0000)",
|
Body: "hi, cert for DNS names example-a.com is going to expire in 0 days (03 Jan 06 14:04 +0000)",
|
||||||
|
@ -442,7 +442,7 @@ func TestFindCertsAtCapacity(t *testing.T) {
|
||||||
// findExpiringCertificates() ends up invoking sendNags which calls
|
// findExpiringCertificates() ends up invoking sendNags which calls
|
||||||
// TimingDuration so we need to EXPECT that with the mock
|
// TimingDuration so we need to EXPECT that with the mock
|
||||||
statter.EXPECT().TimingDuration("Expiration.SendLatency", time.Duration(0), float32(1.0))
|
statter.EXPECT().TimingDuration("Expiration.SendLatency", time.Duration(0), float32(1.0))
|
||||||
// Similarly, findExpiringCerticates() sends its latency as well
|
// Similarly, findExpiringCertificates() sends its latency as well
|
||||||
statter.EXPECT().TimingDuration("Expiration.ProcessingCertificatesLatency", time.Duration(0), float32(1.0))
|
statter.EXPECT().TimingDuration("Expiration.ProcessingCertificatesLatency", time.Duration(0), float32(1.0))
|
||||||
|
|
||||||
err := testCtx.m.findExpiringCertificates()
|
err := testCtx.m.findExpiringCertificates()
|
||||||
|
|
|
@ -56,7 +56,7 @@ type OCSPUpdater struct {
|
||||||
|
|
||||||
// Used to calculate how far back stale OCSP responses should be looked for
|
// Used to calculate how far back stale OCSP responses should be looked for
|
||||||
ocspMinTimeToExpiry time.Duration
|
ocspMinTimeToExpiry time.Duration
|
||||||
// Used to caculate how far back in time the findStaleOCSPResponse will look
|
// Used to calculate how far back in time the findStaleOCSPResponse will look
|
||||||
ocspStaleMaxAge time.Duration
|
ocspStaleMaxAge time.Duration
|
||||||
// Used to calculate how far back missing SCT receipts should be looked for
|
// Used to calculate how far back missing SCT receipts should be looked for
|
||||||
oldestIssuedSCT time.Duration
|
oldestIssuedSCT time.Duration
|
||||||
|
|
|
@ -396,7 +396,7 @@ func TestOldOCSPResponsesTick(t *testing.T) {
|
||||||
test.AssertEquals(t, len(certs), 0)
|
test.AssertEquals(t, len(certs), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestOldOCSPResponesTickIsExpired checks that the old OCSP responses tick
|
// TestOldOCSPResponsesTickIsExpired checks that the old OCSP responses tick
|
||||||
// updates the `IsExpired` field opportunistically as it encounters certificates
|
// updates the `IsExpired` field opportunistically as it encounters certificates
|
||||||
// that are expired but whose certificate status rows do not have `IsExpired`
|
// that are expired but whose certificate status rows do not have `IsExpired`
|
||||||
// set.
|
// set.
|
||||||
|
|
|
@ -76,7 +76,7 @@ func newMockWriter() *mockWriter {
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAll returns all messages logged since insantiation or the last call to
|
// GetAll returns all messages logged since instantiation or the last call to
|
||||||
// Clear().
|
// Clear().
|
||||||
//
|
//
|
||||||
// The caller must not modify the returned slice or its elements.
|
// The caller must not modify the returned slice or its elements.
|
||||||
|
|
|
@ -1282,7 +1282,7 @@ func (m mockSAWithFQDNSet) FQDNSetExists(_ context.Context, names []string) (boo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a map of domain -> certificate count. Note: This naive implementation
|
// Return a map of domain -> certificate count. Note: This naive implementation
|
||||||
// ignores names, earliest and latest paremeters and always returns the same
|
// ignores names, earliest and latest parameters and always returns the same
|
||||||
// nameCount map.
|
// nameCount map.
|
||||||
func (m mockSAWithFQDNSet) CountCertificatesByNames(ctx context.Context, names []string, earliest, latest time.Time) (ret map[string]int, err error) {
|
func (m mockSAWithFQDNSet) CountCertificatesByNames(ctx context.Context, names []string, earliest, latest time.Time) (ret map[string]int, err error) {
|
||||||
return m.nameCounts, nil
|
return m.nameCounts, nil
|
||||||
|
|
|
@ -186,7 +186,7 @@ func TestReloadFailure(t *testing.T) {
|
||||||
// Create a file with no permissions
|
// Create a file with no permissions
|
||||||
oldReadFile := readFile
|
oldReadFile := readFile
|
||||||
readFile = func(string) ([]byte, error) {
|
readFile = func(string) ([]byte, error) {
|
||||||
return nil, fmt.Errorf("permisssion denied")
|
return nil, fmt.Errorf("permission denied")
|
||||||
}
|
}
|
||||||
|
|
||||||
fakeTick <- time.Now()
|
fakeTick <- time.Now()
|
||||||
|
|
|
@ -664,7 +664,7 @@ func NewPublisherClient(clientName string, amqpConf *cmd.AMQPConfig, stats metri
|
||||||
return &PublisherClient{rpc: client}, err
|
return &PublisherClient{rpc: client}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubmitToCT sends a request to submit a certifcate to CT logs
|
// SubmitToCT sends a request to submit a certificate to CT logs
|
||||||
func (pub PublisherClient) SubmitToCT(ctx context.Context, der []byte) (err error) {
|
func (pub PublisherClient) SubmitToCT(ctx context.Context, der []byte) (err error) {
|
||||||
_, err = pub.rpc.DispatchSync(MethodSubmitToCT, der)
|
_, err = pub.rpc.DispatchSync(MethodSubmitToCT, der)
|
||||||
return
|
return
|
||||||
|
@ -1482,7 +1482,7 @@ func (cac StorageAuthorityClient) AddSCTReceipt(ctx context.Context, sct core.Si
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountFQDNSets reutrns the number of currently valid sets with hash |setHash|
|
// CountFQDNSets returns the number of currently valid sets with hash |setHash|
|
||||||
func (cac StorageAuthorityClient) CountFQDNSets(ctx context.Context, window time.Duration, names []string) (int64, error) {
|
func (cac StorageAuthorityClient) CountFQDNSets(ctx context.Context, window time.Duration, names []string) (int64, error) {
|
||||||
data, err := json.Marshal(countFQDNsRequest{window, names})
|
data, err := json.Marshal(countFQDNsRequest{window, names})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -423,7 +423,7 @@ def main():
|
||||||
die(ExitStatus.NodeFailure)
|
die(ExitStatus.NodeFailure)
|
||||||
|
|
||||||
if run_node_test("bad-caa-reserved.com", challenge_types[0], expected_ct_submissions) != ISSUANCE_FAILED:
|
if run_node_test("bad-caa-reserved.com", challenge_types[0], expected_ct_submissions) != ISSUANCE_FAILED:
|
||||||
print("\nIssused certificate for domain with bad CAA records")
|
print("\nIssued certificate for domain with bad CAA records")
|
||||||
die(ExitStatus.NodeFailure)
|
die(ExitStatus.NodeFailure)
|
||||||
|
|
||||||
run_expired_authz_purger_test()
|
run_expired_authz_purger_test()
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
vaPB "github.com/letsencrypt/boulder/va/proto"
|
vaPB "github.com/letsencrypt/boulder/va/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SafeBrowsing is an interface for a third-party safe browing API client.
|
// SafeBrowsing is an interface for a third-party safe browsing API client.
|
||||||
type SafeBrowsing interface {
|
type SafeBrowsing interface {
|
||||||
// IsListed returns a non-empty string if the domain was bad. Specifically,
|
// IsListed returns a non-empty string if the domain was bad. Specifically,
|
||||||
// it is which Google Safe Browsing list the domain was found on.
|
// it is which Google Safe Browsing list the domain was found on.
|
||||||
|
|
2
va/va.go
2
va/va.go
|
@ -393,7 +393,7 @@ func parseHTTPConnError(detail string, err error) *probs.ProblemDetails {
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX: On all of the resolvers I tested that validate DNSSEC, there is
|
// XXX: On all of the resolvers I tested that validate DNSSEC, there is
|
||||||
// no differentation between a DNSSEC failure and an unknown host. If we
|
// no differentiation between a DNSSEC failure and an unknown host. If we
|
||||||
// do not verify DNSSEC ourselves, this function should be modified.
|
// do not verify DNSSEC ourselves, this function should be modified.
|
||||||
if netErr, ok := err.(*net.OpError); ok {
|
if netErr, ok := err.(*net.OpError); ok {
|
||||||
dnsErr, ok := netErr.Err.(*net.DNSError)
|
dnsErr, ok := netErr.Err.(*net.DNSError)
|
||||||
|
|
|
@ -443,7 +443,7 @@ func TestTLSSNI(t *testing.T) {
|
||||||
|
|
||||||
_, prob := va.validateTLSSNI01(ctx, ident, chall)
|
_, prob := va.validateTLSSNI01(ctx, ident, chall)
|
||||||
if prob != nil {
|
if prob != nil {
|
||||||
t.Fatalf("Unexpected failre in validateTLSSNI01: %s", prob)
|
t.Fatalf("Unexpected failure in validateTLSSNI01: %s", prob)
|
||||||
}
|
}
|
||||||
test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1)
|
test.AssertEquals(t, len(log.GetAllMatching(`Resolved addresses for localhost \[using 127.0.0.1\]: \[127.0.0.1\]`)), 1)
|
||||||
if len(log.GetAllMatching(`challenge for localhost received certificate \(1 of 1\): cert=\[`)) != 1 {
|
if len(log.GetAllMatching(`challenge for localhost received certificate \(1 of 1\): cert=\[`)) != 1 {
|
||||||
|
|
|
@ -530,7 +530,7 @@ func (wfe *WebFrontEndImpl) verifyPOST(ctx context.Context, logEvent *requestEve
|
||||||
}
|
}
|
||||||
err = json.Unmarshal([]byte(payload), &parsedRequest)
|
err = json.Unmarshal([]byte(payload), &parsedRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
wfe.stats.Inc("Errors.UnparsableJWSPayload", 1)
|
wfe.stats.Inc("Errors.UnparseableJWSPayload", 1)
|
||||||
logEvent.AddError("unable to JSON parse resource from JWS payload: %s", err)
|
logEvent.AddError("unable to JSON parse resource from JWS payload: %s", err)
|
||||||
return nil, nil, reg, probs.Malformed("Request payload did not parse as JSON")
|
return nil, nil, reg, probs.Malformed("Request payload did not parse as JSON")
|
||||||
}
|
}
|
||||||
|
@ -1088,7 +1088,7 @@ func (wfe *WebFrontEndImpl) postChallenge(
|
||||||
|
|
||||||
var challengeUpdate core.Challenge
|
var challengeUpdate core.Challenge
|
||||||
if err := json.Unmarshal(body, &challengeUpdate); err != nil {
|
if err := json.Unmarshal(body, &challengeUpdate); err != nil {
|
||||||
logEvent.AddError("error JSON unmarshalling challenge response: %s", err)
|
logEvent.AddError("error JSON unmarshaling challenge response: %s", err)
|
||||||
wfe.sendError(response, logEvent, probs.Malformed("Error unmarshaling challenge response"), err)
|
wfe.sendError(response, logEvent, probs.Malformed("Error unmarshaling challenge response"), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue