Merge branch 'master' into cert-limit
This commit is contained in:
		
						commit
						6e3f0e18c6
					
				| 
						 | 
					@ -27,6 +27,16 @@ import (
 | 
				
			||||||
	"github.com/letsencrypt/boulder/sa"
 | 
						"github.com/letsencrypt/boulder/sa"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type cacheCtrlHandler struct {
 | 
				
			||||||
 | 
						http.Handler
 | 
				
			||||||
 | 
						MaxAge time.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *cacheCtrlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						w.Header().Set("Cache-Control", fmt.Sprintf("max-age=%d", c.MaxAge/time.Second))
 | 
				
			||||||
 | 
						c.Handler.ServeHTTP(w, r)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
DBSource maps a given Database schema to a CA Key Hash, so we can pick
 | 
					DBSource maps a given Database schema to a CA Key Hash, so we can pick
 | 
				
			||||||
from among them when presented with OCSP requests for different certs.
 | 
					from among them when presented with OCSP requests for different certs.
 | 
				
			||||||
| 
						 | 
					@ -158,9 +168,9 @@ func main() {
 | 
				
			||||||
		killTimeout, err := time.ParseDuration(c.OCSPResponder.ShutdownKillTimeout)
 | 
							killTimeout, err := time.ParseDuration(c.OCSPResponder.ShutdownKillTimeout)
 | 
				
			||||||
		cmd.FailOnError(err, "Couldn't parse shutdown kill timeout")
 | 
							cmd.FailOnError(err, "Couldn't parse shutdown kill timeout")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Configure HTTP
 | 
					 | 
				
			||||||
		m := http.NewServeMux()
 | 
							m := http.NewServeMux()
 | 
				
			||||||
		m.Handle(c.OCSPResponder.Path, cfocsp.Responder{Source: source})
 | 
							m.Handle(c.OCSPResponder.Path,
 | 
				
			||||||
 | 
								handler(source, c.OCSPResponder.MaxAge.Duration))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		httpMonitor := metrics.NewHTTPMonitor(stats, m, "OCSP")
 | 
							httpMonitor := metrics.NewHTTPMonitor(stats, m, "OCSP")
 | 
				
			||||||
		srv := &http.Server{
 | 
							srv := &http.Server{
 | 
				
			||||||
| 
						 | 
					@ -179,3 +189,10 @@ func main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	app.Run()
 | 
						app.Run()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func handler(src cfocsp.Source, maxAge time.Duration) http.Handler {
 | 
				
			||||||
 | 
						return &cacheCtrlHandler{
 | 
				
			||||||
 | 
							Handler: cfocsp.Responder{Source: src},
 | 
				
			||||||
 | 
							MaxAge:  maxAge,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1 +1,26 @@
 | 
				
			||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"net/http/httptest"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/letsencrypt/boulder/Godeps/_workspace/src/github.com/cloudflare/cfssl/ocsp"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCacheControl(t *testing.T) {
 | 
				
			||||||
 | 
						src := make(ocsp.InMemorySource)
 | 
				
			||||||
 | 
						h := handler(src, 10*time.Second)
 | 
				
			||||||
 | 
						w := httptest.NewRecorder()
 | 
				
			||||||
 | 
						r, err := http.NewRequest("GET", "/", nil)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						h.ServeHTTP(w, r)
 | 
				
			||||||
 | 
						expected := "max-age=10"
 | 
				
			||||||
 | 
						actual := w.Header().Get("Cache-Control")
 | 
				
			||||||
 | 
						if actual != expected {
 | 
				
			||||||
 | 
							t.Errorf("Cache-Control value: want %#v, got %#v", expected, actual)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										27
									
								
								cmd/shell.go
								
								
								
								
							
							
						
						
									
										27
									
								
								cmd/shell.go
								
								
								
								
							| 
						 | 
					@ -163,6 +163,9 @@ type Config struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Path          string
 | 
							Path          string
 | 
				
			||||||
		ListenAddress string
 | 
							ListenAddress string
 | 
				
			||||||
 | 
							// MaxAge is the max-age to set in the Cache-Controler response
 | 
				
			||||||
 | 
							// header. It is a time.Duration formatted string.
 | 
				
			||||||
 | 
							MaxAge JSONDuration
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ShutdownStopTimeout string
 | 
							ShutdownStopTimeout string
 | 
				
			||||||
		ShutdownKillTimeout string
 | 
							ShutdownKillTimeout string
 | 
				
			||||||
| 
						 | 
					@ -431,3 +434,27 @@ func DebugServer(addr string) {
 | 
				
			||||||
	log.Printf("booting debug server at %#v", addr)
 | 
						log.Printf("booting debug server at %#v", addr)
 | 
				
			||||||
	log.Println(http.Serve(ln, nil))
 | 
						log.Println(http.Serve(ln, nil))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type JSONDuration struct {
 | 
				
			||||||
 | 
						time.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var ErrDurationMustBeString = errors.New("cannot JSON unmarshal something other than a string into a JSONDuration")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d *JSONDuration) UnmarshalJSON(b []byte) error {
 | 
				
			||||||
 | 
						s := ""
 | 
				
			||||||
 | 
						err := json.Unmarshal(b, &s)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if _, ok := err.(*json.UnmarshalTypeError); ok {
 | 
				
			||||||
 | 
								return ErrDurationMustBeString
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dd, err := time.ParseDuration(s)
 | 
				
			||||||
 | 
						d.Duration = dd
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (d JSONDuration) MarshalJSON() ([]byte, error) {
 | 
				
			||||||
 | 
						return []byte(d.Duration.String()), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -108,7 +108,6 @@ type StorageGetter interface {
 | 
				
			||||||
	GetAuthorization(string) (Authorization, error)
 | 
						GetAuthorization(string) (Authorization, error)
 | 
				
			||||||
	GetLatestValidAuthorization(int64, AcmeIdentifier) (Authorization, error)
 | 
						GetLatestValidAuthorization(int64, AcmeIdentifier) (Authorization, error)
 | 
				
			||||||
	GetCertificate(string) (Certificate, error)
 | 
						GetCertificate(string) (Certificate, error)
 | 
				
			||||||
	GetCertificateByShortSerial(string) (Certificate, error)
 | 
					 | 
				
			||||||
	GetCertificateStatus(string) (CertificateStatus, error)
 | 
						GetCertificateStatus(string) (CertificateStatus, error)
 | 
				
			||||||
	AlreadyDeniedCSR([]string) (bool, error)
 | 
						AlreadyDeniedCSR([]string) (bool, error)
 | 
				
			||||||
	CountCertificatesRange(time.Time, time.Time) (int64, error)
 | 
						CountCertificatesRange(time.Time, time.Time) (int64, error)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -231,11 +231,6 @@ func (sa *MockSA) GetCertificate(serial string) (core.Certificate, error) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetCertificateByShortSerial is a mock
 | 
					 | 
				
			||||||
func (sa *MockSA) GetCertificateByShortSerial(serial string) (core.Certificate, error) {
 | 
					 | 
				
			||||||
	return sa.GetCertificate("0000000000000000" + serial)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetCertificateStatus is a mock
 | 
					// GetCertificateStatus is a mock
 | 
				
			||||||
func (sa *MockSA) GetCertificateStatus(serial string) (core.CertificateStatus, error) {
 | 
					func (sa *MockSA) GetCertificateStatus(serial string) (core.CertificateStatus, error) {
 | 
				
			||||||
	// Serial ee == 238.crt
 | 
						// Serial ee == 238.crt
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,7 +54,6 @@ const (
 | 
				
			||||||
	MethodGetAuthorization                  = "GetAuthorization"                  // SA
 | 
						MethodGetAuthorization                  = "GetAuthorization"                  // SA
 | 
				
			||||||
	MethodGetLatestValidAuthorization       = "GetLatestValidAuthorization"       // SA
 | 
						MethodGetLatestValidAuthorization       = "GetLatestValidAuthorization"       // SA
 | 
				
			||||||
	MethodGetCertificate                    = "GetCertificate"                    // SA
 | 
						MethodGetCertificate                    = "GetCertificate"                    // SA
 | 
				
			||||||
	MethodGetCertificateByShortSerial       = "GetCertificateByShortSerial"       // SA
 | 
					 | 
				
			||||||
	MethodGetCertificateStatus              = "GetCertificateStatus"              // SA
 | 
						MethodGetCertificateStatus              = "GetCertificateStatus"              // SA
 | 
				
			||||||
	MethodMarkCertificateRevoked            = "MarkCertificateRevoked"            // SA
 | 
						MethodMarkCertificateRevoked            = "MarkCertificateRevoked"            // SA
 | 
				
			||||||
	MethodUpdateOCSP                        = "UpdateOCSP"                        // SA
 | 
						MethodUpdateOCSP                        = "UpdateOCSP"                        // SA
 | 
				
			||||||
| 
						 | 
					@ -940,22 +939,6 @@ func NewStorageAuthorityServer(rpc RPCServer, impl core.StorageAuthority) error
 | 
				
			||||||
		return jsonResponse, nil
 | 
							return jsonResponse, nil
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rpc.Handle(MethodGetCertificateByShortSerial, func(req []byte) (response []byte, err error) {
 | 
					 | 
				
			||||||
		cert, err := impl.GetCertificateByShortSerial(string(req))
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		jsonResponse, err := json.Marshal(cert)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
 | 
					 | 
				
			||||||
			errorCondition(MethodGetCertificateByShortSerial, err, req)
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return jsonResponse, nil
 | 
					 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	rpc.Handle(MethodGetCertificateStatus, func(req []byte) (response []byte, err error) {
 | 
						rpc.Handle(MethodGetCertificateStatus, func(req []byte) (response []byte, err error) {
 | 
				
			||||||
		status, err := impl.GetCertificateStatus(string(req))
 | 
							status, err := impl.GetCertificateStatus(string(req))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -1080,7 +1063,7 @@ func NewStorageAuthorityServer(rpc RPCServer, impl core.StorageAuthority) error
 | 
				
			||||||
		err = impl.AddSCTReceipt(core.SignedCertificateTimestamp(sct))
 | 
							err = impl.AddSCTReceipt(core.SignedCertificateTimestamp(sct))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
 | 
								// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
 | 
				
			||||||
			errorCondition(MethodGetCertificateByShortSerial, err, req)
 | 
								errorCondition(MethodAddSCTReceipt, err, req)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1179,18 +1162,6 @@ func (cac StorageAuthorityClient) GetCertificate(id string) (cert core.Certifica
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetCertificateByShortSerial sends a request to search for a certificate by
 | 
					 | 
				
			||||||
// the predictable portion of its serial number.
 | 
					 | 
				
			||||||
func (cac StorageAuthorityClient) GetCertificateByShortSerial(id string) (cert core.Certificate, err error) {
 | 
					 | 
				
			||||||
	jsonCert, err := cac.rpc.DispatchSync(MethodGetCertificateByShortSerial, []byte(id))
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = json.Unmarshal(jsonCert, &cert)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetCertificateStatus sends a request to obtain the current status of a
 | 
					// GetCertificateStatus sends a request to obtain the current status of a
 | 
				
			||||||
// certificate by ID
 | 
					// certificate by ID
 | 
				
			||||||
func (cac StorageAuthorityClient) GetCertificateStatus(id string) (status core.CertificateStatus, err error) {
 | 
					func (cac StorageAuthorityClient) GetCertificateStatus(id string) (status core.CertificateStatus, err error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -237,21 +237,6 @@ func (ssa *SQLStorageAuthority) GetLatestValidAuthorization(registrationId int64
 | 
				
			||||||
	return ssa.GetAuthorization(auth.ID)
 | 
						return ssa.GetAuthorization(auth.ID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetCertificateByShortSerial takes an id consisting of the first, sequential half of a
 | 
					 | 
				
			||||||
// serial number and returns the first certificate whose full serial number is
 | 
					 | 
				
			||||||
// lexically greater than that id. This allows clients to query on the known
 | 
					 | 
				
			||||||
// sequential half of our serial numbers to enumerate all certificates.
 | 
					 | 
				
			||||||
func (ssa *SQLStorageAuthority) GetCertificateByShortSerial(shortSerial string) (cert core.Certificate, err error) {
 | 
					 | 
				
			||||||
	if len(shortSerial) != 16 {
 | 
					 | 
				
			||||||
		err = errors.New("Invalid certificate short serial " + shortSerial)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	err = ssa.dbMap.SelectOne(&cert, "SELECT * FROM certificates WHERE serial LIKE :shortSerial",
 | 
					 | 
				
			||||||
		map[string]interface{}{"shortSerial": shortSerial + "%"})
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetCertificate takes a serial number and returns the corresponding
 | 
					// GetCertificate takes a serial number and returns the corresponding
 | 
				
			||||||
// certificate, or error if it does not exist.
 | 
					// certificate, or error if it does not exist.
 | 
				
			||||||
func (ssa *SQLStorageAuthority) GetCertificate(serial string) (core.Certificate, error) {
 | 
					func (ssa *SQLStorageAuthority) GetCertificate(serial string) (core.Certificate, error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -301,12 +301,7 @@ func TestAddCertificate(t *testing.T) {
 | 
				
			||||||
	test.AssertNotError(t, err, "Couldn't add www.eff.org.der")
 | 
						test.AssertNotError(t, err, "Couldn't add www.eff.org.der")
 | 
				
			||||||
	test.AssertEquals(t, digest, "qWoItDZmR4P9eFbeYgXXP3SR4ApnkQj8x4LsB_ORKBo")
 | 
						test.AssertEquals(t, digest, "qWoItDZmR4P9eFbeYgXXP3SR4ApnkQj8x4LsB_ORKBo")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Example cert serial is 0x21bd4, so a prefix of all zeroes should fetch it.
 | 
						retrievedCert, err := sa.GetCertificate("000000000000000000000000000000021bd4")
 | 
				
			||||||
	retrievedCert, err := sa.GetCertificateByShortSerial("0000000000000000")
 | 
					 | 
				
			||||||
	test.AssertNotError(t, err, "Couldn't get www.eff.org.der by short serial")
 | 
					 | 
				
			||||||
	test.AssertByteEquals(t, certDER, retrievedCert.DER)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	retrievedCert, err = sa.GetCertificate("000000000000000000000000000000021bd4")
 | 
					 | 
				
			||||||
	test.AssertNotError(t, err, "Couldn't get www.eff.org.der by full serial")
 | 
						test.AssertNotError(t, err, "Couldn't get www.eff.org.der by full serial")
 | 
				
			||||||
	test.AssertByteEquals(t, certDER, retrievedCert.DER)
 | 
						test.AssertByteEquals(t, certDER, retrievedCert.DER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -324,12 +319,7 @@ func TestAddCertificate(t *testing.T) {
 | 
				
			||||||
	test.AssertNotError(t, err, "Couldn't add test-cert.der")
 | 
						test.AssertNotError(t, err, "Couldn't add test-cert.der")
 | 
				
			||||||
	test.AssertEquals(t, digest2, "CMVYqWzyqUW7pfBF2CxL0Uk6I0Upsk7p4EWSnd_vYx4")
 | 
						test.AssertEquals(t, digest2, "CMVYqWzyqUW7pfBF2CxL0Uk6I0Upsk7p4EWSnd_vYx4")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Example cert serial is 0x21bd4, so a prefix of all zeroes should fetch it.
 | 
						retrievedCert2, err := sa.GetCertificate("0000ff00000000000002238054509817da5a")
 | 
				
			||||||
	retrievedCert2, err := sa.GetCertificateByShortSerial("0000ff0000000000")
 | 
					 | 
				
			||||||
	test.AssertNotError(t, err, "Couldn't get test-cert.der")
 | 
					 | 
				
			||||||
	test.AssertByteEquals(t, certDER2, retrievedCert2.DER)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	retrievedCert2, err = sa.GetCertificate("0000ff00000000000002238054509817da5a")
 | 
					 | 
				
			||||||
	test.AssertNotError(t, err, "Couldn't get test-cert.der")
 | 
						test.AssertNotError(t, err, "Couldn't get test-cert.der")
 | 
				
			||||||
	test.AssertByteEquals(t, certDER2, retrievedCert2.DER)
 | 
						test.AssertByteEquals(t, certDER2, retrievedCert2.DER)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -340,19 +330,6 @@ func TestAddCertificate(t *testing.T) {
 | 
				
			||||||
	test.Assert(t, certificateStatus2.OCSPLastUpdated.IsZero(), "OCSPLastUpdated should be nil")
 | 
						test.Assert(t, certificateStatus2.OCSPLastUpdated.IsZero(), "OCSPLastUpdated should be nil")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TestGetCertificateByShortSerial tests some failure conditions for GetCertificate.
 | 
					 | 
				
			||||||
// Success conditions are tested above in TestAddCertificate.
 | 
					 | 
				
			||||||
func TestGetCertificateByShortSerial(t *testing.T) {
 | 
					 | 
				
			||||||
	sa, _, cleanUp := initSA(t)
 | 
					 | 
				
			||||||
	defer cleanUp()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err := sa.GetCertificateByShortSerial("")
 | 
					 | 
				
			||||||
	test.AssertError(t, err, "Should've failed on empty serial")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err = sa.GetCertificateByShortSerial("01020304050607080102030405060708")
 | 
					 | 
				
			||||||
	test.AssertError(t, err, "Should've failed on too-long serial")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestDeniedCSR(t *testing.T) {
 | 
					func TestDeniedCSR(t *testing.T) {
 | 
				
			||||||
	key, _ := rsa.GenerateKey(rand.Reader, 512)
 | 
						key, _ := rsa.GenerateKey(rand.Reader, 512)
 | 
				
			||||||
	template := &x509.CertificateRequest{
 | 
						template := &x509.CertificateRequest{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,6 +149,7 @@
 | 
				
			||||||
    "source": "mysql+tcp://boulder@localhost:3306/boulder_sa_integration",
 | 
					    "source": "mysql+tcp://boulder@localhost:3306/boulder_sa_integration",
 | 
				
			||||||
    "path": "/",
 | 
					    "path": "/",
 | 
				
			||||||
    "listenAddress": "localhost:4002",
 | 
					    "listenAddress": "localhost:4002",
 | 
				
			||||||
 | 
					    "maxAge": "10s",
 | 
				
			||||||
    "shutdownStopTimeout": "10s",
 | 
					    "shutdownStopTimeout": "10s",
 | 
				
			||||||
    "shutdownKillTimeout": "1m",
 | 
					    "shutdownKillTimeout": "1m",
 | 
				
			||||||
    "debugAddr": "localhost:8005"
 | 
					    "debugAddr": "localhost:8005"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue