ocsp_helper: allow suppressing output. (#5103)
This adds a configurable output parameter for ocsp_helper, which defaults to stdout. This allows suppressing the stdout output when using ocsp_helper in integration tests. That output was making it hard to see details about failing tests.
This commit is contained in:
parent
d3f2efcb7f
commit
d90a2817c4
|
|
@ -3,6 +3,7 @@
|
||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -39,7 +40,7 @@ func TestPrecertificateOCSP(t *testing.T) {
|
||||||
t.Fatalf("couldn't find rejected precert for %q", domain)
|
t.Fatalf("couldn't find rejected precert for %q", domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
ocspConfig := ocsp_helper.DefaultConfig.WithExpectStatus(ocsp.Good)
|
ocspConfig := ocsp_helper.DefaultConfig.WithExpectStatus(ocsp.Good).WithOutput(ioutil.Discard)
|
||||||
_, err = ocsp_helper.ReqDER(cert.Raw, ocspConfig)
|
_, err = ocsp_helper.ReqDER(cert.Raw, ocspConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("requesting OCSP for rejected precertificate: %s", err)
|
t.Errorf("requesting OCSP for rejected precertificate: %s", err)
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@ import (
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -37,6 +39,7 @@ type Config struct {
|
||||||
ignoreExpiredCerts bool
|
ignoreExpiredCerts bool
|
||||||
expectStatus int
|
expectStatus int
|
||||||
expectReason int
|
expectReason int
|
||||||
|
output io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultConfig is a Config populated with the same defaults as if no
|
// DefaultConfig is a Config populated with the same defaults as if no
|
||||||
|
|
@ -49,6 +52,7 @@ var DefaultConfig = Config{
|
||||||
ignoreExpiredCerts: *ignoreExpiredCerts,
|
ignoreExpiredCerts: *ignoreExpiredCerts,
|
||||||
expectStatus: *expectStatus,
|
expectStatus: *expectStatus,
|
||||||
expectReason: *expectReason,
|
expectReason: *expectReason,
|
||||||
|
output: os.Stdout,
|
||||||
}
|
}
|
||||||
|
|
||||||
var parseFlagsOnce sync.Once
|
var parseFlagsOnce sync.Once
|
||||||
|
|
@ -78,6 +82,14 @@ func (template Config) WithExpectStatus(status int) Config {
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithOutput returns a new Config with the given output,
|
||||||
|
// and all other fields the same as the receiver.
|
||||||
|
func (template Config) WithOutput(w io.Writer) Config {
|
||||||
|
ret := template
|
||||||
|
ret.output = w
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func getIssuer(cert *x509.Certificate) (*x509.Certificate, error) {
|
func getIssuer(cert *x509.Certificate) (*x509.Certificate, error) {
|
||||||
if cert == nil {
|
if cert == nil {
|
||||||
return nil, fmt.Errorf("nil certificate")
|
return nil, fmt.Errorf("nil certificate")
|
||||||
|
|
@ -187,14 +199,14 @@ func ReqDER(der []byte, config Config) (*ocsp.Response, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
httpResp, err := sendHTTPRequest(req, ocspURL, config.method, config.hostOverride)
|
httpResp, err := sendHTTPRequest(req, ocspURL, config.method, config.hostOverride, config.output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Printf("HTTP %d\n", httpResp.StatusCode)
|
fmt.Fprintf(config.output, "HTTP %d\n", httpResp.StatusCode)
|
||||||
for k, v := range httpResp.Header {
|
for k, v := range httpResp.Header {
|
||||||
for _, vv := range v {
|
for _, vv := range v {
|
||||||
fmt.Printf("%s: %s\n", k, vv)
|
fmt.Fprintf(config.output, "%s: %s\n", k, vv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if httpResp.StatusCode != 200 {
|
if httpResp.StatusCode != 200 {
|
||||||
|
|
@ -211,16 +223,22 @@ func ReqDER(der []byte, config Config) (*ocsp.Response, error) {
|
||||||
return parseAndPrint(respBytes, cert, issuer, config)
|
return parseAndPrint(respBytes, cert, issuer, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendHTTPRequest(req []byte, ocspURL *url.URL, method string, host string) (*http.Response, error) {
|
func sendHTTPRequest(
|
||||||
|
req []byte,
|
||||||
|
ocspURL *url.URL,
|
||||||
|
method string,
|
||||||
|
host string,
|
||||||
|
output io.Writer,
|
||||||
|
) (*http.Response, error) {
|
||||||
encodedReq := base64.StdEncoding.EncodeToString(req)
|
encodedReq := base64.StdEncoding.EncodeToString(req)
|
||||||
var httpRequest *http.Request
|
var httpRequest *http.Request
|
||||||
var err error
|
var err error
|
||||||
if method == "GET" {
|
if method == "GET" {
|
||||||
ocspURL.Path = encodedReq
|
ocspURL.Path = encodedReq
|
||||||
fmt.Printf("Fetching %s\n", ocspURL.String())
|
fmt.Fprintf(output, "Fetching %s\n", ocspURL.String())
|
||||||
httpRequest, err = http.NewRequest("GET", ocspURL.String(), http.NoBody)
|
httpRequest, err = http.NewRequest("GET", ocspURL.String(), http.NoBody)
|
||||||
} else if method == "POST" {
|
} else if method == "POST" {
|
||||||
fmt.Printf("POSTing request, reproduce with: curl -i --data-binary @- %s < <(base64 -d <<<%s)\n",
|
fmt.Fprintf(output, "POSTing request, reproduce with: curl -i --data-binary @- %s < <(base64 -d <<<%s)\n",
|
||||||
ocspURL, encodedReq)
|
ocspURL, encodedReq)
|
||||||
httpRequest, err = http.NewRequest("POST", ocspURL.String(), bytes.NewBuffer(req))
|
httpRequest, err = http.NewRequest("POST", ocspURL.String(), bytes.NewBuffer(req))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -259,12 +277,12 @@ func getOCSPURL(cert *x509.Certificate, urlOverride string) (*url.URL, error) {
|
||||||
// checkSignerTimes checks that the OCSP response is within the
|
// checkSignerTimes checks that the OCSP response is within the
|
||||||
// validity window of whichever certificate signed it, and that that
|
// validity window of whichever certificate signed it, and that that
|
||||||
// certificate is currently valid.
|
// certificate is currently valid.
|
||||||
func checkSignerTimes(resp *ocsp.Response, issuer *x509.Certificate) error {
|
func checkSignerTimes(resp *ocsp.Response, issuer *x509.Certificate, output io.Writer) error {
|
||||||
var ocspSigner = issuer
|
var ocspSigner = issuer
|
||||||
if delegatedSigner := resp.Certificate; delegatedSigner != nil {
|
if delegatedSigner := resp.Certificate; delegatedSigner != nil {
|
||||||
ocspSigner = delegatedSigner
|
ocspSigner = delegatedSigner
|
||||||
|
|
||||||
fmt.Printf("Using delegated OCSP signer from response: %s\n",
|
fmt.Fprintf(output, "Using delegated OCSP signer from response: %s\n",
|
||||||
base64.StdEncoding.EncodeToString(ocspSigner.Raw))
|
base64.StdEncoding.EncodeToString(ocspSigner.Raw))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -287,7 +305,7 @@ func checkSignerTimes(resp *ocsp.Response, issuer *x509.Certificate) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseAndPrint(respBytes []byte, cert, issuer *x509.Certificate, config Config) (*ocsp.Response, error) {
|
func parseAndPrint(respBytes []byte, cert, issuer *x509.Certificate, config Config) (*ocsp.Response, error) {
|
||||||
fmt.Printf("\nDecoding body: %s\n", base64.StdEncoding.EncodeToString(respBytes))
|
fmt.Fprintf(config.output, "\nDecoding body: %s\n", base64.StdEncoding.EncodeToString(respBytes))
|
||||||
resp, err := ocsp.ParseResponseForCert(respBytes, cert, issuer)
|
resp, err := ocsp.ParseResponseForCert(respBytes, cert, issuer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("parsing response: %s", err)
|
return nil, fmt.Errorf("parsing response: %s", err)
|
||||||
|
|
@ -306,30 +324,34 @@ func parseAndPrint(respBytes []byte, cert, issuer *x509.Certificate, config Conf
|
||||||
errs = append(errs, fmt.Errorf("NextUpdate is too soon: %s", timeTilExpiry))
|
errs = append(errs, fmt.Errorf("NextUpdate is too soon: %s", timeTilExpiry))
|
||||||
}
|
}
|
||||||
|
|
||||||
err = checkSignerTimes(resp, issuer)
|
err = checkSignerTimes(resp, issuer, config.output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, fmt.Errorf("checking signature on delegated signer: %s", err))
|
errs = append(errs, fmt.Errorf("checking signature on delegated signer: %s", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Print("\n")
|
pr := func(s string, v ...interface{}) {
|
||||||
fmt.Print("Response:\n")
|
fmt.Fprintf(config.output, s, v)
|
||||||
fmt.Printf(" CertStatus %d\n", resp.Status)
|
}
|
||||||
fmt.Printf(" SerialNumber %036x\n", resp.SerialNumber)
|
|
||||||
fmt.Printf(" ProducedAt %s\n", resp.ProducedAt)
|
pr("\n")
|
||||||
fmt.Printf(" ThisUpdate %s\n", resp.ThisUpdate)
|
pr("Response:\n")
|
||||||
fmt.Printf(" NextUpdate %s\n", resp.NextUpdate)
|
pr(" CertStatus %d\n", resp.Status)
|
||||||
fmt.Printf(" RevokedAt %s\n", resp.RevokedAt)
|
pr(" SerialNumber %036x\n", resp.SerialNumber)
|
||||||
fmt.Printf(" RevocationReason %d\n", resp.RevocationReason)
|
pr(" ProducedAt %s\n", resp.ProducedAt)
|
||||||
fmt.Printf(" SignatureAlgorithm %s\n", resp.SignatureAlgorithm)
|
pr(" ThisUpdate %s\n", resp.ThisUpdate)
|
||||||
fmt.Printf(" Extensions %#v\n", resp.Extensions)
|
pr(" NextUpdate %s\n", resp.NextUpdate)
|
||||||
|
pr(" RevokedAt %s\n", resp.RevokedAt)
|
||||||
|
pr(" RevocationReason %d\n", resp.RevocationReason)
|
||||||
|
pr(" SignatureAlgorithm %s\n", resp.SignatureAlgorithm)
|
||||||
|
pr(" Extensions %#v\n", resp.Extensions)
|
||||||
if resp.Certificate == nil {
|
if resp.Certificate == nil {
|
||||||
fmt.Print(" Certificate: nil\n")
|
pr(" Certificate: nil\n")
|
||||||
} else {
|
} else {
|
||||||
fmt.Print(" Certificate:\n")
|
pr(" Certificate:\n")
|
||||||
fmt.Printf(" Subject: %s\n", resp.Certificate.Subject)
|
pr(" Subject: %s\n", resp.Certificate.Subject)
|
||||||
fmt.Printf(" Issuer: %s\n", resp.Certificate.Issuer)
|
pr(" Issuer: %s\n", resp.Certificate.Issuer)
|
||||||
fmt.Printf(" NotBefore: %s\n", resp.Certificate.NotBefore)
|
pr(" NotBefore: %s\n", resp.Certificate.NotBefore)
|
||||||
fmt.Printf(" NotAfter: %s\n", resp.Certificate.NotAfter)
|
pr(" NotAfter: %s\n", resp.Certificate.NotAfter)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue