Merge branch 'release/21.09'

* release/21.09:
  Bump boulder version to release-2021-08-31
  Move patch files to subdir for cleaner main dir
  Add some troubleshooting info on CAA (#23)
  Make initial setup phase more robust
  Make initial setup phase more robust
  Show more information on page to diagnose initial problems
  Suppress checksum warning on "message repeated X times" lines
  Show more information on page to diagnose initial problems
This commit is contained in:
Arjan H
2021-09-02 18:54:21 +02:00
30 changed files with 264 additions and 115 deletions

View File

@@ -105,6 +105,12 @@ Some log files to check in case of issues are:
If you get "No valid IP addresses found for <hostname>" in /etc/nginx/ssl/acme_tiny.log, solve it by entering the hostname in your local DNS. Same for "Could not resolve host: <hostname>" in /var/log/labca.err.
When issuing a certificate, LabCA/boulder checks for CAA (Certification Authority Authorization) records in DNS, which specify what CAs are allowed to issue certificates for the domain. If you get an error like "SERVFAIL looking up CAA for internal" or "CAA record for ca01.foo.internal prevents issuance", you can try to add something like this to your DNS domain:
```
foo.internal. CAA 0 issue "foo.internal"
```
See also the [Let's Encrypt&trade; page on CAA](https://letsencrypt.org/docs/caa/).
### NOTE
Although LabCA tries to be as robust as possible, use it at your own risk. If you depend on it, make sure that you know what you are doing!

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -e
set -euo pipefail
LOGFILE=/home/labca/logs/commander.log
@@ -18,8 +18,15 @@ function wait_server() {
local status=0
local cnt=0
set +e
res=$(curl -o /dev/null -sSLk --head --write-out '%{http_code}\n' $url 2>&1)
if [ $? -ne 0 ]; then
echo -n $res
fi
set -e
while [ $cnt -lt 40 ] && [ "$status" != "200" ]; do
status=$(curl -o /dev/null -sSL --head --write-out '%{http_code}\n' $url)
status=$(curl -o /dev/null -sSL --head --write-out '%{http_code}\n' $url 2>>$LOGFILE)
let cnt=$cnt+1
if [ "$status" != "200" ]; then
sleep 5
@@ -70,17 +77,25 @@ case $txt in
service nginx restart
;;
"log-cert")
tail -200 /etc/nginx/ssl/acme_tiny.log
[ -f /etc/nginx/ssl/acme_tiny.log ] && tail -200 /etc/nginx/ssl/acme_tiny.log || /bin/true
exit 0
;;
"log-commander")
[ -f $LOGFILE ] && tail -200 $LOGFILE || /bin/true
exit 0
;;
"log-boulder")
cd /home/labca/boulder
docker-compose logs -f --no-color --tail=50 boulder
;;
"log-boulder-notail")
cd /home/labca/boulder
docker-compose logs --no-color --tail=50 boulder
;;
"log-audit")
cd /home/labca/boulder
docker-compose logs --no-color boulder | grep "\[AUDIT\]" | grep -v "grpc: parseServiceConfig error unmarshaling due to unexpected end of JSON input" | tail -50
docker-compose logs -f --no-color --tail=0 boulder
docker-compose logs -f --no-color --tail=0 boulder | grep "\[AUDIT\]"
;;
"log-activity")
cd /home/labca/boulder
@@ -92,11 +107,19 @@ case $txt in
cd /home/labca/boulder
docker-compose logs -f --no-color --tail=50 labca
;;
"log-labca-notail")
cd /home/labca/boulder
docker-compose logs --no-color --tail=50 labca
;;
"log-labca-err")
[ -f /var/log/labca.err ] && tail -200 /var/log/labca.err || /bin/true
exit 0
;;
"log-web")
tail -f -n 50 /var/log/nginx/access.log
;;
"log-weberr")
tail -200 /var/log/nginx/error.log
[ -f /var/log/nginx/error.log ] && tail -200 /var/log/nginx/error.log || /bin/true
exit 0
;;
"log-components")

