Add new method ACMEClient.ValidateWithPayload
This new method will be used to validate to validate the device attestation payload.
This commit is contained in:
parent
f1c63bc38d
commit
ebce40e9b6
2 changed files with 109 additions and 3 deletions
|
@ -243,6 +243,19 @@ func (c *ACMEClient) ValidateChallenge(url string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// ValidateWithPayload will attempt to validate the challenge at the given url
|
||||
// with the given attestation payload.
|
||||
func (c *ACMEClient) ValidateWithPayload(url string, payload []byte) error {
|
||||
resp, err := c.post(payload, url, withKid(c))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode >= 400 {
|
||||
return readACMEError(resp.Body)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAuthz returns the Authz at the given path.
|
||||
func (c *ACMEClient) GetAuthz(url string) (*acme.Authorization, error) {
|
||||
resp, err := c.post(nil, url, withKid(c))
|
||||
|
|
|
@ -12,13 +12,12 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"go.step.sm/crypto/jose"
|
||||
"go.step.sm/crypto/pemutil"
|
||||
|
||||
"github.com/smallstep/assert"
|
||||
"github.com/smallstep/certificates/acme"
|
||||
acmeAPI "github.com/smallstep/certificates/acme/api"
|
||||
"github.com/smallstep/certificates/api/render"
|
||||
"go.step.sm/crypto/jose"
|
||||
"go.step.sm/crypto/pemutil"
|
||||
)
|
||||
|
||||
func TestNewACMEClient(t *testing.T) {
|
||||
|
@ -980,6 +979,100 @@ func TestACMEClient_ValidateChallenge(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestACMEClient_ValidateWithPayload(t *testing.T) {
|
||||
key, err := jose.GenerateJWK("EC", "P-256", "ES256", "sig", "", 0)
|
||||
assert.FatalError(t, err)
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
assert.Equals(t, "step-http-client/1.0", req.Header.Get("User-Agent")) // check default User-Agent header
|
||||
|
||||
t.Log(req.RequestURI)
|
||||
w.Header().Set("Replay-Nonce", "nonce")
|
||||
switch req.RequestURI {
|
||||
case "/nonce":
|
||||
render.JSONStatus(w, []byte{}, 200)
|
||||
return
|
||||
case "/fail-nonce":
|
||||
render.JSONStatus(w, acme.NewError(acme.ErrorMalformedType, "malformed request"), 400)
|
||||
return
|
||||
}
|
||||
|
||||
// validate jws request protected headers and body
|
||||
body, err := io.ReadAll(req.Body)
|
||||
assert.FatalError(t, err)
|
||||
|
||||
jws, err := jose.ParseJWS(string(body))
|
||||
assert.FatalError(t, err)
|
||||
|
||||
hdr := jws.Signatures[0].Protected
|
||||
assert.Equals(t, hdr.Nonce, "nonce")
|
||||
|
||||
_, ok := hdr.ExtraHeaders["url"].(string)
|
||||
assert.Fatal(t, ok)
|
||||
assert.Equals(t, hdr.KeyID, "kid")
|
||||
|
||||
payload, err := jws.Verify(key.Public())
|
||||
assert.FatalError(t, err)
|
||||
assert.Equals(t, payload, []byte("the-payload"))
|
||||
|
||||
switch req.RequestURI {
|
||||
case "/ok":
|
||||
render.JSONStatus(w, acme.Challenge{
|
||||
Type: "device-attestation-01",
|
||||
Status: "valid",
|
||||
Token: "foo",
|
||||
}, 200)
|
||||
case "/fail":
|
||||
render.JSONStatus(w, acme.NewError(acme.ErrorMalformedType, "malformed request"), 400)
|
||||
}
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
type fields struct {
|
||||
client *http.Client
|
||||
dirLoc string
|
||||
dir *acmeAPI.Directory
|
||||
acc *acme.Account
|
||||
Key *jose.JSONWebKey
|
||||
kid string
|
||||
}
|
||||
type args struct {
|
||||
url string
|
||||
payload []byte
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantErr bool
|
||||
}{
|
||||
{"ok", fields{srv.Client(), srv.URL, &acmeAPI.Directory{
|
||||
NewNonce: srv.URL + "/nonce",
|
||||
}, nil, key, "kid"}, args{srv.URL + "/ok", []byte("the-payload")}, false},
|
||||
{"fail nonce", fields{srv.Client(), srv.URL, &acmeAPI.Directory{
|
||||
NewNonce: srv.URL + "/fail-nonce",
|
||||
}, nil, key, "kid"}, args{srv.URL + "/ok", []byte("the-payload")}, true},
|
||||
{"fail payload", fields{srv.Client(), srv.URL, &acmeAPI.Directory{
|
||||
NewNonce: srv.URL + "/nonce",
|
||||
}, nil, key, "kid"}, args{srv.URL + "/fail", []byte("the-payload")}, true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
c := &ACMEClient{
|
||||
client: tt.fields.client,
|
||||
dirLoc: tt.fields.dirLoc,
|
||||
dir: tt.fields.dir,
|
||||
acc: tt.fields.acc,
|
||||
Key: tt.fields.Key,
|
||||
kid: tt.fields.kid,
|
||||
}
|
||||
if err := c.ValidateWithPayload(tt.args.url, tt.args.payload); (err != nil) != tt.wantErr {
|
||||
t.Errorf("ACMEClient.ValidateWithPayload() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestACMEClient_FinalizeOrder(t *testing.T) {
|
||||
type test struct {
|
||||
r1, r2 interface{}
|
||||
|
|
Loading…
Reference in a new issue