diff --git a/acme/api/account.go b/acme/api/account.go index bf8fdfe5..fa5597e0 100644 --- a/acme/api/account.go +++ b/acme/api/account.go @@ -265,7 +265,6 @@ func (h *Handler) validateExternalAccountBinding(ctx context.Context, nar *NewAc return nil, acme.WrapErrorISE(err, "error parsing externalAccountBinding jws") } - // TODO: verify supported algorithms against the incoming alg (and corresponding settings)? // TODO: implement strategy pattern to allow for different ways of verification (i.e. webhook call) based on configuration keyID := eabJWS.Signatures[0].Protected.KeyID diff --git a/authority/admin/api/acme.go b/authority/admin/api/acme.go index 36fc10fe..7772e435 100644 --- a/authority/admin/api/acme.go +++ b/authority/admin/api/acme.go @@ -5,6 +5,7 @@ import ( "github.com/smallstep/certificates/api" "github.com/smallstep/certificates/authority/admin" + "go.step.sm/linkedca" ) // CreateExternalAccountKeyRequest is the type for POST /admin/acme/eab requests @@ -13,29 +14,35 @@ type CreateExternalAccountKeyRequest struct { Name string `json:"name"` } -// CreateExternalAccountKeyResponse is the type for POST /admin/acme/eab responses -type CreateExternalAccountKeyResponse struct { - ProvisionerName string `json:"provisioner"` - KeyID string `json:"keyID"` - Name string `json:"name"` - Key []byte `json:"key"` +// Validate validates a new-admin request body. +func (r *CreateExternalAccountKeyRequest) Validate() error { + if r.ProvisionerName == "" { + return admin.NewError(admin.ErrorBadRequestType, "provisioner name cannot be empty") + } + if r.Name == "" { + return admin.NewError(admin.ErrorBadRequestType, "name / reference cannot be empty") + } + return nil } // GetExternalAccountKeysResponse is the type for GET /admin/acme/eab responses type GetExternalAccountKeysResponse struct { - EAKs []*CreateExternalAccountKeyResponse `json:"eaks"` - NextCursor string `json:"nextCursor"` + EAKs []*linkedca.EABKey `json:"eaks"` + NextCursor string `json:"nextCursor"` } // CreateExternalAccountKey creates a new External Account Binding key func (h *Handler) CreateExternalAccountKey(w http.ResponseWriter, r *http.Request) { var body CreateExternalAccountKeyRequest if err := api.ReadJSON(r.Body, &body); err != nil { // TODO: rewrite into protobuf json (likely) - api.WriteError(w, err) + api.WriteError(w, admin.WrapError(admin.ErrorBadRequestType, err, "error reading request body")) return } - // TODO: Validate input + if err := body.Validate(); err != nil { + api.WriteError(w, err) + return + } eak, err := h.acmeDB.CreateExternalAccountKey(r.Context(), body.ProvisionerName, body.Name) if err != nil { @@ -43,14 +50,14 @@ func (h *Handler) CreateExternalAccountKey(w http.ResponseWriter, r *http.Reques return } - eakResponse := CreateExternalAccountKeyResponse{ + response := &linkedca.EABKey{ + EabKid: eak.ID, + EabHmacKey: eak.KeyBytes, ProvisionerName: eak.ProvisionerName, - KeyID: eak.ID, Name: eak.Name, - Key: eak.KeyBytes, } - api.JSONStatus(w, eakResponse, http.StatusCreated) // TODO: rewrite into protobuf json (likely) + api.ProtoJSONStatus(w, response, http.StatusCreated) } // GetExternalAccountKeys returns a segment of ACME EAB Keys. diff --git a/ca/adminClient.go b/ca/adminClient.go index 7f24efa9..06462051 100644 --- a/ca/adminClient.go +++ b/ca/adminClient.go @@ -12,7 +12,6 @@ import ( "time" "github.com/pkg/errors" - "github.com/smallstep/certificates/api" "github.com/smallstep/certificates/authority/admin" adminAPI "github.com/smallstep/certificates/authority/admin/api" "github.com/smallstep/certificates/authority/provisioner" @@ -600,7 +599,7 @@ retry: } // CreateExternalAccountKey performs the POST /admin/acme/eab request to the CA. -func (c *AdminClient) CreateExternalAccountKey(eakRequest *adminAPI.CreateExternalAccountKeyRequest) (*adminAPI.CreateExternalAccountKeyResponse, error) { +func (c *AdminClient) CreateExternalAccountKey(eakRequest *adminAPI.CreateExternalAccountKeyRequest) (*linkedca.EABKey, error) { var retried bool body, err := json.Marshal(eakRequest) if err != nil { @@ -628,18 +627,18 @@ retry: } return nil, readAdminError(resp.Body) } - var eakResp = new(adminAPI.CreateExternalAccountKeyResponse) - if err := api.ReadJSON(resp.Body, &eakResp); err != nil { + var eabKey = new(linkedca.EABKey) + if err := readProtoJSON(resp.Body, eabKey); err != nil { return nil, errors.Wrapf(err, "error reading %s", u) } - return eakResp, nil + return eabKey, nil } // GetExternalAccountKeys returns all ACME EAB Keys from the GET /admin/acme/eab request to the CA. -func (c *AdminClient) GetExternalAccountKeys(opts ...AdminOption) ([]*adminAPI.CreateExternalAccountKeyResponse, error) { +func (c *AdminClient) GetExternalAccountKeys(opts ...AdminOption) ([]*linkedca.EABKey, error) { var ( cursor = "" - eaks = []*adminAPI.CreateExternalAccountKeyResponse{} + eaks = []*linkedca.EABKey{} ) for { resp, err := c.GetExternalAccountKeysPaginate(WithAdminCursor(cursor), WithAdminLimit(100))