ef16febf40
The ACME EAB keys are now also indexed by the provisioner. This solves part of the issue in which too many EAB keys may be in memory at a given time.
146 lines
3.5 KiB
Go
146 lines
3.5 KiB
Go
package acme
|
|
|
|
import (
|
|
"crypto"
|
|
"encoding/base64"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/smallstep/assert"
|
|
"go.step.sm/crypto/jose"
|
|
)
|
|
|
|
func TestKeyToID(t *testing.T) {
|
|
type test struct {
|
|
jwk *jose.JSONWebKey
|
|
exp string
|
|
err *Error
|
|
}
|
|
tests := map[string]func(t *testing.T) test{
|
|
"fail/error-generating-thumbprint": func(t *testing.T) test {
|
|
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
|
|
assert.FatalError(t, err)
|
|
jwk.Key = "foo"
|
|
return test{
|
|
jwk: jwk,
|
|
err: NewErrorISE("error generating jwk thumbprint: square/go-jose: unknown key type 'string'"),
|
|
}
|
|
},
|
|
"ok": func(t *testing.T) test {
|
|
jwk, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
|
|
assert.FatalError(t, err)
|
|
|
|
kid, err := jwk.Thumbprint(crypto.SHA256)
|
|
assert.FatalError(t, err)
|
|
|
|
return test{
|
|
jwk: jwk,
|
|
exp: base64.RawURLEncoding.EncodeToString(kid),
|
|
}
|
|
},
|
|
}
|
|
for name, run := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
tc := run(t)
|
|
if id, err := KeyToID(tc.jwk); err != nil {
|
|
if assert.NotNil(t, tc.err) {
|
|
switch k := err.(type) {
|
|
case *Error:
|
|
assert.Equals(t, k.Type, tc.err.Type)
|
|
assert.Equals(t, k.Detail, tc.err.Detail)
|
|
assert.Equals(t, k.Status, tc.err.Status)
|
|
assert.Equals(t, k.Err.Error(), tc.err.Err.Error())
|
|
assert.Equals(t, k.Detail, tc.err.Detail)
|
|
default:
|
|
assert.FatalError(t, errors.New("unexpected error type"))
|
|
}
|
|
}
|
|
} else {
|
|
if assert.Nil(t, tc.err) {
|
|
assert.Equals(t, id, tc.exp)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAccount_IsValid(t *testing.T) {
|
|
type test struct {
|
|
acc *Account
|
|
exp bool
|
|
}
|
|
tests := map[string]test{
|
|
"valid": {acc: &Account{Status: StatusValid}, exp: true},
|
|
"invalid": {acc: &Account{Status: StatusInvalid}, exp: false},
|
|
}
|
|
for name, tc := range tests {
|
|
t.Run(name, func(t *testing.T) {
|
|
assert.Equals(t, tc.acc.IsValid(), tc.exp)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestExternalAccountKey_BindTo(t *testing.T) {
|
|
boundAt := time.Now()
|
|
tests := []struct {
|
|
name string
|
|
eak *ExternalAccountKey
|
|
acct *Account
|
|
err *Error
|
|
}{
|
|
{
|
|
name: "ok",
|
|
eak: &ExternalAccountKey{
|
|
ID: "eakID",
|
|
ProvisionerID: "provID",
|
|
Reference: "ref",
|
|
KeyBytes: []byte{1, 3, 3, 7},
|
|
},
|
|
acct: &Account{
|
|
ID: "accountID",
|
|
},
|
|
err: nil,
|
|
},
|
|
{
|
|
name: "fail/already-bound",
|
|
eak: &ExternalAccountKey{
|
|
ID: "eakID",
|
|
ProvisionerID: "provID",
|
|
Reference: "ref",
|
|
KeyBytes: []byte{1, 3, 3, 7},
|
|
AccountID: "someAccountID",
|
|
BoundAt: boundAt,
|
|
},
|
|
acct: &Account{
|
|
ID: "accountID",
|
|
},
|
|
err: NewError(ErrorUnauthorizedType, "external account binding key with id '%s' was already bound to account '%s' on %s", "eakID", "someAccountID", boundAt),
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
eak := tt.eak
|
|
acct := tt.acct
|
|
err := eak.BindTo(acct)
|
|
wantErr := tt.err != nil
|
|
gotErr := err != nil
|
|
if wantErr != gotErr {
|
|
t.Errorf("ExternalAccountKey.BindTo() error = %v, wantErr %v", err, tt.err)
|
|
}
|
|
if wantErr {
|
|
assert.NotNil(t, err)
|
|
assert.Type(t, &Error{}, err)
|
|
ae, _ := err.(*Error)
|
|
assert.Equals(t, ae.Type, tt.err.Type)
|
|
assert.Equals(t, ae.Detail, tt.err.Detail)
|
|
assert.Equals(t, ae.Identifier, tt.err.Identifier)
|
|
assert.Equals(t, ae.Subproblems, tt.err.Subproblems)
|
|
} else {
|
|
assert.Equals(t, eak.AccountID, acct.ID)
|
|
assert.Equals(t, eak.KeyBytes, []byte{})
|
|
assert.NotNil(t, eak.BoundAt)
|
|
}
|
|
})
|
|
}
|
|
}
|