View File

@@ -47,6 +47,9 @@ func _parseLine(line string, loc *time.Location) Activity {
re := regexp.MustCompile("^.*\\|\\s*(\\S)(\\S+) (\\S+) (\\S+) (.*)$")
result := re.FindStringSubmatch(line)
if len(result) == 0 {
return activity
}
activity.Class = ""
if result[1] == "W" {

View File

@@ -186,10 +186,18 @@ func (cfg *SetupConfig) Validate(orgRequired bool) bool {
cfg.Errors["LockdownDomains"] = "Please enter one or more domains that this PKI host is locked down to"
}
if cfg.DomainMode == "lockdown" && strings.HasPrefix(cfg.LockdownDomains, ".") {
cfg.Errors["LockdownDomains"] = "Domain should not start with a dot"
}
if cfg.DomainMode == "whitelist" && strings.TrimSpace(cfg.WhitelistDomains) == "" {
cfg.Errors["WhitelistDomains"] = "Please enter one or more domains that are whitelisted for this PKI host"
}
if cfg.DomainMode == "whitelist" && strings.HasPrefix(cfg.WhitelistDomains, ".") {
cfg.Errors["WhitelistDomains"] = "Domain should not start with a dot"
}
return len(cfg.Errors) == 0
}
@@ -210,7 +218,7 @@ func getSession(w http.ResponseWriter, r *http.Request) *sessions.Session {
}
func errorHandler(w http.ResponseWriter, r *http.Request, err error, status int) {
log.Printf("errorHandler: %v", err)
log.Printf("errorHandler: err=%v\n", err)
w.WriteHeader(status)
@@ -234,8 +242,34 @@ func errorHandler(w http.ResponseWriter, r *http.Request, err error, status int)
}
fmt.Print(strings.Join(lines, "\n"))
render(w, r, "error", map[string]interface{}{"Message": "Some unexpected error occurred!"})
// TODO: send email eventually with info on the error
if viper.GetBool("config.complete") {
render(w, r, "error", map[string]interface{}{"Message": "Some unexpected error occurred!"})
} else {
// ONLY in the setup phase to prevent leaking too much details to users
var FileErrors []interface{}
data := getLog(w, r, "cert")
if data != "" {
FileErrors = append(FileErrors, map[string]interface{}{"FileName": "/etc/nginx/ssl/acme_tiny.log", "Content": data})
}
data = getLog(w, r, "commander")
if data != "" {
FileErrors = append(FileErrors, map[string]interface{}{"FileName": "/home/labca/logs/commander.log", "Content": data})
}
data = getLog(w, r, "labca-notail")
if data != "" {
FileErrors = append(FileErrors, map[string]interface{}{"FileName": "docker-compose logs labca", "Content": data})
}
data = getLog(w, r, "boulder-notail")
if data != "" {
FileErrors = append(FileErrors, map[string]interface{}{"FileName": "docker-compose logs boulder", "Content": data})
}
data = getLog(w, r, "labca-err")
if data != "" {
FileErrors = append(FileErrors, map[string]interface{}{"FileName": "/var/log/labca.err", "Content": data})
}
render(w, r, "error", map[string]interface{}{"Message": "Some unexpected error occurred!", "FileErrors": FileErrors})
}
}
}
@@ -340,7 +374,7 @@ func loginHandler(w http.ResponseWriter, r *http.Request) {
RequestBase: r.Header.Get("X-Request-Base"),
}
if reg.Validate(false, false) == false {
if !reg.Validate(false, false) {
render(w, r, "login", map[string]interface{}{"User": reg, "IsLogin": true})
return
}
@@ -584,7 +618,7 @@ func (cfg *EmailConfig) Validate() bool {
cfg.Errors["EmailPwd"] = "Could not encrypt this password: " + err.Error()
}
if cfg.DoEmail == false {
if !cfg.DoEmail {
return len(cfg.Errors) == 0
}
@@ -945,7 +979,7 @@ func _managePost(w http.ResponseWriter, r *http.Request) {
}
}
if !actionKnown {
errorHandler(w, r, fmt.Errorf("Unknown manage action '%s'", action), http.StatusBadRequest)
errorHandler(w, r, fmt.Errorf("unknown manage action '%s'", action), http.StatusBadRequest)
return
}
@@ -1164,7 +1198,7 @@ func logsHandler(w http.ResponseWriter, r *http.Request) {
wsurl = ""
data = getLog(w, r, logType)
default:
errorHandler(w, r, fmt.Errorf("Unknown log type '%s'", logType), http.StatusBadRequest)
errorHandler(w, r, fmt.Errorf("unknown log type '%s'", logType), http.StatusBadRequest)
return
}
@@ -1233,7 +1267,7 @@ func showLog(ws *websocket.Conn, logType string) {
scanner := bufio.NewScanner(conn)
for scanner.Scan() {
msg := scanner.Text()
if logType != "audit" || strings.Index(msg, "[AUDIT]") > -1 {
if logType != "audit" || strings.Contains(msg, "[AUDIT]") {
ws.SetWriteDeadline(time.Now().Add(writeWait))
if err := ws.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
// Probably "websocket: close sent"
@@ -1245,8 +1279,6 @@ func showLog(ws *websocket.Conn, logType string) {
wsErrorHandler(err)
return
}
return
}
func reader(ws *websocket.Conn) {
@@ -1300,7 +1332,7 @@ func wsHandler(w http.ResponseWriter, r *http.Request) {
case "labca":
case "web":
default:
errorHandler(w, r, fmt.Errorf("Unknown log type '%s'", logType), http.StatusBadRequest)
errorHandler(w, r, fmt.Errorf("unknown log type '%s'", logType), http.StatusBadRequest)
return
}
@@ -1398,7 +1430,7 @@ func _certCreate(w http.ResponseWriter, r *http.Request, certBase string, isRoot
ci.Certificate = r.Form.Get("certificate")
ci.RequestBase = r.Header.Get("X-Request-Base")
if ci.Validate() == false {
if !ci.Validate() {
render(w, r, "cert:manage", map[string]interface{}{"CertificateInfo": ci, "Progress": _progress(certBase), "HelpText": _helptext(certBase)})
return false
}
@@ -1664,7 +1696,7 @@ func _setupAdminUser(w http.ResponseWriter, r *http.Request) bool {
RequestBase: r.Header.Get("X-Request-Base"),
}
if reg.Validate(true, false) == false {
if !reg.Validate(true, false) {
render(w, r, "register:manage", map[string]interface{}{"User": reg, "IsLogin": true, "Progress": _progress("register"), "HelpText": _helptext("register")})
return false
}
@@ -1727,7 +1759,7 @@ func _setupBaseConfig(w http.ResponseWriter, r *http.Request) bool {
RequestBase: r.Header.Get("X-Request-Base"),
}
if cfg.Validate(false) == false {
if !cfg.Validate(false) {
render(w, r, "setup:manage", map[string]interface{}{"SetupConfig": cfg, "Progress": _progress("setup"), "HelpText": _helptext("setup")})
return false
}
@@ -1759,7 +1791,7 @@ func _setupBaseConfig(w http.ResponseWriter, r *http.Request) bool {
}
func setupHandler(w http.ResponseWriter, r *http.Request) {
if viper.GetBool("config.complete") == true {
if viper.GetBool("config.complete") {
render(w, r, "index:manage", map[string]interface{}{"Message": template.HTML("Setup already completed! Go <a href=\"" + r.Header.Get("X-Request-Base") + "/\">home</a>")})
return
}
@@ -1852,33 +1884,60 @@ func finalHandler(w http.ResponseWriter, r *http.Request) {
return
}
// Don't let the retry mechanism trigger a certificate request and restart!
if r.Header.Get("X-Requested-With") == "XMLHttpRequest" {
render(w, r, "index", map[string]interface{}{"Message": "Retry OK"})
} else {
// 9. Setup our own web certificate
if !_hostCommand(w, r, "acme-request") {
http.Redirect(w, r, r.Header.Get("X-Request-Base")+"/logs/cert", http.StatusSeeOther)
return
t := viper.GetTime("config.cert_requested")
if !t.IsZero() && t.After(time.Now().Add(-5*time.Minute)) {
// Too soon
if r.Header.Get("X-Requested-With") == "XMLHttpRequest" {
w.Header().Set("Content-Type", "application/json")
if viper.GetBool("config.error") {
viper.Set("config.cert_requested", nil)
viper.WriteConfig()
}
json.NewEncoder(w).Encode(map[string]interface{}{"complete": viper.GetBool("config.complete"), "error": viper.GetBool("config.error")})
} else {
render(w, r, "polling:manage", map[string]interface{}{"Progress": _progress("polling"), "HelpText": _helptext("polling")})
}
return
}
// 10. remove the temporary bit from nginx config
if !_hostCommand(w, r, "nginx-remove-redirect") {
return
}
// 11. reload nginx
if !_hostCommand(w, r, "nginx-reload") {
return
}
viper.Set("config.complete", true)
viper.Set("config.cert_requested", time.Now())
if viper.GetBool("config.error") {
viper.Set("config.error", false)
}
viper.WriteConfig()
// 9. Setup our own web certificate
if !_hostCommand(w, r, "acme-request") {
viper.Set("config.error", true)
viper.WriteConfig()
http.Redirect(w, r, r.Header.Get("X-Request-Base")+"/logs/cert", http.StatusSeeOther)
return
}
// 10. remove the temporary bit from nginx config
if !_hostCommand(w, r, "nginx-remove-redirect") {
return
}
// 11. reload nginx
if !_hostCommand(w, r, "nginx-reload") {
return
}
viper.Set("config.complete", true)
viper.WriteConfig()
if r.Header.Get("X-Requested-With") == "XMLHttpRequest" {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(map[string]interface{}{"complete": viper.GetBool("config.complete")})
} else {
render(w, r, "final:manage", map[string]interface{}{"RequestBase": r.Header.Get("X-Request-Base"), "Progress": _progress("final"), "HelpText": _helptext("final")})
}
}
func showErrorHandler(w http.ResponseWriter, r *http.Request) {
errorHandler(w, r, nil, http.StatusInternalServerError)
}
// RangeStructer takes the first argument, which must be a struct, and
// returns the value of each field in a slice. It will return nil
// if there are no arguments or first argument is not a struct
@@ -2064,7 +2123,7 @@ func certificateHandler(w http.ResponseWriter, r *http.Request) {
func certRevokeHandler(w http.ResponseWriter, r *http.Request) {
if !viper.GetBool("config.complete") {
errorHandler(w, r, errors.New("Method not allowed at this point"), http.StatusMethodNotAllowed)
errorHandler(w, r, errors.New("method not allowed at this point"), http.StatusMethodNotAllowed)
return
}
@@ -2402,6 +2461,7 @@ func main() {
r.HandleFunc("/about", aboutHandler).Methods("GET")
r.HandleFunc("/manage", manageHandler).Methods("GET", "POST")
r.HandleFunc("/final", finalHandler).Methods("GET")
r.HandleFunc("/error", showErrorHandler).Methods("GET")
r.HandleFunc("/login", loginHandler).Methods("GET", "POST")
r.HandleFunc("/logout", logoutHandler).Methods("GET")
r.HandleFunc("/logs/{type}", logsHandler).Methods("GET")

View File

@@ -1,4 +1,13 @@
{{ define "body" }}
<h3>OOPS</h3>
<p>{{ .Message }}</p>
{{ if .FileErrors }}
<br/>
<h4>Diagnostics</h4>
<p>These log files might help you determine what the problem is:</p>
{{ range $item := .FileErrors }}
<p><b>{{ $item.FileName }}</b></p>
<pre>{{ $item.Content }}</pre>
{{ end }}
{{ end }}
{{ end }}

49
install
View File

@@ -24,7 +24,7 @@ dockerComposeVersion="1.28.5"
labcaUrl="https://github.com/hakwerk/labca/"
boulderUrl="https://github.com/letsencrypt/boulder/"
boulderTag="release-2021-08-02"
boulderTag="release-2021-08-31"
#
# Color configuration
@@ -520,51 +520,54 @@ config_boulder() {
msg_info "$msg"
cd "$boulderDir"
sudo -u labca -H patch -p1 < $cloneDir/docker-compose.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/docker-compose.patch &>>$installLog
cp docker-compose.yml "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/cmd_shell.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/cmd_shell.patch &>>$installLog
cp cmd/shell.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/core_interfaces.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/core_interfaces.patch &>>$installLog
cp core/interfaces.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/policy_pa.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/policy_pa.patch &>>$installLog
cp policy/pa.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/ra_ra.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/ra_ra.patch &>>$installLog
cp ra/ra.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/reloader_reloader.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/reloader_reloader.patch &>>$installLog
cp reloader/reloader.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/mail_mailer.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/mail_mailer.patch &>>$installLog
cp mail/mailer.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/expiration-mailer_main.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/expiration-mailer_main.patch &>>$installLog
cp cmd/expiration-mailer/main.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/notify-mailer_main.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/notify-mailer_main.patch &>>$installLog
cp cmd/notify-mailer/main.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/contact-auditor_main.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/contact-auditor_main.patch &>>$installLog
cp cmd/contact-auditor/main.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 < $cloneDir/bad-key-revoker_main.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/bad-key-revoker_main.patch &>>$installLog
cp cmd/bad-key-revoker/main.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 -o "$boulderLabCADir/entrypoint.sh" < $cloneDir/entrypoint.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/startservers.py" < $cloneDir/startservers.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/startservers.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/log-validator_main.patch &>>$installLog
cp cmd/log-validator/main.go "$boulderLabCADir/.backup/"
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/ca-a.json" < $cloneDir/test_config_ca_a.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/ca-b.json" < $cloneDir/test_config_ca_b.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/entrypoint.sh" < $cloneDir/patches/entrypoint.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/startservers.py" < $cloneDir/patches/startservers.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/startservers.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/expiration-mailer.json" < $cloneDir/config_expiration-mailer.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/notify-mailer.json" < $cloneDir/config_notify-mailer.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/bad-key-revoker.json" < $cloneDir/config_bad-key-revoker.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/ocsp-responder.json" < $cloneDir/config_ocsp-responder.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/publisher.json" < $cloneDir/config_publisher.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/ca-a.json" < $cloneDir/patches/test_config_ca_a.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/ca-b.json" < $cloneDir/patches/test_config_ca_b.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/expiration-mailer.json" < $cloneDir/patches/config_expiration-mailer.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/notify-mailer.json" < $cloneDir/patches/config_notify-mailer.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/bad-key-revoker.json" < $cloneDir/patches/config_bad-key-revoker.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/ocsp-responder.json" < $cloneDir/patches/config_ocsp-responder.patch &>>$installLog
sudo -u labca -H patch -p1 -o "$boulderLabCADir/config/publisher.json" < $cloneDir/patches/config_publisher.patch &>>$installLog
sed -i -e "s|https://letsencrypt.org/docs/rate-limits/|http://$LABCA_FQDN/rate-limits|" errors/errors.go &>>$installLog
cp errors/errors.go "$boulderLabCADir/.backup/"
@@ -575,7 +578,7 @@ config_boulder() {
mkdir -p "cmd/mail-tester"
cp $cloneDir/mail-tester.go cmd/mail-tester/main.go
sudo -u labca -H patch -p1 < $cloneDir/db_migrations.patch &>>$installLog
sudo -u labca -H patch -p1 < $cloneDir/patches/db_migrations.patch &>>$installLog
cp sa/_db/migrations/20210223140000_CombinedSchema.sql "$boulderLabCADir/.backup/"
mkdir -p $baseDir/backup

View File

@@ -1,5 +1,5 @@
diff --git a/cmd/bad-key-revoker/main.go b/cmd/bad-key-revoker/main.go
index 2d6d17f16..e09948cfc 100644
index 3f3a953d3..c02b4dfc1 100644
--- a/cmd/bad-key-revoker/main.go
+++ b/cmd/bad-key-revoker/main.go
@@ -15,6 +15,7 @@ import (
@@ -10,7 +10,7 @@ index 2d6d17f16..e09948cfc 100644
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/db"
@@ -348,6 +349,9 @@ func main() {
@@ -352,6 +353,9 @@ func main() {
TLS cmd.TLSConfig
RAService *cmd.GRPCClientConfig
@@ -20,7 +20,7 @@ index 2d6d17f16..e09948cfc 100644
// MaximumRevocations specifies the maximum number of certificates associated with
// a key hash that bad-key-revoker will attempt to revoke. If the number of certificates
// is higher than MaximumRevocations bad-key-revoker will error out and refuse to
@@ -375,6 +379,12 @@ func main() {
@@ -385,6 +389,12 @@ func main() {
Syslog cmd.SyslogConfig
Beeline cmd.BeelineConfig
@@ -33,7 +33,7 @@ index 2d6d17f16..e09948cfc 100644
}
configPath := flag.String("config", "", "File path to the configuration file for this service")
flag.Parse()
@@ -424,6 +434,32 @@ func main() {
@@ -434,6 +444,32 @@ func main() {
cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to RA")
rac := rapb.NewRegistrationAuthorityClient(conn)
@@ -66,7 +66,7 @@ index 2d6d17f16..e09948cfc 100644
var smtpRoots *x509.CertPool
if config.BadKeyRevoker.Mailer.SMTPTrustedRootFile != "" {
pem, err := ioutil.ReadFile(config.BadKeyRevoker.Mailer.SMTPTrustedRootFile)
@@ -445,6 +481,7 @@ func main() {
@@ -455,6 +491,7 @@ func main() {
config.BadKeyRevoker.Mailer.Username,
smtpPassword,
smtpRoots,

View File

@@ -1,8 +1,8 @@
diff --git a/core/interfaces.go b/core/interfaces.go
index 4e03131cb..43468ca3b 100644
index d19eb4fb8..3ae50d737 100644
--- a/core/interfaces.go
+++ b/core/interfaces.go
@@ -94,6 +94,7 @@ type PolicyAuthority interface {
@@ -91,6 +91,7 @@ type PolicyAuthority interface {
WillingToIssueWildcards(identifiers []identifier.ACMEIdentifier) error
ChallengesFor(domain identifier.ACMEIdentifier) ([]Challenge, error)
ChallengeTypeEnabled(t AcmeChallenge) bool

View File

@@ -1,5 +1,5 @@
diff --git a/cmd/expiration-mailer/main.go b/cmd/expiration-mailer/main.go
index 9f56157dd..8cc77676c 100644
index f6b02976e..0b00b794d 100644
--- a/cmd/expiration-mailer/main.go
+++ b/cmd/expiration-mailer/main.go
@@ -20,6 +20,7 @@ import (
@@ -9,8 +9,8 @@ index 9f56157dd..8cc77676c 100644
+ "github.com/letsencrypt/boulder/bdns"
"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/core"
"github.com/letsencrypt/boulder/db"
@@ -35,7 +36,7 @@ import (
corepb "github.com/letsencrypt/boulder/core/proto"
@@ -36,7 +37,7 @@ import (
const (
defaultNagCheckInterval = 24 * time.Hour
@@ -19,7 +19,7 @@ index 9f56157dd..8cc77676c 100644
)
type regStore interface {
@@ -384,6 +385,9 @@ type config struct {
@@ -385,6 +386,9 @@ type config struct {
TLS cmd.TLSConfig
SAService *cmd.GRPCClientConfig
@@ -29,7 +29,7 @@ index 9f56157dd..8cc77676c 100644
// Path to a file containing a list of trusted root certificates for use
// during the SMTP connection (as opposed to the gRPC connections).
SMTPTrustedRootFile string
@@ -393,6 +397,12 @@ type config struct {
@@ -394,6 +398,12 @@ type config struct {
Syslog cmd.SyslogConfig
Beeline cmd.BeelineConfig
@@ -42,7 +42,7 @@ index 9f56157dd..8cc77676c 100644
}
func initStats(stats prometheus.Registerer) mailerStats {
@@ -510,6 +520,32 @@ func main() {
@@ -511,6 +521,32 @@ func main() {
cmd.FailOnError(err, "Failed to load credentials and create gRPC connection to SA")
sac := bgrpc.NewStorageAuthorityClient(sapb.NewStorageAuthorityClient(conn))
@@ -75,7 +75,7 @@ index 9f56157dd..8cc77676c 100644
var smtpRoots *x509.CertPool
if c.Mailer.SMTPTrustedRootFile != "" {
pem, err := ioutil.ReadFile(c.Mailer.SMTPTrustedRootFile)
@@ -545,6 +581,7 @@ func main() {
@@ -546,6 +582,7 @@ func main() {
c.Mailer.Username,
smtpPassword,
smtpRoots,

View File

@@ -0,0 +1,15 @@
diff --git a/cmd/log-validator/main.go b/cmd/log-validator/main.go
index fdab2ac6..bb136880 100644
--- a/cmd/log-validator/main.go
+++ b/cmd/log-validator/main.go
@@ -52,8 +52,8 @@ func lineValid(text string) error {
if strings.Contains(text, errorPrefix) {
return nil
}
- // Check the extracted checksum against the computed checksum
- if computedChecksum := blog.LogLineChecksum(line); checksum != computedChecksum {
+ // Check the extracted checksum against the computed checksum, but ignore "message repeated X times" lines
+ if computedChecksum := blog.LogLineChecksum(line); checksum != computedChecksum && checksum != "message" {
return fmt.Errorf("%s invalid checksum (expected %q, got %q)", errorPrefix, computedChecksum, checksum)
}
return nil

View File

@@ -1,5 +1,5 @@
diff --git a/ra/ra.go b/ra/ra.go
index 58fa25ca8..09d2a3579 100644
index 1023d0232..3f8d86d87 100644
--- a/ra/ra.go
+++ b/ra/ra.go
@@ -31,7 +31,6 @@ import (
@@ -10,7 +10,7 @@ index 58fa25ca8..09d2a3579 100644
"github.com/letsencrypt/boulder/probs"
pubpb "github.com/letsencrypt/boulder/publisher/proto"
rapb "github.com/letsencrypt/boulder/ra/proto"
@@ -446,7 +445,7 @@ func (ra *RegistrationAuthorityImpl) validateContacts(ctx context.Context, conta
@@ -435,7 +434,7 @@ func (ra *RegistrationAuthorityImpl) validateContacts(ctx context.Context, conta
contact,
)
}

View File

@@ -2,7 +2,7 @@ diff --git a/test/config/ca-a.json b/test/config/ca-a.json
index 92b32f094..e220d7d4f 100644
--- a/test/config/ca-a.json
+++ b/test/config/ca-a.json
@@ -58,19 +58,7 @@
@@ -60,19 +60,7 @@
"crlURL": "http://example.com/crl",
"location": {
"configFile": "test/test-ca.key-pkcs11.json",

View File

@@ -2,7 +2,7 @@ diff --git a/test/config/ca-b.json b/test/config/ca-b.json
index 6c7d9d272..4e428bc4a 100644
--- a/test/config/ca-b.json
+++ b/test/config/ca-b.json
@@ -58,19 +58,7 @@
@@ -60,19 +60,7 @@
"crlURL": "http://example.com/crl",
"location": {
"configFile": "test/test-ca.key-pkcs11.json",

File diff suppressed because one or more lines are too long

View File

@@ -182,7 +182,6 @@ $(function() {
positionFooter();
});
$("#restart-button").click(function(evt) {
$("#pre-restart-1").hide();
$("#pre-restart-2").hide();
@@ -190,53 +189,69 @@ $(function() {
$("#restarting").show();
$(window).resize();
var args = window.location.href.split('?')[1].split('=');
var args = [ "unknown" ];
if (window.location.href.indexOf('?') > 0 ) {
var tmp = window.location.href.split('?');
if (tmp.length > 1) {
args = tmp[1].split('=');
}
}
var secret = "";
var nextPath = "";
if (args[0] == "restart") {
secret = args[1];
nextPath = "/restart";
}
var pollTimer;
var baseUrl = window.location.href.substr(0, window.location.href.indexOf("?")).replace("/wait", "");
$.ajax(baseUrl + "/restart", {
var baseUrl = window.location.href;
if (baseUrl.indexOf("?") > 0) {
baseUrl = baseUrl.substr(0, baseUrl.indexOf("?"));
}
if (baseUrl.endsWith("/wait")) {
baseUrl = baseUrl.substr(0, baseUrl.length-5);
}
$.ajax(baseUrl + nextPath, {
data: {
token: secret,
},
timeout: 3000
timeout: 30000
})
.done(function(data) {
clearInterval(pollTimer);
window.location.href = baseUrl + "/setup";
})
.fail(function(xhr, status, err) {
if (err === "timeout") {
// Assume that the restart was initiated... Wait for server to be available again.
var ctr = 0;
pollTimer = setInterval(pollServer, 3000);
pollServer();
nextPath = "";
// Assume that the restart was initiated... Wait for server to be available again.
var ctr = 0;
pollTimer = setInterval(pollServer, 3000);
function pollServer() {
if (ctr > 59) {
function pollServer() {
if (ctr > 59) {
clearInterval(pollTimer);
$("img#restart-spinner").parent().text("timeout").addClass("error");
} else if (ctr < 10) {
// No need to try immediately, the server is restarting
ctr++;
} else {
$.ajax(baseUrl + nextPath, {
timeout: 2500
})
.done(function(data) {
clearInterval(pollTimer);
$("img#restart-spinner").parent().text("timeout").addClass("error");
} else {
$.ajax(baseUrl + "/setup", {
timeout: 2500
})
.done(function(data) {
window.location.href = baseUrl;
})
.fail(function(xhr, status, err) {
ctr++;
if ((typeof err === 'undefined' || err === "") && status === "error") {
// Probably because the certificate has changed
clearInterval(pollTimer);
window.location.href = baseUrl + "/setup";
})
.fail(function(xhr, status, err) {
ctr++;
});
}
window.location.href = baseUrl;
}
});
}
} else {
clearInterval(pollTimer);
$("img#restart-spinner").parent().text(err).addClass("error");
}
});
@@ -246,23 +261,37 @@ $(function() {
if ( $("img#wrapup-spinner").length ) {
var targetUrl = window.location.href.replace("/setup", "/final");
var ctr = 0;
var pollTimer = setInterval(pollServer, 3000);
pollServer();
var pollTimer = setInterval(pollServer, 5000);
function pollServer() {
if (ctr > 20) {
if (ctr > 60) {
clearInterval(pollTimer);
$("img#wrapup-spinner").parent().text("timeout").addClass("error");
} else if (ctr < 5) {
// No need to try immediately, the server won't be ready this quick
ctr++;
} else {
$.ajax(targetUrl, {
timeout: 2500
timeout: 4500
})
.done(function(data) {
clearInterval(pollTimer);
window.location.href = targetUrl;
if (data.error) {
clearInterval(pollTimer);
targetUrl = targetUrl.replace("/final", "/error");
window.location.href = targetUrl;
} else if (data.complete) {
clearInterval(pollTimer);
targetUrl = targetUrl.replace("/final", "");
window.location.href = targetUrl;
}
})
.fail(function(xhr, status, err) {
ctr++;
if ((typeof err === 'undefined' || err === "") && status === "error") {
// Probably because the certificate has changed
clearInterval(pollTimer);
window.location.href = targetUrl;
}
});
}
}