Add markInvalid arg to storeError for invalidating challenge

This commit is contained in:
max furman 2021-03-29 22:58:26 -07:00
parent 6b8585c702
commit 440678cb62
5 changed files with 190 additions and 109 deletions

View file

@ -25,7 +25,7 @@ type Clock struct{}
// Now returns the UTC time rounded to seconds. // Now returns the UTC time rounded to seconds.
func (c *Clock) Now() time.Time { func (c *Clock) Now() time.Time {
return time.Now().UTC().Round(time.Second) return time.Now().UTC().Truncate(time.Second)
} }
var clock Clock var clock Clock

View file

@ -14,6 +14,7 @@ import (
"io/ioutil" "io/ioutil"
"net" "net"
"net/http" "net/http"
"net/url"
"strings" "strings"
"time" "time"
@ -49,7 +50,7 @@ func (ch *Challenge) ToLog() (interface{}, error) {
// updated. // updated.
func (ch *Challenge) Validate(ctx context.Context, db DB, jwk *jose.JSONWebKey, vo *ValidateChallengeOptions) error { func (ch *Challenge) Validate(ctx context.Context, db DB, jwk *jose.JSONWebKey, vo *ValidateChallengeOptions) error {
// If already valid or invalid then return without performing validation. // If already valid or invalid then return without performing validation.
if ch.Status == StatusValid || ch.Status == StatusInvalid { if ch.Status != StatusPending {
return nil return nil
} }
switch ch.Type { switch ch.Type {
@ -65,32 +66,32 @@ func (ch *Challenge) Validate(ctx context.Context, db DB, jwk *jose.JSONWebKey,
} }
func http01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, vo *ValidateChallengeOptions) error { func http01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, vo *ValidateChallengeOptions) error {
url := fmt.Sprintf("http://%s/.well-known/acme-challenge/%s", ch.Value, ch.Token) url := &url.URL{Scheme: "http", Host: ch.Value, Path: fmt.Sprintf("/.well-known/acme-challenge/%s", ch.Token)}
resp, err := vo.HTTPGet(url) resp, err := vo.HTTPGet(url.String())
if err != nil { if err != nil {
return storeError(ctx, ch, db, WrapError(ErrorConnectionType, err, return storeError(ctx, db, ch, false, WrapError(ErrorConnectionType, err,
"error doing http GET for url %s", url)) "error doing http GET for url %s", url))
} }
defer resp.Body.Close()
if resp.StatusCode >= 400 { if resp.StatusCode >= 400 {
return storeError(ctx, ch, db, NewError(ErrorConnectionType, return storeError(ctx, db, ch, false, NewError(ErrorConnectionType,
"error doing http GET for url %s with status code %d", url, resp.StatusCode)) "error doing http GET for url %s with status code %d", url, resp.StatusCode))
} }
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body) body, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
return WrapErrorISE(err, "error reading "+ return WrapErrorISE(err, "error reading "+
"response body for url %s", url) "response body for url %s", url)
} }
keyAuth := strings.Trim(string(body), "\r\n") keyAuth := strings.TrimSpace(string(body))
expected, err := KeyAuthorization(ch.Token, jwk) expected, err := KeyAuthorization(ch.Token, jwk)
if err != nil { if err != nil {
return err return err
} }
if keyAuth != expected { if keyAuth != expected {
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"keyAuthorization does not match; expected %s, but got %s", expected, keyAuth)) "keyAuthorization does not match; expected %s, but got %s", expected, keyAuth))
} }
@ -107,7 +108,11 @@ func http01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWeb
func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, vo *ValidateChallengeOptions) error { func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebKey, vo *ValidateChallengeOptions) error {
config := &tls.Config{ config := &tls.Config{
NextProtos: []string{"acme-tls/1"}, NextProtos: []string{"acme-tls/1"},
// https://tools.ietf.org/html/rfc8737#section-4
// ACME servers that implement "acme-tls/1" MUST only negotiate TLS 1.2
// [RFC5246] or higher when connecting to clients for validation.
MinVersion: tls.VersionTLS12,
ServerName: ch.Value, ServerName: ch.Value,
InsecureSkipVerify: true, // we expect a self-signed challenge certificate InsecureSkipVerify: true, // we expect a self-signed challenge certificate
} }
@ -116,7 +121,7 @@ func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSON
conn, err := vo.TLSDial("tcp", hostPort, config) conn, err := vo.TLSDial("tcp", hostPort, config)
if err != nil { if err != nil {
return storeError(ctx, ch, db, WrapError(ErrorConnectionType, err, return storeError(ctx, db, ch, false, WrapError(ErrorConnectionType, err,
"error doing TLS dial for %s", hostPort)) "error doing TLS dial for %s", hostPort))
} }
defer conn.Close() defer conn.Close()
@ -125,19 +130,19 @@ func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSON
certs := cs.PeerCertificates certs := cs.PeerCertificates
if len(certs) == 0 { if len(certs) == 0 {
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"%s challenge for %s resulted in no certificates", ch.Type, ch.Value)) "%s challenge for %s resulted in no certificates", ch.Type, ch.Value))
} }
if !cs.NegotiatedProtocolIsMutual || cs.NegotiatedProtocol != "acme-tls/1" { if !cs.NegotiatedProtocolIsMutual || cs.NegotiatedProtocol != "acme-tls/1" {
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"cannot negotiate ALPN acme-tls/1 protocol for tls-alpn-01 challenge")) "cannot negotiate ALPN acme-tls/1 protocol for tls-alpn-01 challenge"))
} }
leafCert := certs[0] leafCert := certs[0]
if len(leafCert.DNSNames) != 1 || !strings.EqualFold(leafCert.DNSNames[0], ch.Value) { if len(leafCert.DNSNames) != 1 || !strings.EqualFold(leafCert.DNSNames[0], ch.Value) {
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"incorrect certificate for tls-alpn-01 challenge: leaf certificate must contain a single DNS name, %v", ch.Value)) "incorrect certificate for tls-alpn-01 challenge: leaf certificate must contain a single DNS name, %v", ch.Value))
} }
@ -154,7 +159,7 @@ func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSON
for _, ext := range leafCert.Extensions { for _, ext := range leafCert.Extensions {
if idPeAcmeIdentifier.Equal(ext.Id) { if idPeAcmeIdentifier.Equal(ext.Id) {
if !ext.Critical { if !ext.Critical {
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"incorrect certificate for tls-alpn-01 challenge: acmeValidationV1 extension not critical")) "incorrect certificate for tls-alpn-01 challenge: acmeValidationV1 extension not critical"))
} }
@ -162,12 +167,12 @@ func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSON
rest, err := asn1.Unmarshal(ext.Value, &extValue) rest, err := asn1.Unmarshal(ext.Value, &extValue)
if err != nil || len(rest) > 0 || len(hashedKeyAuth) != len(extValue) { if err != nil || len(rest) > 0 || len(hashedKeyAuth) != len(extValue) {
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"incorrect certificate for tls-alpn-01 challenge: malformed acmeValidationV1 extension value")) "incorrect certificate for tls-alpn-01 challenge: malformed acmeValidationV1 extension value"))
} }
if subtle.ConstantTimeCompare(hashedKeyAuth[:], extValue) != 1 { if subtle.ConstantTimeCompare(hashedKeyAuth[:], extValue) != 1 {
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"incorrect certificate for tls-alpn-01 challenge: "+ "incorrect certificate for tls-alpn-01 challenge: "+
"expected acmeValidationV1 extension value %s for this challenge but got %s", "expected acmeValidationV1 extension value %s for this challenge but got %s",
hex.EncodeToString(hashedKeyAuth[:]), hex.EncodeToString(extValue))) hex.EncodeToString(hashedKeyAuth[:]), hex.EncodeToString(extValue)))
@ -189,11 +194,11 @@ func tlsalpn01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSON
} }
if foundIDPeAcmeIdentifierV1Obsolete { if foundIDPeAcmeIdentifierV1Obsolete {
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"incorrect certificate for tls-alpn-01 challenge: obsolete id-pe-acmeIdentifier in acmeValidationV1 extension")) "incorrect certificate for tls-alpn-01 challenge: obsolete id-pe-acmeIdentifier in acmeValidationV1 extension"))
} }
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, true, NewError(ErrorRejectedIdentifierType,
"incorrect certificate for tls-alpn-01 challenge: missing acmeValidationV1 extension")) "incorrect certificate for tls-alpn-01 challenge: missing acmeValidationV1 extension"))
} }
@ -206,7 +211,7 @@ func dns01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebK
txtRecords, err := vo.LookupTxt("_acme-challenge." + domain) txtRecords, err := vo.LookupTxt("_acme-challenge." + domain)
if err != nil { if err != nil {
return storeError(ctx, ch, db, WrapError(ErrorDNSType, err, return storeError(ctx, db, ch, false, WrapError(ErrorDNSType, err,
"error looking up TXT records for domain %s", domain)) "error looking up TXT records for domain %s", domain))
} }
@ -224,7 +229,7 @@ func dns01Validate(ctx context.Context, ch *Challenge, db DB, jwk *jose.JSONWebK
} }
} }
if !found { if !found {
return storeError(ctx, ch, db, NewError(ErrorRejectedIdentifierType, return storeError(ctx, db, ch, false, NewError(ErrorRejectedIdentifierType,
"keyAuthorization does not match; expected %s, but got %s", expectedKeyAuth, txtRecords)) "keyAuthorization does not match; expected %s, but got %s", expectedKeyAuth, txtRecords))
} }
@ -251,8 +256,11 @@ func KeyAuthorization(token string, jwk *jose.JSONWebKey) (string, error) {
} }
// storeError the given error to an ACME error and saves using the DB interface. // storeError the given error to an ACME error and saves using the DB interface.
func storeError(ctx context.Context, ch *Challenge, db DB, err *Error) error { func storeError(ctx context.Context, db DB, ch *Challenge, markInvalid bool, err *Error) error {
ch.Error = err ch.Error = err
if markInvalid {
ch.Status = StatusInvalid
}
if err := db.UpdateChallenge(ctx, ch); err != nil { if err := db.UpdateChallenge(ctx, ch); err != nil {
return WrapErrorISE(err, "failure saving error to acme challenge") return WrapErrorISE(err, "failure saving error to acme challenge")
} }

View file

@ -31,17 +31,19 @@ import (
func Test_storeError(t *testing.T) { func Test_storeError(t *testing.T) {
type test struct { type test struct {
ch *Challenge ch *Challenge
db DB db DB
err *Error markInvalid bool
err *Error
} }
err := NewError(ErrorMalformedType, "foo") err := NewError(ErrorMalformedType, "foo")
tests := map[string]func(t *testing.T) test{ tests := map[string]func(t *testing.T) test{
"fail/db.UpdateChallenge-error": func(t *testing.T) test { "fail/db.UpdateChallenge-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusValid,
} }
return test{ return test{
ch: ch, ch: ch,
@ -50,6 +52,7 @@ func Test_storeError(t *testing.T) {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusValid)
assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error())
assert.Equals(t, updch.Error.Type, err.Type) assert.Equals(t, updch.Error.Type, err.Type)
@ -64,9 +67,10 @@ func Test_storeError(t *testing.T) {
}, },
"fail/db.UpdateChallenge-acme-error": func(t *testing.T) test { "fail/db.UpdateChallenge-acme-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusValid,
} }
return test{ return test{
ch: ch, ch: ch,
@ -75,6 +79,7 @@ func Test_storeError(t *testing.T) {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusValid)
assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error())
assert.Equals(t, updch.Error.Type, err.Type) assert.Equals(t, updch.Error.Type, err.Type)
@ -89,9 +94,10 @@ func Test_storeError(t *testing.T) {
}, },
"ok": func(t *testing.T) test { "ok": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusValid,
} }
return test{ return test{
ch: ch, ch: ch,
@ -100,6 +106,7 @@ func Test_storeError(t *testing.T) {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusValid)
assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error())
assert.Equals(t, updch.Error.Type, err.Type) assert.Equals(t, updch.Error.Type, err.Type)
@ -111,11 +118,38 @@ func Test_storeError(t *testing.T) {
}, },
} }
}, },
"ok/mark-invalid": func(t *testing.T) test {
ch := &Challenge{
ID: "chID",
Token: "token",
Value: "zap.internal",
Status: StatusValid,
}
return test{
ch: ch,
db: &MockDB{
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusInvalid)
assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error())
assert.Equals(t, updch.Error.Type, err.Type)
assert.Equals(t, updch.Error.Detail, err.Detail)
assert.Equals(t, updch.Error.Status, err.Status)
assert.Equals(t, updch.Error.Detail, err.Detail)
return nil
},
},
markInvalid: true,
}
},
} }
for name, run := range tests { for name, run := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
tc := run(t) tc := run(t)
if err := storeError(context.Background(), tc.ch, tc.db, err); err != nil { if err := storeError(context.Background(), tc.db, tc.ch, tc.markInvalid, err); err != nil {
if assert.NotNil(t, tc.err) { if assert.NotNil(t, tc.err) {
switch k := err.(type) { switch k := err.(type) {
case *Error: case *Error:
@ -499,9 +533,10 @@ func TestHTTP01Validate(t *testing.T) {
tests := map[string]func(t *testing.T) test{ tests := map[string]func(t *testing.T) test{
"fail/http-get-error-store-error": func(t *testing.T) test { "fail/http-get-error-store-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
return test{ return test{
@ -515,6 +550,8 @@ func TestHTTP01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusPending)
err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s: force", ch.Token) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s: force", ch.Token)
assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error())
@ -530,9 +567,10 @@ func TestHTTP01Validate(t *testing.T) {
}, },
"ok/http-get-error": func(t *testing.T) test { "ok/http-get-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
return test{ return test{
@ -546,6 +584,8 @@ func TestHTTP01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusPending)
err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s: force", ch.Token) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s: force", ch.Token)
assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error())
@ -560,9 +600,10 @@ func TestHTTP01Validate(t *testing.T) {
}, },
"fail/http-get->=400-store-error": func(t *testing.T) test { "fail/http-get->=400-store-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
return test{ return test{
@ -571,6 +612,7 @@ func TestHTTP01Validate(t *testing.T) {
HTTPGet: func(url string) (*http.Response, error) { HTTPGet: func(url string) (*http.Response, error) {
return &http.Response{ return &http.Response{
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
Body: errReader(0),
}, nil }, nil
}, },
}, },
@ -578,6 +620,8 @@ func TestHTTP01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusPending)
err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s with status code 400", ch.Token) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s with status code 400", ch.Token)
assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error())
@ -593,9 +637,10 @@ func TestHTTP01Validate(t *testing.T) {
}, },
"ok/http-get->=400": func(t *testing.T) test { "ok/http-get->=400": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
return test{ return test{
@ -604,6 +649,7 @@ func TestHTTP01Validate(t *testing.T) {
HTTPGet: func(url string) (*http.Response, error) { HTTPGet: func(url string) (*http.Response, error) {
return &http.Response{ return &http.Response{
StatusCode: http.StatusBadRequest, StatusCode: http.StatusBadRequest,
Body: errReader(0),
}, nil }, nil
}, },
}, },
@ -611,6 +657,8 @@ func TestHTTP01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusPending)
err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s with status code 400", ch.Token) err := NewError(ErrorConnectionType, "error doing http GET for url http://zap.internal/.well-known/acme-challenge/%s with status code 400", ch.Token)
assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error()) assert.HasPrefix(t, updch.Error.Err.Error(), err.Err.Error())
@ -625,9 +673,10 @@ func TestHTTP01Validate(t *testing.T) {
}, },
"fail/read-body": func(t *testing.T) test { "fail/read-body": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
return test{ return test{
@ -644,9 +693,10 @@ func TestHTTP01Validate(t *testing.T) {
}, },
"fail/key-auth-gen-error": func(t *testing.T) test { "fail/key-auth-gen-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -667,9 +717,10 @@ func TestHTTP01Validate(t *testing.T) {
}, },
"ok/key-auth-mismatch": func(t *testing.T) test { "ok/key-auth-mismatch": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -692,6 +743,7 @@ func TestHTTP01Validate(t *testing.T) {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusInvalid)
err := NewError(ErrorRejectedIdentifierType, err := NewError(ErrorRejectedIdentifierType,
"keyAuthorization does not match; expected %s, but got foo", expKeyAuth) "keyAuthorization does not match; expected %s, but got foo", expKeyAuth)
@ -707,9 +759,10 @@ func TestHTTP01Validate(t *testing.T) {
}, },
"fail/key-auth-mismatch-store-error": func(t *testing.T) test { "fail/key-auth-mismatch-store-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -732,6 +785,7 @@ func TestHTTP01Validate(t *testing.T) {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusInvalid)
err := NewError(ErrorRejectedIdentifierType, err := NewError(ErrorRejectedIdentifierType,
"keyAuthorization does not match; expected %s, but got foo", expKeyAuth) "keyAuthorization does not match; expected %s, but got foo", expKeyAuth)
@ -748,9 +802,10 @@ func TestHTTP01Validate(t *testing.T) {
}, },
"fail/update-challenge-error": func(t *testing.T) test { "fail/update-challenge-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -789,9 +844,10 @@ func TestHTTP01Validate(t *testing.T) {
}, },
"ok": func(t *testing.T) test { "ok": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: "zap.internal", Value: "zap.internal",
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -864,9 +920,10 @@ func TestDNS01Validate(t *testing.T) {
tests := map[string]func(t *testing.T) test{ tests := map[string]func(t *testing.T) test{
"fail/lookupTXT-store-error": func(t *testing.T) test { "fail/lookupTXT-store-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: fulldomain, Value: fulldomain,
Status: StatusPending,
} }
return test{ return test{
@ -880,6 +937,8 @@ func TestDNS01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusPending)
err := NewError(ErrorDNSType, "error looking up TXT records for domain %s: force", domain) err := NewError(ErrorDNSType, "error looking up TXT records for domain %s: force", domain)
@ -896,9 +955,10 @@ func TestDNS01Validate(t *testing.T) {
}, },
"ok/lookupTXT-error": func(t *testing.T) test { "ok/lookupTXT-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: fulldomain, Value: fulldomain,
Status: StatusPending,
} }
return test{ return test{
@ -912,6 +972,8 @@ func TestDNS01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusPending)
err := NewError(ErrorDNSType, "error looking up TXT records for domain %s: force", domain) err := NewError(ErrorDNSType, "error looking up TXT records for domain %s: force", domain)
@ -927,9 +989,10 @@ func TestDNS01Validate(t *testing.T) {
}, },
"fail/key-auth-gen-error": func(t *testing.T) test { "fail/key-auth-gen-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: fulldomain, Value: fulldomain,
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -949,9 +1012,10 @@ func TestDNS01Validate(t *testing.T) {
}, },
"fail/key-auth-mismatch-store-error": func(t *testing.T) test { "fail/key-auth-mismatch-store-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: fulldomain, Value: fulldomain,
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -971,6 +1035,8 @@ func TestDNS01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusPending)
err := NewError(ErrorRejectedIdentifierType, "keyAuthorization does not match; expected %s, but got %s", expKeyAuth, []string{"foo", "bar"}) err := NewError(ErrorRejectedIdentifierType, "keyAuthorization does not match; expected %s, but got %s", expKeyAuth, []string{"foo", "bar"})
@ -988,9 +1054,10 @@ func TestDNS01Validate(t *testing.T) {
}, },
"ok/key-auth-mismatch-store-error": func(t *testing.T) test { "ok/key-auth-mismatch-store-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: fulldomain, Value: fulldomain,
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -1010,6 +1077,8 @@ func TestDNS01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusPending)
err := NewError(ErrorRejectedIdentifierType, "keyAuthorization does not match; expected %s, but got %s", expKeyAuth, []string{"foo", "bar"}) err := NewError(ErrorRejectedIdentifierType, "keyAuthorization does not match; expected %s, but got %s", expKeyAuth, []string{"foo", "bar"})
@ -1026,9 +1095,10 @@ func TestDNS01Validate(t *testing.T) {
}, },
"fail/update-challenge-error": func(t *testing.T) test { "fail/update-challenge-error": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: fulldomain, Value: fulldomain,
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -1051,6 +1121,7 @@ func TestDNS01Validate(t *testing.T) {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusValid)
assert.Equals(t, updch.Status, StatusValid) assert.Equals(t, updch.Status, StatusValid)
assert.Equals(t, updch.Error, nil) assert.Equals(t, updch.Error, nil)
@ -1069,9 +1140,10 @@ func TestDNS01Validate(t *testing.T) {
}, },
"ok": func(t *testing.T) test { "ok": func(t *testing.T) test {
ch := &Challenge{ ch := &Challenge{
ID: "chID", ID: "chID",
Token: "token", Token: "token",
Value: fulldomain, Value: fulldomain,
Status: StatusPending,
} }
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0) jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
@ -1094,6 +1166,7 @@ func TestDNS01Validate(t *testing.T) {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Status, StatusValid)
assert.Equals(t, updch.Status, StatusValid) assert.Equals(t, updch.Status, StatusValid)
assert.Equals(t, updch.Error, nil) assert.Equals(t, updch.Error, nil)
@ -1349,7 +1422,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1379,7 +1452,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1415,7 +1488,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1452,7 +1525,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1496,7 +1569,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1539,7 +1612,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1583,7 +1656,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1626,7 +1699,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1692,7 +1765,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1731,7 +1804,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1775,7 +1848,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1818,7 +1891,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1858,7 +1931,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1897,7 +1970,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1942,7 +2015,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -1988,7 +2061,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -2034,7 +2107,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -2078,7 +2151,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusInvalid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
@ -2123,7 +2196,7 @@ func TestTLSALPN01Validate(t *testing.T) {
MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error { MockUpdateChallenge: func(ctx context.Context, updch *Challenge) error {
assert.Equals(t, updch.ID, ch.ID) assert.Equals(t, updch.ID, ch.ID)
assert.Equals(t, updch.Token, ch.Token) assert.Equals(t, updch.Token, ch.Token)
assert.Equals(t, updch.Status, ch.Status) assert.Equals(t, updch.Status, StatusValid)
assert.Equals(t, updch.Type, ch.Type) assert.Equals(t, updch.Type, ch.Type)
assert.Equals(t, updch.Value, ch.Value) assert.Equals(t, updch.Value, ch.Value)
assert.Equals(t, updch.Error, nil) assert.Equals(t, updch.Error, nil)

View file

@ -19,7 +19,7 @@ type Clock struct{}
// Now returns the UTC time rounded to seconds. // Now returns the UTC time rounded to seconds.
func (c *Clock) Now() time.Time { func (c *Clock) Now() time.Time {
return time.Now().UTC().Round(time.Second) return time.Now().UTC().Truncate(time.Second)
} }
var clock Clock var clock Clock

View file

@ -24,10 +24,10 @@ type Order struct {
AccountID string `json:"-"` AccountID string `json:"-"`
ProvisionerID string `json:"-"` ProvisionerID string `json:"-"`
Status Status `json:"status"` Status Status `json:"status"`
ExpiresAt time.Time `json:"expires,omitempty"` ExpiresAt time.Time `json:"expires"`
Identifiers []Identifier `json:"identifiers"` Identifiers []Identifier `json:"identifiers"`
NotBefore time.Time `json:"notBefore,omitempty"` NotBefore time.Time `json:"notBefore"`
NotAfter time.Time `json:"notAfter,omitempty"` NotAfter time.Time `json:"notAfter"`
Error *Error `json:"error,omitempty"` Error *Error `json:"error,omitempty"`
AuthorizationIDs []string `json:"-"` AuthorizationIDs []string `json:"-"`
AuthorizationURLs []string `json:"authorizations"` AuthorizationURLs []string `json:"authorizations"`