Merge branch 'master' into paranoid-key

This commit is contained in:
Jacob Hoffman-Andrews 2015-10-01 14:12:38 -07:00
commit a9db85adf2
17 changed files with 86 additions and 57 deletions

View File

@ -118,8 +118,8 @@ func main() {
cmd.FailOnError(err, "Could not connect to statsd") cmd.FailOnError(err, "Could not connect to statsd")
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
blog.SetAuditLogger(auditlogger) blog.SetAuditLogger(auditlogger)
@ -131,8 +131,6 @@ func main() {
go cmd.ProfileCmd("AM", stats) go cmd.ProfileCmd("AM", stats)
auditlogger.Info(app.VersionString())
startMonitor(ch, auditlogger, stats) startMonitor(ch, auditlogger, stats)
} }

View File

@ -25,6 +25,7 @@ func main() {
// Set up logging // Set up logging
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
defer auditlogger.AuditPanic() defer auditlogger.AuditPanic()
@ -65,8 +66,6 @@ func main() {
cmd.FailOnError(err, "Unable to create CA RPC server") cmd.FailOnError(err, "Unable to create CA RPC server")
rpc.NewCertificateAuthorityServer(cas, cai) rpc.NewCertificateAuthorityServer(cas, cai)
auditlogger.Info(app.VersionString())
err = cas.Start(c) err = cas.Start(c)
cmd.FailOnError(err, "Unable to run CA RPC server") cmd.FailOnError(err, "Unable to run CA RPC server")
} }

View File

@ -23,6 +23,7 @@ func main() {
// Set up logging // Set up logging
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to syslog") cmd.FailOnError(err, "Could not connect to syslog")
auditlogger.Info(app.VersionString())
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
defer auditlogger.AuditPanic() defer auditlogger.AuditPanic()
@ -49,8 +50,6 @@ func main() {
cmd.FailOnError(err, "Unable to create Publisher RPC server") cmd.FailOnError(err, "Unable to create Publisher RPC server")
rpc.NewPublisherServer(pubs, &pubi) rpc.NewPublisherServer(pubs, &pubi)
auditlogger.Info(app.VersionString())
err = pubs.Start(c) err = pubs.Start(c)
cmd.FailOnError(err, "Unable to run Publisher RPC server") cmd.FailOnError(err, "Unable to run Publisher RPC server")
} }

View File

@ -29,6 +29,7 @@ func main() {
// Set up logging // Set up logging
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
defer auditlogger.AuditPanic() defer auditlogger.AuditPanic()
@ -82,8 +83,6 @@ func main() {
cmd.FailOnError(err, "Unable to create RA RPC server") cmd.FailOnError(err, "Unable to create RA RPC server")
rpc.NewRegistrationAuthorityServer(ras, &rai) rpc.NewRegistrationAuthorityServer(ras, &rai)
auditlogger.Info(app.VersionString())
err = ras.Start(c) err = ras.Start(c)
cmd.FailOnError(err, "Unable to run RA RPC server") cmd.FailOnError(err, "Unable to run RA RPC server")
} }

View File

@ -23,6 +23,7 @@ func main() {
// Set up logging // Set up logging
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
defer auditlogger.AuditPanic() defer auditlogger.AuditPanic()
@ -46,8 +47,6 @@ func main() {
cmd.FailOnError(err, "Unable to create SA RPC server") cmd.FailOnError(err, "Unable to create SA RPC server")
rpc.NewStorageAuthorityServer(sas, sai) rpc.NewStorageAuthorityServer(sas, sai)
auditlogger.Info(app.VersionString())
err = sas.Start(c) err = sas.Start(c)
cmd.FailOnError(err, "Unable to run SA RPC server") cmd.FailOnError(err, "Unable to run SA RPC server")
} }

View File

