forked from TrueCloudLab/certificates
gethttp01 validate unit tests working
This commit is contained in:
parent
7f9ffbd514
commit
3612a0b990
7 changed files with 1487 additions and 900 deletions
File diff suppressed because it is too large
Load diff
|
@ -14,16 +14,16 @@ var defaultExpiryDuration = time.Hour * 24
|
||||||
|
|
||||||
// dbAuthz is the base authz type that others build from.
|
// dbAuthz is the base authz type that others build from.
|
||||||
type dbAuthz struct {
|
type dbAuthz struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
AccountID string `json:"accountID"`
|
AccountID string `json:"accountID"`
|
||||||
Identifier acme.Identifier `json:"identifier"`
|
Identifier acme.Identifier `json:"identifier"`
|
||||||
Status acme.Status `json:"status"`
|
Status acme.Status `json:"status"`
|
||||||
ExpiresAt time.Time `json:"expiresAt"`
|
ExpiresAt time.Time `json:"expiresAt"`
|
||||||
Challenges []string `json:"challenges"`
|
ChallengeIDs []string `json:"challengeIDs"`
|
||||||
Wildcard bool `json:"wildcard"`
|
Wildcard bool `json:"wildcard"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
Error *acme.Error `json:"error"`
|
Error *acme.Error `json:"error"`
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ba *dbAuthz) clone() *dbAuthz {
|
func (ba *dbAuthz) clone() *dbAuthz {
|
||||||
|
@ -55,8 +55,8 @@ func (db *DB) GetAuthorization(ctx context.Context, id string) (*acme.Authorizat
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var chs = make([]*acme.Challenge, len(dbaz.Challenges))
|
var chs = make([]*acme.Challenge, len(dbaz.ChallengeIDs))
|
||||||
for i, chID := range dbaz.Challenges {
|
for i, chID := range dbaz.ChallengeIDs {
|
||||||
chs[i], err = db.GetChallenge(ctx, chID, id)
|
chs[i], err = db.GetChallenge(ctx, chID, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -91,15 +91,15 @@ func (db *DB) CreateAuthorization(ctx context.Context, az *acme.Authorization) e
|
||||||
|
|
||||||
now := clock.Now()
|
now := clock.Now()
|
||||||
dbaz := &dbAuthz{
|
dbaz := &dbAuthz{
|
||||||
ID: az.ID,
|
ID: az.ID,
|
||||||
AccountID: az.AccountID,
|
AccountID: az.AccountID,
|
||||||
Status: az.Status,
|
Status: az.Status,
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
ExpiresAt: az.ExpiresAt,
|
ExpiresAt: az.ExpiresAt,
|
||||||
Identifier: az.Identifier,
|
Identifier: az.Identifier,
|
||||||
Challenges: chIDs,
|
ChallengeIDs: chIDs,
|
||||||
Token: az.Token,
|
Token: az.Token,
|
||||||
Wildcard: az.Wildcard,
|
Wildcard: az.Wildcard,
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.save(ctx, az.ID, dbaz, nil, "authz", authzTable)
|
return db.save(ctx, az.ID, dbaz, nil, "authz", authzTable)
|
||||||
|
|
|
@ -71,13 +71,13 @@ func TestDB_getDBAuthz(t *testing.T) {
|
||||||
Type: "dns",
|
Type: "dns",
|
||||||
Value: "test.ca.smallstep.com",
|
Value: "test.ca.smallstep.com",
|
||||||
},
|
},
|
||||||
Status: acme.StatusPending,
|
Status: acme.StatusPending,
|
||||||
Token: "token",
|
Token: "token",
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
ExpiresAt: now.Add(5 * time.Minute),
|
ExpiresAt: now.Add(5 * time.Minute),
|
||||||
Error: acme.NewErrorISE("force"),
|
Error: acme.NewErrorISE("force"),
|
||||||
Challenges: []string{"foo", "bar"},
|
ChallengeIDs: []string{"foo", "bar"},
|
||||||
Wildcard: true,
|
Wildcard: true,
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(dbaz)
|
b, err := json.Marshal(dbaz)
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
@ -174,13 +174,13 @@ func TestDB_GetAuthorization(t *testing.T) {
|
||||||
Type: "dns",
|
Type: "dns",
|
||||||
Value: "test.ca.smallstep.com",
|
Value: "test.ca.smallstep.com",
|
||||||
},
|
},
|
||||||
Status: acme.StatusPending,
|
Status: acme.StatusPending,
|
||||||
Token: "token",
|
Token: "token",
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
ExpiresAt: now.Add(5 * time.Minute),
|
ExpiresAt: now.Add(5 * time.Minute),
|
||||||
Error: acme.NewErrorISE("force"),
|
Error: acme.NewErrorISE("force"),
|
||||||
Challenges: []string{"foo", "bar"},
|
ChallengeIDs: []string{"foo", "bar"},
|
||||||
Wildcard: true,
|
Wildcard: true,
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(dbaz)
|
b, err := json.Marshal(dbaz)
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
@ -212,13 +212,13 @@ func TestDB_GetAuthorization(t *testing.T) {
|
||||||
Type: "dns",
|
Type: "dns",
|
||||||
Value: "test.ca.smallstep.com",
|
Value: "test.ca.smallstep.com",
|
||||||
},
|
},
|
||||||
Status: acme.StatusPending,
|
Status: acme.StatusPending,
|
||||||
Token: "token",
|
Token: "token",
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
ExpiresAt: now.Add(5 * time.Minute),
|
ExpiresAt: now.Add(5 * time.Minute),
|
||||||
Error: acme.NewErrorISE("force"),
|
Error: acme.NewErrorISE("force"),
|
||||||
Challenges: []string{"foo", "bar"},
|
ChallengeIDs: []string{"foo", "bar"},
|
||||||
Wildcard: true,
|
Wildcard: true,
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(dbaz)
|
b, err := json.Marshal(dbaz)
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
@ -250,13 +250,13 @@ func TestDB_GetAuthorization(t *testing.T) {
|
||||||
Type: "dns",
|
Type: "dns",
|
||||||
Value: "test.ca.smallstep.com",
|
Value: "test.ca.smallstep.com",
|
||||||
},
|
},
|
||||||
Status: acme.StatusPending,
|
Status: acme.StatusPending,
|
||||||
Token: "token",
|
Token: "token",
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
ExpiresAt: now.Add(5 * time.Minute),
|
ExpiresAt: now.Add(5 * time.Minute),
|
||||||
Error: acme.NewErrorISE("force"),
|
Error: acme.NewErrorISE("force"),
|
||||||
Challenges: []string{"foo", "bar"},
|
ChallengeIDs: []string{"foo", "bar"},
|
||||||
Wildcard: true,
|
Wildcard: true,
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(dbaz)
|
b, err := json.Marshal(dbaz)
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
@ -374,7 +374,7 @@ func TestDB_CreateAuthorization(t *testing.T) {
|
||||||
})
|
})
|
||||||
assert.Equals(t, dbaz.Status, az.Status)
|
assert.Equals(t, dbaz.Status, az.Status)
|
||||||
assert.Equals(t, dbaz.Token, az.Token)
|
assert.Equals(t, dbaz.Token, az.Token)
|
||||||
assert.Equals(t, dbaz.Challenges, []string{"foo", "bar"})
|
assert.Equals(t, dbaz.ChallengeIDs, []string{"foo", "bar"})
|
||||||
assert.Equals(t, dbaz.Wildcard, az.Wildcard)
|
assert.Equals(t, dbaz.Wildcard, az.Wildcard)
|
||||||
assert.Equals(t, dbaz.ExpiresAt, az.ExpiresAt)
|
assert.Equals(t, dbaz.ExpiresAt, az.ExpiresAt)
|
||||||
assert.Nil(t, dbaz.Error)
|
assert.Nil(t, dbaz.Error)
|
||||||
|
@ -428,7 +428,7 @@ func TestDB_CreateAuthorization(t *testing.T) {
|
||||||
})
|
})
|
||||||
assert.Equals(t, dbaz.Status, az.Status)
|
assert.Equals(t, dbaz.Status, az.Status)
|
||||||
assert.Equals(t, dbaz.Token, az.Token)
|
assert.Equals(t, dbaz.Token, az.Token)
|
||||||
assert.Equals(t, dbaz.Challenges, []string{"foo", "bar"})
|
assert.Equals(t, dbaz.ChallengeIDs, []string{"foo", "bar"})
|
||||||
assert.Equals(t, dbaz.Wildcard, az.Wildcard)
|
assert.Equals(t, dbaz.Wildcard, az.Wildcard)
|
||||||
assert.Equals(t, dbaz.ExpiresAt, az.ExpiresAt)
|
assert.Equals(t, dbaz.ExpiresAt, az.ExpiresAt)
|
||||||
assert.Nil(t, dbaz.Error)
|
assert.Nil(t, dbaz.Error)
|
||||||
|
@ -469,12 +469,12 @@ func TestDB_UpdateAuthorization(t *testing.T) {
|
||||||
Type: "dns",
|
Type: "dns",
|
||||||
Value: "test.ca.smallstep.com",
|
Value: "test.ca.smallstep.com",
|
||||||
},
|
},
|
||||||
Status: acme.StatusPending,
|
Status: acme.StatusPending,
|
||||||
Token: "token",
|
Token: "token",
|
||||||
CreatedAt: now,
|
CreatedAt: now,
|
||||||
ExpiresAt: now.Add(5 * time.Minute),
|
ExpiresAt: now.Add(5 * time.Minute),
|
||||||
Challenges: []string{"foo", "bar"},
|
ChallengeIDs: []string{"foo", "bar"},
|
||||||
Wildcard: true,
|
Wildcard: true,
|
||||||
}
|
}
|
||||||
b, err := json.Marshal(dbaz)
|
b, err := json.Marshal(dbaz)
|
||||||
assert.FatalError(t, err)
|
assert.FatalError(t, err)
|
||||||
|
@ -530,7 +530,7 @@ func TestDB_UpdateAuthorization(t *testing.T) {
|
||||||
assert.Equals(t, dbNew.Identifier, dbaz.Identifier)
|
assert.Equals(t, dbNew.Identifier, dbaz.Identifier)
|
||||||
assert.Equals(t, dbNew.Status, acme.StatusValid)
|
assert.Equals(t, dbNew.Status, acme.StatusValid)
|
||||||
assert.Equals(t, dbNew.Token, dbaz.Token)
|
assert.Equals(t, dbNew.Token, dbaz.Token)
|
||||||
assert.Equals(t, dbNew.Challenges, dbaz.Challenges)
|
assert.Equals(t, dbNew.ChallengeIDs, dbaz.ChallengeIDs)
|
||||||
assert.Equals(t, dbNew.Wildcard, dbaz.Wildcard)
|
assert.Equals(t, dbNew.Wildcard, dbaz.Wildcard)
|
||||||
assert.Equals(t, dbNew.CreatedAt, dbaz.CreatedAt)
|
assert.Equals(t, dbNew.CreatedAt, dbaz.CreatedAt)
|
||||||
assert.Equals(t, dbNew.ExpiresAt, dbaz.ExpiresAt)
|
assert.Equals(t, dbNew.ExpiresAt, dbaz.ExpiresAt)
|
||||||
|
@ -580,7 +580,7 @@ func TestDB_UpdateAuthorization(t *testing.T) {
|
||||||
assert.Equals(t, dbNew.Identifier, dbaz.Identifier)
|
assert.Equals(t, dbNew.Identifier, dbaz.Identifier)
|
||||||
assert.Equals(t, dbNew.Status, acme.StatusValid)
|
assert.Equals(t, dbNew.Status, acme.StatusValid)
|
||||||
assert.Equals(t, dbNew.Token, dbaz.Token)
|
assert.Equals(t, dbNew.Token, dbaz.Token)
|
||||||
assert.Equals(t, dbNew.Challenges, dbaz.Challenges)
|
assert.Equals(t, dbNew.ChallengeIDs, dbaz.ChallengeIDs)
|
||||||
assert.Equals(t, dbNew.Wildcard, dbaz.Wildcard)
|
assert.Equals(t, dbNew.Wildcard, dbaz.Wildcard)
|
||||||
assert.Equals(t, dbNew.CreatedAt, dbaz.CreatedAt)
|
assert.Equals(t, dbNew.CreatedAt, dbaz.CreatedAt)
|
||||||
assert.Equals(t, dbNew.ExpiresAt, dbaz.ExpiresAt)
|
assert.Equals(t, dbNew.ExpiresAt, dbaz.ExpiresAt)
|
||||||
|
|
|
@ -42,9 +42,17 @@ func New(db nosqlDB.DB) (*DB, error) {
|
||||||
// save writes the new data to the database, overwriting the old data if it
|
// save writes the new data to the database, overwriting the old data if it
|
||||||
// existed.
|
// existed.
|
||||||
func (db *DB) save(ctx context.Context, id string, nu interface{}, old interface{}, typ string, table []byte) error {
|
func (db *DB) save(ctx context.Context, id string, nu interface{}, old interface{}, typ string, table []byte) error {
|
||||||
newB, err := json.Marshal(nu)
|
var (
|
||||||
if err != nil {
|
err error
|
||||||
return errors.Wrapf(err, "error marshaling acme type: %s, value: %v", typ, nu)
|
newB []byte
|
||||||
|
)
|
||||||
|
if nu == nil {
|
||||||
|
newB = nil
|
||||||
|
} else {
|
||||||
|
newB, err = json.Marshal(nu)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error marshaling acme type: %s, value: %v", typ, nu)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
var oldB []byte
|
var oldB []byte
|
||||||
if old == nil {
|
if old == nil {
|
||||||
|
|
|
@ -110,6 +110,19 @@ func TestDB_save(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
"ok/nils": test{
|
||||||
|
nu: nil,
|
||||||
|
old: nil,
|
||||||
|
db: &db.MockNoSQLDB{
|
||||||
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
||||||
|
assert.Equals(t, bucket, challengeTable)
|
||||||
|
assert.Equals(t, string(key), "id")
|
||||||
|
assert.Equals(t, old, nil)
|
||||||
|
assert.Equals(t, nu, nil)
|
||||||
|
return nu, true, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
|
|
|
@ -127,15 +127,17 @@ func (db *DB) updateAddOrderIDs(ctx context.Context, accID string, addOids ...st
|
||||||
defer ordersByAccountMux.Unlock()
|
defer ordersByAccountMux.Unlock()
|
||||||
|
|
||||||
b, err := db.db.Get(ordersByAccountIDTable, []byte(accID))
|
b, err := db.db.Get(ordersByAccountIDTable, []byte(accID))
|
||||||
|
var (
|
||||||
|
oldOids []string
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if nosql.IsErrNotFound(err) {
|
if !nosql.IsErrNotFound(err) {
|
||||||
return []string{}, nil
|
return nil, errors.Wrapf(err, "error loading orderIDs for account %s", accID)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err := json.Unmarshal(b, &oldOids); err != nil {
|
||||||
|
return nil, errors.Wrapf(err, "error unmarshaling orderIDs for account %s", accID)
|
||||||
}
|
}
|
||||||
return nil, errors.Wrapf(err, "error loading orderIDs for account %s", accID)
|
|
||||||
}
|
|
||||||
var oids []string
|
|
||||||
if err := json.Unmarshal(b, &oids); err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "error unmarshaling orderIDs for account %s", accID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove any order that is not in PENDING state and update the stored list
|
// Remove any order that is not in PENDING state and update the stored list
|
||||||
|
@ -145,7 +147,7 @@ func (db *DB) updateAddOrderIDs(ctx context.Context, accID string, addOids ...st
|
||||||
// The server SHOULD include pending orders and SHOULD NOT include orders
|
// The server SHOULD include pending orders and SHOULD NOT include orders
|
||||||
// that are invalid in the array of URLs.
|
// that are invalid in the array of URLs.
|
||||||
pendOids := []string{}
|
pendOids := []string{}
|
||||||
for _, oid := range oids {
|
for _, oid := range oldOids {
|
||||||
o, err := db.GetOrder(ctx, oid)
|
o, err := db.GetOrder(ctx, oid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, acme.WrapErrorISE(err, "error loading order %s for account %s", oid, accID)
|
return nil, acme.WrapErrorISE(err, "error loading order %s for account %s", oid, accID)
|
||||||
|
@ -158,15 +160,27 @@ func (db *DB) updateAddOrderIDs(ctx context.Context, accID string, addOids ...st
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pendOids = append(pendOids, addOids...)
|
pendOids = append(pendOids, addOids...)
|
||||||
if len(oids) == 0 {
|
var (
|
||||||
oids = nil
|
_old interface{} = oldOids
|
||||||
|
_new interface{} = pendOids
|
||||||
|
)
|
||||||
|
switch {
|
||||||
|
case len(oldOids) == 0 && len(pendOids) == 0:
|
||||||
|
// If list has not changed from empty, then no need to write the DB.
|
||||||
|
return []string{}, nil
|
||||||
|
case len(oldOids) == 0:
|
||||||
|
_old = nil
|
||||||
|
case len(pendOids) == 0:
|
||||||
|
_new = nil
|
||||||
}
|
}
|
||||||
if err = db.save(ctx, accID, pendOids, oids, "orderIDsByAccountID", ordersByAccountIDTable); err != nil {
|
if err = db.save(ctx, accID, _new, _old, "orderIDsByAccountID", ordersByAccountIDTable); err != nil {
|
||||||
// Delete all orders that may have been previously stored if orderIDsByAccountID update fails.
|
// Delete all orders that may have been previously stored if orderIDsByAccountID update fails.
|
||||||
for _, oid := range addOids {
|
for _, oid := range addOids {
|
||||||
|
// Ignore error from delete -- we tried our best.
|
||||||
|
// TODO when we have logging w/ request ID tracking, logging this error.
|
||||||
db.db.Del(orderTable, []byte(oid))
|
db.db.Del(orderTable, []byte(oid))
|
||||||
}
|
}
|
||||||
return nil, errors.Wrap(err, "error saving OrderIDsByAccountID index")
|
return nil, errors.Wrapf(err, "error saving orderIDs index for account %s", accID)
|
||||||
}
|
}
|
||||||
return pendOids, nil
|
return pendOids, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package nosql
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -511,27 +512,39 @@ func TestDB_CreateOrder(t *testing.T) {
|
||||||
return nil, nosqldb.ErrNotFound
|
return nil, nosqldb.ErrNotFound
|
||||||
},
|
},
|
||||||
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
||||||
*idptr = string(key)
|
switch string(bucket) {
|
||||||
assert.Equals(t, string(bucket), string(orderTable))
|
case string(ordersByAccountIDTable):
|
||||||
assert.Equals(t, string(key), o.ID)
|
b, err := json.Marshal([]string{o.ID})
|
||||||
assert.Equals(t, old, nil)
|
assert.FatalError(t, err)
|
||||||
|
assert.Equals(t, string(key), "accID")
|
||||||
|
assert.Equals(t, old, nil)
|
||||||
|
assert.Equals(t, nu, b)
|
||||||
|
return nu, true, nil
|
||||||
|
case string(orderTable):
|
||||||
|
*idptr = string(key)
|
||||||
|
assert.Equals(t, string(key), o.ID)
|
||||||
|
assert.Equals(t, old, nil)
|
||||||
|
|
||||||
dbo := new(dbOrder)
|
dbo := new(dbOrder)
|
||||||
assert.FatalError(t, json.Unmarshal(nu, dbo))
|
assert.FatalError(t, json.Unmarshal(nu, dbo))
|
||||||
assert.Equals(t, dbo.ID, o.ID)
|
assert.Equals(t, dbo.ID, o.ID)
|
||||||
assert.Equals(t, dbo.AccountID, o.AccountID)
|
assert.Equals(t, dbo.AccountID, o.AccountID)
|
||||||
assert.Equals(t, dbo.ProvisionerID, o.ProvisionerID)
|
assert.Equals(t, dbo.ProvisionerID, o.ProvisionerID)
|
||||||
assert.Equals(t, dbo.CertificateID, "")
|
assert.Equals(t, dbo.CertificateID, "")
|
||||||
assert.Equals(t, dbo.Status, o.Status)
|
assert.Equals(t, dbo.Status, o.Status)
|
||||||
assert.True(t, dbo.CreatedAt.Add(-time.Minute).Before(now))
|
assert.True(t, dbo.CreatedAt.Add(-time.Minute).Before(now))
|
||||||
assert.True(t, dbo.CreatedAt.Add(time.Minute).After(now))
|
assert.True(t, dbo.CreatedAt.Add(time.Minute).After(now))
|
||||||
assert.Equals(t, dbo.ExpiresAt, o.ExpiresAt)
|
assert.Equals(t, dbo.ExpiresAt, o.ExpiresAt)
|
||||||
assert.Equals(t, dbo.NotBefore, o.NotBefore)
|
assert.Equals(t, dbo.NotBefore, o.NotBefore)
|
||||||
assert.Equals(t, dbo.NotAfter, o.NotAfter)
|
assert.Equals(t, dbo.NotAfter, o.NotAfter)
|
||||||
assert.Equals(t, dbo.AuthorizationIDs, o.AuthorizationIDs)
|
assert.Equals(t, dbo.AuthorizationIDs, o.AuthorizationIDs)
|
||||||
assert.Equals(t, dbo.Identifiers, o.Identifiers)
|
assert.Equals(t, dbo.Identifiers, o.Identifiers)
|
||||||
assert.Equals(t, dbo.Error, nil)
|
assert.Equals(t, dbo.Error, nil)
|
||||||
return nu, true, nil
|
return nu, true, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket)))
|
||||||
|
return nil, false, errors.New("force")
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
o: o,
|
o: o,
|
||||||
|
@ -555,3 +568,434 @@ func TestDB_CreateOrder(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDB_updateAddOrderIDs(t *testing.T) {
|
||||||
|
accID := "accID"
|
||||||
|
type test struct {
|
||||||
|
db nosql.DB
|
||||||
|
err error
|
||||||
|
acmeErr *acme.Error
|
||||||
|
addOids []string
|
||||||
|
res []string
|
||||||
|
}
|
||||||
|
var tests = map[string]func(t *testing.T) test{
|
||||||
|
"fail/db.Get-error": func(t *testing.T) test {
|
||||||
|
return test{
|
||||||
|
db: &db.MockNoSQLDB{
|
||||||
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
||||||
|
assert.Equals(t, bucket, ordersByAccountIDTable)
|
||||||
|
assert.Equals(t, key, []byte(accID))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: errors.Errorf("error loading orderIDs for account %s", accID),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fail/unmarshal-error": func(t *testing.T) test {
|
||||||
|
return test{
|
||||||
|
db: &db.MockNoSQLDB{
|
||||||
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
||||||
|
assert.Equals(t, bucket, ordersByAccountIDTable)
|
||||||
|
assert.Equals(t, key, []byte(accID))
|
||||||
|
return []byte("foo"), nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
err: errors.Errorf("error unmarshaling orderIDs for account %s", accID),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fail/db.Get-order-error": func(t *testing.T) test {
|
||||||
|
return test{
|
||||||
|
db: &db.MockNoSQLDB{
|
||||||
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
||||||
|
switch string(bucket) {
|
||||||
|
case string(ordersByAccountIDTable):
|
||||||
|
assert.Equals(t, key, []byte(accID))
|
||||||
|
b, err := json.Marshal([]string{"foo", "bar"})
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
return b, nil
|
||||||
|
case string(orderTable):
|
||||||
|
assert.Equals(t, key, []byte("foo"))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
acmeErr: acme.NewErrorISE("error loading order foo for account accID: error loading order foo: force"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fail/update-order-status-error": func(t *testing.T) test {
|
||||||
|
expiry := clock.Now().Add(-5 * time.Minute)
|
||||||
|
ofoo := &dbOrder{
|
||||||
|
ID: "foo",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: expiry,
|
||||||
|
}
|
||||||
|
bfoo, err := json.Marshal(ofoo)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
return test{
|
||||||
|
db: &db.MockNoSQLDB{
|
||||||
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
||||||
|
switch string(bucket) {
|
||||||
|
case string(ordersByAccountIDTable):
|
||||||
|
assert.Equals(t, key, []byte(accID))
|
||||||
|
b, err := json.Marshal([]string{"foo", "bar"})
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
return b, nil
|
||||||
|
case string(orderTable):
|
||||||
|
assert.Equals(t, key, []byte("foo"))
|
||||||
|
return bfoo, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
||||||
|
assert.Equals(t, bucket, orderTable)
|
||||||
|
assert.Equals(t, key, []byte("foo"))
|
||||||
|
assert.Equals(t, old, bfoo)
|
||||||
|
|
||||||
|
newdbo := new(dbOrder)
|
||||||
|
assert.FatalError(t, json.Unmarshal(nu, newdbo))
|
||||||
|
assert.Equals(t, newdbo.ID, "foo")
|
||||||
|
assert.Equals(t, newdbo.Status, acme.StatusInvalid)
|
||||||
|
assert.Equals(t, newdbo.ExpiresAt, expiry)
|
||||||
|
assert.Equals(t, newdbo.Error.Error(), acme.NewError(acme.ErrorMalformedType, "order has expired").Error())
|
||||||
|
return nil, false, errors.New("force")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
acmeErr: acme.NewErrorISE("error updating order foo for account accID: error saving acme order: force"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"fail/db.save-order-error": func(t *testing.T) test {
|
||||||
|
addOids := []string{"foo", "bar"}
|
||||||
|
b, err := json.Marshal(addOids)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
delCount := 0
|
||||||
|
return test{
|
||||||
|
db: &db.MockNoSQLDB{
|
||||||
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
||||||
|
assert.Equals(t, bucket, ordersByAccountIDTable)
|
||||||
|
assert.Equals(t, key, []byte(accID))
|
||||||
|
return nil, nosqldb.ErrNotFound
|
||||||
|
},
|
||||||
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
||||||
|
assert.Equals(t, bucket, ordersByAccountIDTable)
|
||||||
|
assert.Equals(t, key, []byte(accID))
|
||||||
|
assert.Equals(t, old, nil)
|
||||||
|
assert.Equals(t, nu, b)
|
||||||
|
return nil, false, errors.New("force")
|
||||||
|
},
|
||||||
|
MDel: func(bucket, key []byte) error {
|
||||||
|
delCount++
|
||||||
|
switch delCount {
|
||||||
|
case 1:
|
||||||
|
assert.Equals(t, bucket, orderTable)
|
||||||
|
assert.Equals(t, key, []byte("foo"))
|
||||||
|
return nil
|
||||||
|
case 2:
|
||||||
|
assert.Equals(t, bucket, orderTable)
|
||||||
|
assert.Equals(t, key, []byte("bar"))
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.New("delete should only be called twice"))
|
||||||
|
return errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
addOids: addOids,
|
||||||
|
err: errors.Errorf("error saving orderIDs index for account %s", accID),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ok/all-old-not-pending": func(t *testing.T) test {
|
||||||
|
oldOids := []string{"foo", "bar"}
|
||||||
|
bOldOids, err := json.Marshal(oldOids)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
expiry := clock.Now().Add(-5 * time.Minute)
|
||||||
|
ofoo := &dbOrder{
|
||||||
|
ID: "foo",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: expiry,
|
||||||
|
}
|
||||||
|
bfoo, err := json.Marshal(ofoo)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
obar := &dbOrder{
|
||||||
|
ID: "bar",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: expiry,
|
||||||
|
}
|
||||||
|
bbar, err := json.Marshal(obar)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
return test{
|
||||||
|
db: &db.MockNoSQLDB{
|
||||||
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
||||||
|
switch string(bucket) {
|
||||||
|
case string(ordersByAccountIDTable):
|
||||||
|
return bOldOids, nil
|
||||||
|
case string(orderTable):
|
||||||
|
switch string(key) {
|
||||||
|
case "foo":
|
||||||
|
assert.Equals(t, key, []byte("foo"))
|
||||||
|
return bfoo, nil
|
||||||
|
case "bar":
|
||||||
|
assert.Equals(t, key, []byte("bar"))
|
||||||
|
return bbar, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected key %s", string(key)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
||||||
|
switch string(bucket) {
|
||||||
|
case string(orderTable):
|
||||||
|
return nil, true, nil
|
||||||
|
case string(ordersByAccountIDTable):
|
||||||
|
assert.Equals(t, key, []byte(accID))
|
||||||
|
assert.Equals(t, old, bOldOids)
|
||||||
|
assert.Equals(t, nu, nil)
|
||||||
|
return nil, true, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket)))
|
||||||
|
return nil, false, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
res: []string{},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ok/old-and-new": func(t *testing.T) test {
|
||||||
|
oldOids := []string{"foo", "bar"}
|
||||||
|
bOldOids, err := json.Marshal(oldOids)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
addOids := []string{"zap", "zar"}
|
||||||
|
bAddOids, err := json.Marshal(addOids)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
expiry := clock.Now().Add(-5 * time.Minute)
|
||||||
|
ofoo := &dbOrder{
|
||||||
|
ID: "foo",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: expiry,
|
||||||
|
}
|
||||||
|
bfoo, err := json.Marshal(ofoo)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
obar := &dbOrder{
|
||||||
|
ID: "bar",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: expiry,
|
||||||
|
}
|
||||||
|
bbar, err := json.Marshal(obar)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
return test{
|
||||||
|
db: &db.MockNoSQLDB{
|
||||||
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
||||||
|
switch string(bucket) {
|
||||||
|
case string(ordersByAccountIDTable):
|
||||||
|
return bOldOids, nil
|
||||||
|
case string(orderTable):
|
||||||
|
switch string(key) {
|
||||||
|
case "foo":
|
||||||
|
assert.Equals(t, key, []byte("foo"))
|
||||||
|
return bfoo, nil
|
||||||
|
case "bar":
|
||||||
|
assert.Equals(t, key, []byte("bar"))
|
||||||
|
return bbar, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected key %s", string(key)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
||||||
|
switch string(bucket) {
|
||||||
|
case string(orderTable):
|
||||||
|
return nil, true, nil
|
||||||
|
case string(ordersByAccountIDTable):
|
||||||
|
assert.Equals(t, key, []byte(accID))
|
||||||
|
assert.Equals(t, old, bOldOids)
|
||||||
|
assert.Equals(t, nu, bAddOids)
|
||||||
|
return nil, true, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket)))
|
||||||
|
return nil, false, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
addOids: addOids,
|
||||||
|
res: addOids,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ok/old-and-new-2": func(t *testing.T) test {
|
||||||
|
oldOids := []string{"foo", "bar", "baz"}
|
||||||
|
bOldOids, err := json.Marshal(oldOids)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
addOids := []string{"zap", "zar"}
|
||||||
|
now := clock.Now()
|
||||||
|
min5 := now.Add(5 * time.Minute)
|
||||||
|
expiry := now.Add(-5 * time.Minute)
|
||||||
|
|
||||||
|
o1 := &dbOrder{
|
||||||
|
ID: "foo",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: min5,
|
||||||
|
AuthorizationIDs: []string{"a"},
|
||||||
|
}
|
||||||
|
bo1, err := json.Marshal(o1)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
o2 := &dbOrder{
|
||||||
|
ID: "bar",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: expiry,
|
||||||
|
}
|
||||||
|
bo2, err := json.Marshal(o2)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
o3 := &dbOrder{
|
||||||
|
ID: "baz",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: min5,
|
||||||
|
AuthorizationIDs: []string{"b"},
|
||||||
|
}
|
||||||
|
bo3, err := json.Marshal(o3)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
|
||||||
|
az1 := &dbAuthz{
|
||||||
|
ID: "a",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: min5,
|
||||||
|
ChallengeIDs: []string{"aa"},
|
||||||
|
}
|
||||||
|
baz1, err := json.Marshal(az1)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
az2 := &dbAuthz{
|
||||||
|
ID: "b",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
ExpiresAt: min5,
|
||||||
|
ChallengeIDs: []string{"bb"},
|
||||||
|
}
|
||||||
|
baz2, err := json.Marshal(az2)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
|
||||||
|
ch1 := &dbChallenge{
|
||||||
|
ID: "aa",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
}
|
||||||
|
bch1, err := json.Marshal(ch1)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
ch2 := &dbChallenge{
|
||||||
|
ID: "bb",
|
||||||
|
Status: acme.StatusPending,
|
||||||
|
}
|
||||||
|
bch2, err := json.Marshal(ch2)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
|
||||||
|
newOids := append([]string{"foo", "baz"}, addOids...)
|
||||||
|
bNewOids, err := json.Marshal(newOids)
|
||||||
|
assert.FatalError(t, err)
|
||||||
|
|
||||||
|
return test{
|
||||||
|
db: &db.MockNoSQLDB{
|
||||||
|
MGet: func(bucket, key []byte) ([]byte, error) {
|
||||||
|
switch string(bucket) {
|
||||||
|
case string(authzTable):
|
||||||
|
switch string(key) {
|
||||||
|
case "a":
|
||||||
|
return baz1, nil
|
||||||
|
case "b":
|
||||||
|
return baz2, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected authz key %s", string(key)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
case string(challengeTable):
|
||||||
|
switch string(key) {
|
||||||
|
case "aa":
|
||||||
|
return bch1, nil
|
||||||
|
case "bb":
|
||||||
|
return bch2, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected challenge key %s", string(key)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
case string(ordersByAccountIDTable):
|
||||||
|
return bOldOids, nil
|
||||||
|
case string(orderTable):
|
||||||
|
switch string(key) {
|
||||||
|
case "foo":
|
||||||
|
return bo1, nil
|
||||||
|
case "bar":
|
||||||
|
return bo2, nil
|
||||||
|
case "baz":
|
||||||
|
return bo3, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected key %s", string(key)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket)))
|
||||||
|
return nil, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
MCmpAndSwap: func(bucket, key, old, nu []byte) ([]byte, bool, error) {
|
||||||
|
switch string(bucket) {
|
||||||
|
case string(orderTable):
|
||||||
|
return nil, true, nil
|
||||||
|
case string(ordersByAccountIDTable):
|
||||||
|
assert.Equals(t, key, []byte(accID))
|
||||||
|
assert.Equals(t, old, bOldOids)
|
||||||
|
assert.Equals(t, nu, bNewOids)
|
||||||
|
return nil, true, nil
|
||||||
|
default:
|
||||||
|
assert.FatalError(t, errors.Errorf("unexpected bucket %s", string(bucket)))
|
||||||
|
return nil, false, errors.New("force")
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
addOids: addOids,
|
||||||
|
res: newOids,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for name, run := range tests {
|
||||||
|
tc := run(t)
|
||||||
|
t.Run(name, func(t *testing.T) {
|
||||||
|
db := DB{db: tc.db}
|
||||||
|
var (
|
||||||
|
res []string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
if tc.addOids == nil {
|
||||||
|
res, err = db.updateAddOrderIDs(context.Background(), accID)
|
||||||
|
} else {
|
||||||
|
res, err = db.updateAddOrderIDs(context.Background(), accID, tc.addOids...)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
switch k := err.(type) {
|
||||||
|
case *acme.Error:
|
||||||
|
if assert.NotNil(t, tc.acmeErr) {
|
||||||
|
assert.Equals(t, k.Type, tc.acmeErr.Type)
|
||||||
|
assert.Equals(t, k.Detail, tc.acmeErr.Detail)
|
||||||
|
assert.Equals(t, k.Status, tc.acmeErr.Status)
|
||||||
|
assert.Equals(t, k.Err.Error(), tc.acmeErr.Err.Error())
|
||||||
|
assert.Equals(t, k.Detail, tc.acmeErr.Detail)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
if assert.NotNil(t, tc.err) {
|
||||||
|
assert.HasPrefix(t, err.Error(), tc.err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if assert.Nil(t, tc.err) {
|
||||||
|
assert.True(t, reflect.DeepEqual(res, tc.res))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue