Make authentication work for /admin/eak

This commit is contained in:
Herman Slatman 2021-07-22 22:43:21 +02:00
parent d669f3cb14
commit b65a588d5b
No known key found for this signature in database
GPG key ID: F4D8A44EA0A75A4F
3 changed files with 45 additions and 7 deletions

View file

@ -7,12 +7,12 @@ import (
"github.com/smallstep/certificates/authority/admin" "github.com/smallstep/certificates/authority/admin"
) )
// CreateExternalAccountKeyRequest is the type for GET /admin/eak requests // CreateExternalAccountKeyRequest is the type for POST /admin/eak requests
type CreateExternalAccountKeyRequest struct { type CreateExternalAccountKeyRequest struct {
Name string `json:"name"` Name string `json:"name"`
} }
// CreateExternalAccountKeyResponse is the type for GET /admin/eak responses // CreateExternalAccountKeyResponse is the type for POST /admin/eak responses
type CreateExternalAccountKeyResponse struct { type CreateExternalAccountKeyResponse struct {
KeyID string `json:"keyID"` KeyID string `json:"keyID"`
Name string `json:"name"` Name string `json:"name"`
@ -21,17 +21,17 @@ type CreateExternalAccountKeyResponse struct {
// CreateExternalAccountKey creates a new External Account Binding key // CreateExternalAccountKey creates a new External Account Binding key
func (h *Handler) CreateExternalAccountKey(w http.ResponseWriter, r *http.Request) { func (h *Handler) CreateExternalAccountKey(w http.ResponseWriter, r *http.Request) {
var eakRequest = new(CreateExternalAccountKeyRequest) var body CreateExternalAccountKeyRequest
if err := api.ReadJSON(r.Body, eakRequest); err != nil { // TODO: rewrite into protobuf json (likely) if err := api.ReadJSON(r.Body, &body); err != nil { // TODO: rewrite into protobuf json (likely)
api.WriteError(w, err) api.WriteError(w, err)
return return
} }
// TODO: Validate input // TODO: Validate input
eak, err := h.db.CreateExternalAccountKey(r.Context(), eakRequest.Name) eak, err := h.db.CreateExternalAccountKey(r.Context(), body.Name)
if err != nil { if err != nil {
api.WriteError(w, admin.WrapErrorISE(err, "error creating external account key %s", eakRequest.Name)) api.WriteError(w, admin.WrapErrorISE(err, "error creating external account key %s", body.Name))
return return
} }

View file

@ -40,5 +40,5 @@ func (h *Handler) Route(r api.Router) {
r.MethodFunc("DELETE", "/admins/{id}", authnz(h.DeleteAdmin)) r.MethodFunc("DELETE", "/admins/{id}", authnz(h.DeleteAdmin))
// External Account Binding Keys // External Account Binding Keys
r.MethodFunc("POST", "/eak", h.CreateExternalAccountKey) // TODO: authnz r.MethodFunc("POST", "/eak", authnz(h.CreateExternalAccountKey))
} }

View file

@ -12,6 +12,7 @@ import (
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/certificates/api"
"github.com/smallstep/certificates/authority/admin" "github.com/smallstep/certificates/authority/admin"
adminAPI "github.com/smallstep/certificates/authority/admin/api" adminAPI "github.com/smallstep/certificates/authority/admin/api"
"github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/authority/provisioner"
@ -558,6 +559,43 @@ retry:
return nil return nil
} }
// CreateExternalAccountKey performs the POST /admin/eak request to the CA.
func (c *AdminClient) CreateExternalAccountKey(eakRequest *adminAPI.CreateExternalAccountKeyRequest) (*adminAPI.CreateExternalAccountKeyResponse, error) {
var retried bool
//body, err := protojson.Marshal(req)
body, err := json.Marshal(eakRequest)
if err != nil {
return nil, errs.Wrap(http.StatusInternalServerError, err, "error marshaling request")
}
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join(adminURLPrefix, "eak")})
tok, err := c.generateAdminToken(u.Path)
if err != nil {
return nil, errors.Wrapf(err, "error generating admin token")
}
req, err := http.NewRequest("POST", u.String(), bytes.NewReader(body))
if err != nil {
return nil, errors.Wrapf(err, "create POST %s request failed", u)
}
req.Header.Add("Authorization", tok)
retry:
resp, err := c.client.Do(req)
if err != nil {
return nil, errors.Wrapf(err, "client POST %s failed", u)
}
if resp.StatusCode >= 400 {
if !retried && c.retryOnError(resp) {
retried = true
goto retry
}
return nil, readAdminError(resp.Body)
}
var eakResp = new(adminAPI.CreateExternalAccountKeyResponse)
if err := api.ReadJSON(resp.Body, &eakResp); err != nil {
return nil, errors.Wrapf(err, "error reading %s", u)
}
return eakResp, nil
}
func readAdminError(r io.ReadCloser) error { func readAdminError(r io.ReadCloser) error {
defer r.Close() defer r.Close()
adminErr := new(admin.Error) adminErr := new(admin.Error)