@ -27,6 +27,7 @@ func main() {
// Set up logging // Set up logging
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
defer auditlogger.AuditPanic() defer auditlogger.AuditPanic()
@ -75,8 +76,6 @@ func main() {
cmd.FailOnError(err, "Unable to create VA RPC server") cmd.FailOnError(err, "Unable to create VA RPC server")
rpc.NewValidationAuthorityServer(vas, vai) rpc.NewValidationAuthorityServer(vas, vai)
auditlogger.Info(app.VersionString())
err = vas.Start(c) err = vas.Start(c)
cmd.FailOnError(err, "Unable to run VA RPC server") cmd.FailOnError(err, "Unable to run VA RPC server")
} }

View File

@ -66,6 +66,7 @@ func main() {
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
defer auditlogger.AuditPanic() defer auditlogger.AuditPanic()
@ -120,8 +121,6 @@ func main() {
h, err := wfe.Handler() h, err := wfe.Handler()
cmd.FailOnError(err, "Problem setting up HTTP handlers") cmd.FailOnError(err, "Problem setting up HTTP handlers")
auditlogger.Info(app.VersionString())
httpMonitor := metrics.NewHTTPMonitor(stats, h, "WFE") httpMonitor := metrics.NewHTTPMonitor(stats, h, "WFE")
auditlogger.Info(fmt.Sprintf("Server running, listening on %s...\n", c.WFE.ListenAddress)) auditlogger.Info(fmt.Sprintf("Server running, listening on %s...\n", c.WFE.ListenAddress))

View File

@ -239,9 +239,9 @@ func main() {
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
blog.SetAuditLogger(auditlogger) blog.SetAuditLogger(auditlogger)
auditlogger.Info(app.VersionString())
saDbMap, err := sa.NewDbMap(c.CertChecker.DBConnect) saDbMap, err := sa.NewDbMap(c.CertChecker.DBConnect)
cmd.FailOnError(err, "Could not connect to database") cmd.FailOnError(err, "Could not connect to database")

View File

@ -230,14 +230,13 @@ func main() {
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
defer auditlogger.AuditPanic() defer auditlogger.AuditPanic()
blog.SetAuditLogger(auditlogger) blog.SetAuditLogger(auditlogger)
auditlogger.Info(app.VersionString())
go cmd.DebugServer(c.Mailer.DebugAddr) go cmd.DebugServer(c.Mailer.DebugAddr)
// Configure DB // Configure DB

View File

@ -131,6 +131,7 @@ func main() {
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
defer auditlogger.AuditPanic() defer auditlogger.AuditPanic()
@ -141,8 +142,6 @@ func main() {
go cmd.ProfileCmd("OCSP", stats) go cmd.ProfileCmd("OCSP", stats)
auditlogger.Info(app.VersionString())
config := c.OCSPResponder config := c.OCSPResponder
var source cfocsp.Source var source cfocsp.Source
url, err := url.Parse(config.Source) url, err := url.Parse(config.Source)

View File

@ -205,6 +205,7 @@ func main() {
auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats) auditlogger, err := blog.Dial(c.Syslog.Network, c.Syslog.Server, c.Syslog.Tag, stats)
cmd.FailOnError(err, "Could not connect to Syslog") cmd.FailOnError(err, "Could not connect to Syslog")
auditlogger.Info(app.VersionString())
// AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3 // AUDIT[ Error Conditions ] 9cc4d537-8534-4970-8665-4b382abe82f3
defer auditlogger.AuditPanic() defer auditlogger.AuditPanic()
@ -229,8 +230,6 @@ func main() {
} }
}() }()
auditlogger.Info(app.VersionString())
updater := &OCSPUpdater{ updater := &OCSPUpdater{
cac: cac, cac: cac,
dbMap: dbMap, dbMap: dbMap,

View File

@ -119,7 +119,7 @@ func SetSQLDebug(dbMap *gorp.DbMap, state bool) {
// SQLLogger adapts the AuditLogger to a format GORP can use. // SQLLogger adapts the AuditLogger to a format GORP can use.
type SQLLogger struct { type SQLLogger struct {
log *blog.AuditLogger log blog.SyslogWriter
} }
// Printf adapts the AuditLogger to GORP's interface // Printf adapts the AuditLogger to GORP's interface

View File

@ -38,6 +38,7 @@ func initSA(t *testing.T) (*SQLStorageAuthority, clock.FakeClock, func()) {
if err != nil { if err != nil {
t.Fatalf("Failed to create dbMap: %s", err) t.Fatalf("Failed to create dbMap: %s", err)
} }
dbMap.TraceOn("SQL: ", &SQLLogger{log})
fc := clock.NewFake() fc := clock.NewFake()
fc.Add(1 * time.Hour) fc.Add(1 * time.Hour)

View File

@ -7,12 +7,13 @@ import socket
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
import urllib2
import startservers import startservers
class ExitStatus: class ExitStatus:
OK, PythonFailure, NodeFailure, Error, OCSPFailure = range(5) OK, PythonFailure, NodeFailure, Error, OCSPFailure, CTFailure = range(6)
class ProcInfo: class ProcInfo:
@ -62,6 +63,13 @@ def verify_ocsp_revoked(certFile, url):
die(ExitStatus.OCSPFailure) die(ExitStatus.OCSPFailure)
pass pass
def verify_ct_submission(expectedSubmissions, url):
resp = urllib2.urlopen(url)
submissionStr = resp.read()
if int(submissionStr) != expectedSubmissions:
print "Expected %d submissions, found %d" % (expectedSubmissions, int(submissionStr))
die(ExitStatus.CTFailure)
def run_node_test(): def run_node_test():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try: try:
@ -91,6 +99,7 @@ def run_node_test():
# Also verify that the static OCSP responder, which answers with a # Also verify that the static OCSP responder, which answers with a
# pre-signed, long-lived response for the CA cert, also works. # pre-signed, long-lived response for the CA cert, also works.
verify_ocsp_good("../test-ca.der", issuer_ocsp_url) verify_ocsp_good("../test-ca.der", issuer_ocsp_url)
verify_ct_submission(1, "http://localhost:4500/submissions")
if subprocess.Popen(''' if subprocess.Popen('''
node revoke.js %s %s http://localhost:4000/acme/revoke-cert node revoke.js %s %s http://localhost:4000/acme/revoke-cert

View File

@ -10,47 +10,70 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io/ioutil" "io/ioutil"
"log" "log"
"net/http" "net/http"
"sync/atomic"
) )
type ctSubmissionRequest struct { type ctSubmissionRequest struct {
Chain []string `json:"chain"` Chain []string `json:"chain"`
} }
func handler(w http.ResponseWriter, r *http.Request) { type integrationSrv struct {
if r.Method != "POST" || r.URL.Path != "/ct/v1/add-chain" { submissions int64
}
func (is *integrationSrv) handler(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/ct/v1/add-chain":
if r.Method != "POST" {
http.NotFound(w, r)
return
}
bodyBytes, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
var addChainReq ctSubmissionRequest
err = json.Unmarshal(bodyBytes, &addChainReq)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
w.WriteHeader(http.StatusOK)
// id is a sha256 of a random EC key. Generate your own with:
// openssl ecparam -name prime256v1 -genkey -outform der | openssl sha256 -binary | base64
w.Write([]byte(`{
"sct_version": 0,
"id": "8fjM8cvLPOhzCFwI62IYJhjkOcvWFLx1dMJbs0uhxJU=",
"timestamp": 1442400000,
"extensions": "",
"signature": "BAMARzBFAiBB5wKED8KqKhADT37n0y28fZIPiGbCfZRVKq0wNo0hrwIhAOIa2tPBF/rB1y30Y/ROh4LBmJ0mItAbTWy8XZKh7Wcp"
}`))
atomic.AddInt64(&is.submissions, 1)
case "/submissions":
if r.Method != "GET" {
http.NotFound(w, r)
return
}
submissions := atomic.LoadInt64(&is.submissions)
w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("%d", submissions)))
default:
http.NotFound(w, r) http.NotFound(w, r)
return return
} }
bodyBytes, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
var addChainReq ctSubmissionRequest
err = json.Unmarshal(bodyBytes, &addChainReq)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
}
w.WriteHeader(http.StatusOK)
// id is a sha256 of a random EC key. Generate your own with:
// openssl ecparam -name prime256v1 -genkey -outform der | openssl sha256 -binary | base64
w.Write([]byte(`{
"sct_version": 0,
"id": "8fjM8cvLPOhzCFwI62IYJhjkOcvWFLx1dMJbs0uhxJU=",
"timestamp": 1442400000,
"extensions": "",
"signature": "BAMARzBFAiBB5wKED8KqKhADT37n0y28fZIPiGbCfZRVKq0wNo0hrwIhAOIa2tPBF/rB1y30Y/ROh4LBmJ0mItAbTWy8XZKh7Wcp"
}`))
} }
func main() { func main() {
is := integrationSrv{}
s := &http.Server{ s := &http.Server{
Addr: ":4500", Addr: "localhost:4500",
Handler: http.HandlerFunc(handler), Handler: http.HandlerFunc(is.handler),
} }
log.Fatal(s.ListenAndServe()) log.Fatal(s.ListenAndServe())
} }

View File

@ -153,8 +153,9 @@ func (mrw BodylessResponseWriter) Write(buf []byte) (int, error) {
// * Respond http.StatusMethodNotAllowed for HTTP methods other than // * Respond http.StatusMethodNotAllowed for HTTP methods other than
// those listed. // those listed.
// //
// * Never send a body in response to a HEAD request. (Anything // * Never send a body in response to a HEAD request. Anything
// written by the handler will be discarded if the method is HEAD.) // written by the handler will be discarded if the method is HEAD. Also, all
// handlers that accept GET automatically accept HEAD.
func (wfe *WebFrontEndImpl) HandleFunc(mux *http.ServeMux, pattern string, h func(http.ResponseWriter, *http.Request), methods ...string) { func (wfe *WebFrontEndImpl) HandleFunc(mux *http.ServeMux, pattern string, h func(http.ResponseWriter, *http.Request), methods ...string) {
methodsOK := make(map[string]bool) methodsOK := make(map[string]bool)
for _, m := range methods { for _, m := range methods {
@ -169,14 +170,14 @@ func (wfe *WebFrontEndImpl) HandleFunc(mux *http.ServeMux, pattern string, h fun
} }
response.Header().Set("Access-Control-Allow-Origin", "*") response.Header().Set("Access-Control-Allow-Origin", "*")
switch request.Method { // Return a bodyless response to HEAD for any resource that allows GET.
case "HEAD": if _, ok := methodsOK["GET"]; ok && request.Method == "HEAD" {
// We'll be sending an error anyway, but we // We'll be sending an error anyway, but we
// should still comply with HTTP spec by not // should still comply with HTTP spec by not
// sending a body. // sending a body.
response = BodylessResponseWriter{response} response = BodylessResponseWriter{response}
case "OPTIONS": h(response, request)
// TODO, #469 return
} }
if _, ok := methodsOK[request.Method]; !ok { if _, ok := methodsOK[request.Method]; !ok {

View File

@ -307,9 +307,15 @@ func TestHandleFunc(t *testing.T) {
// Disallowed method special case: response to HEAD has got no body // Disallowed method special case: response to HEAD has got no body
runWrappedHandler(&http.Request{Method: "HEAD"}, "GET", "POST") runWrappedHandler(&http.Request{Method: "HEAD"}, "GET", "POST")
test.AssertEquals(t, stubCalled, false) test.AssertEquals(t, stubCalled, true)
test.AssertEquals(t, rw.Body.String(), "") test.AssertEquals(t, rw.Body.String(), "")
test.AssertEquals(t, sortHeader(rw.Header().Get("Allow")), "GET, POST")
// HEAD doesn't work with POST-only endpoints
runWrappedHandler(&http.Request{Method: "HEAD"}, "POST")
test.AssertEquals(t, stubCalled, false)
test.AssertEquals(t, rw.Header().Get("Content-Type"), "application/problem+json")
test.AssertEquals(t, rw.Body.String(), `{"type":"urn:acme:error:malformed","detail":"Method not allowed"}`)
test.AssertEquals(t, rw.Header().Get("Allow"), "POST")
} }
func TestStandardHeaders(t *testing.T) { func TestStandardHeaders(t *testing.T) {