forked from TrueCloudLab/certificates
Add provisioner to remove endpoint and clear reference index on delete
This commit is contained in:
parent
746c5c9fd9
commit
c2bc1351c6
5 changed files with 35 additions and 16 deletions
|
@ -23,7 +23,7 @@ type DB interface {
|
||||||
GetExternalAccountKey(ctx context.Context, provisionerName string, keyID string) (*ExternalAccountKey, error)
|
GetExternalAccountKey(ctx context.Context, provisionerName string, keyID string) (*ExternalAccountKey, error)
|
||||||
GetExternalAccountKeys(ctx context.Context, provisionerName string) ([]*ExternalAccountKey, error)
|
GetExternalAccountKeys(ctx context.Context, provisionerName string) ([]*ExternalAccountKey, error)
|
||||||
GetExternalAccountKeyByReference(ctx context.Context, provisionerName string, reference string) (*ExternalAccountKey, error)
|
GetExternalAccountKeyByReference(ctx context.Context, provisionerName string, reference string) (*ExternalAccountKey, error)
|
||||||
DeleteExternalAccountKey(ctx context.Context, keyID string) error
|
DeleteExternalAccountKey(ctx context.Context, provisionerName string, keyID string) error
|
||||||
UpdateExternalAccountKey(ctx context.Context, provisionerName string, eak *ExternalAccountKey) error
|
UpdateExternalAccountKey(ctx context.Context, provisionerName string, eak *ExternalAccountKey) error
|
||||||
|
|
||||||
CreateNonce(ctx context.Context) (Nonce, error)
|
CreateNonce(ctx context.Context) (Nonce, error)
|
||||||
|
@ -58,7 +58,7 @@ type MockDB struct {
|
||||||
MockGetExternalAccountKey func(ctx context.Context, provisionerName string, keyID string) (*ExternalAccountKey, error)
|
MockGetExternalAccountKey func(ctx context.Context, provisionerName string, keyID string) (*ExternalAccountKey, error)
|
||||||
MockGetExternalAccountKeys func(ctx context.Context, provisionerName string) ([]*ExternalAccountKey, error)
|
MockGetExternalAccountKeys func(ctx context.Context, provisionerName string) ([]*ExternalAccountKey, error)
|
||||||
MockGetExternalAccountKeyByReference func(ctx context.Context, provisionerName string, reference string) (*ExternalAccountKey, error)
|
MockGetExternalAccountKeyByReference func(ctx context.Context, provisionerName string, reference string) (*ExternalAccountKey, error)
|
||||||
MockDeleteExternalAccountKey func(ctx context.Context, keyID string) error
|
MockDeleteExternalAccountKey func(ctx context.Context, provisionerName string, keyID string) error
|
||||||
MockUpdateExternalAccountKey func(ctx context.Context, provisionerName string, eak *ExternalAccountKey) error
|
MockUpdateExternalAccountKey func(ctx context.Context, provisionerName string, eak *ExternalAccountKey) error
|
||||||
|
|
||||||
MockCreateNonce func(ctx context.Context) (Nonce, error)
|
MockCreateNonce func(ctx context.Context) (Nonce, error)
|
||||||
|
@ -165,9 +165,9 @@ func (m *MockDB) GetExternalAccountKeyByReference(ctx context.Context, provision
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteExternalAccountKey mock
|
// DeleteExternalAccountKey mock
|
||||||
func (m *MockDB) DeleteExternalAccountKey(ctx context.Context, keyID string) error {
|
func (m *MockDB) DeleteExternalAccountKey(ctx context.Context, provisionerName string, keyID string) error {
|
||||||
if m.MockDeleteExternalAccountKey != nil {
|
if m.MockDeleteExternalAccountKey != nil {
|
||||||
return m.MockDeleteExternalAccountKey(ctx, keyID)
|
return m.MockDeleteExternalAccountKey(ctx, provisionerName, keyID)
|
||||||
} else if m.MockError != nil {
|
} else if m.MockError != nil {
|
||||||
return m.MockError
|
return m.MockError
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/smallstep/certificates/acme"
|
"github.com/smallstep/certificates/acme"
|
||||||
"github.com/smallstep/nosql"
|
|
||||||
nosqlDB "github.com/smallstep/nosql"
|
nosqlDB "github.com/smallstep/nosql"
|
||||||
"go.step.sm/crypto/jose"
|
"go.step.sm/crypto/jose"
|
||||||
)
|
)
|
||||||
|
@ -238,11 +237,21 @@ func (db *DB) GetExternalAccountKey(ctx context.Context, provisionerName string,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) DeleteExternalAccountKey(ctx context.Context, keyID string) error {
|
func (db *DB) DeleteExternalAccountKey(ctx context.Context, provisionerName string, keyID string) error {
|
||||||
_, err := db.db.Get(externalAccountKeyTable, []byte(keyID))
|
dbeak, err := db.getDBExternalAccountKey(ctx, keyID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error loading ACME EAB Key with Key ID %s", keyID)
|
return errors.Wrapf(err, "error loading ACME EAB Key with Key ID %s", keyID)
|
||||||
}
|
}
|
||||||
|
if dbeak.Provisioner != provisionerName {
|
||||||
|
// TODO: change these ACME error types; they don't make a lot of sense if used in the Admin APIs
|
||||||
|
return acme.NewError(acme.ErrorUnauthorizedType, "name of provisioner does not match provisioner for which the EAB key was created")
|
||||||
|
}
|
||||||
|
if dbeak.Reference != "" {
|
||||||
|
err = db.db.Del(externalAccountKeysByReferenceTable, []byte(dbeak.Reference))
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "error deleting ACME EAB Key Reference with Key ID %s and reference %s", keyID, dbeak.Reference)
|
||||||
|
}
|
||||||
|
}
|
||||||
err = db.db.Del(externalAccountKeyTable, []byte(keyID))
|
err = db.db.Del(externalAccountKeyTable, []byte(keyID))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error deleting ACME EAB Key with Key ID %s", keyID)
|
return errors.Wrapf(err, "error deleting ACME EAB Key with Key ID %s", keyID)
|
||||||
|
@ -286,7 +295,7 @@ func (db *DB) GetExternalAccountKeyByReference(ctx context.Context, provisionerN
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
k, err := db.db.Get(externalAccountKeysByReferenceTable, []byte(reference))
|
k, err := db.db.Get(externalAccountKeysByReferenceTable, []byte(reference))
|
||||||
if nosql.IsErrNotFound(err) {
|
if nosqlDB.IsErrNotFound(err) {
|
||||||
return nil, errors.Errorf("ACME EAB key for reference %s not found", reference)
|
return nil, errors.Errorf("ACME EAB key for reference %s not found", reference)
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, errors.Wrapf(err, "error loading ACME EAB key for reference %s", reference)
|
return nil, errors.Wrapf(err, "error loading ACME EAB key for reference %s", reference)
|
||||||
|
|
|
@ -120,12 +120,22 @@ func (h *Handler) CreateExternalAccountKey(w http.ResponseWriter, r *http.Reques
|
||||||
|
|
||||||
// DeleteExternalAccountKey deletes an ACME External Account Key.
|
// DeleteExternalAccountKey deletes an ACME External Account Key.
|
||||||
func (h *Handler) DeleteExternalAccountKey(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) DeleteExternalAccountKey(w http.ResponseWriter, r *http.Request) {
|
||||||
id := chi.URLParam(r, "id")
|
provisioner := chi.URLParam(r, "prov")
|
||||||
|
keyID := chi.URLParam(r, "id")
|
||||||
|
|
||||||
// TODO: add provisioner as parameter, so that check can be performed if EAB is enabled or not
|
eabEnabled, err := h.provisionerHasEABEnabled(r.Context(), provisioner)
|
||||||
|
if err != nil {
|
||||||
|
api.WriteError(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err := h.acmeDB.DeleteExternalAccountKey(r.Context(), id); err != nil {
|
if !eabEnabled {
|
||||||
api.WriteError(w, admin.WrapErrorISE(err, "error deleting ACME EAB Key %s", id))
|
api.WriteError(w, admin.NewError(admin.ErrorBadRequestType, "ACME EAB not enabled for provisioner %s", provisioner))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.acmeDB.DeleteExternalAccountKey(r.Context(), provisioner, keyID); err != nil {
|
||||||
|
api.WriteError(w, admin.WrapErrorISE(err, "error deleting ACME EAB Key %s", keyID))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,5 +47,5 @@ func (h *Handler) Route(r api.Router) {
|
||||||
r.MethodFunc("GET", "/acme/eab/{prov}/{ref}", authnz(h.GetExternalAccountKeys))
|
r.MethodFunc("GET", "/acme/eab/{prov}/{ref}", authnz(h.GetExternalAccountKeys))
|
||||||
r.MethodFunc("GET", "/acme/eab/{prov}", authnz(h.GetExternalAccountKeys))
|
r.MethodFunc("GET", "/acme/eab/{prov}", authnz(h.GetExternalAccountKeys))
|
||||||
r.MethodFunc("POST", "/acme/eab", authnz(h.CreateExternalAccountKey))
|
r.MethodFunc("POST", "/acme/eab", authnz(h.CreateExternalAccountKey))
|
||||||
r.MethodFunc("DELETE", "/acme/eab/{id}", authnz(h.DeleteExternalAccountKey))
|
r.MethodFunc("DELETE", "/acme/eab/{prov}/{id}", authnz(h.DeleteExternalAccountKey))
|
||||||
}
|
}
|
||||||
|
|
|
@ -637,10 +637,10 @@ retry:
|
||||||
return eabKey, nil
|
return eabKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveExternalAccountKey performs the DELETE /admin/acme/eab/{key_id} request to the CA.
|
// RemoveExternalAccountKey performs the DELETE /admin/acme/eab/{prov}/{key_id} request to the CA.
|
||||||
func (c *AdminClient) RemoveExternalAccountKey(keyID string) error {
|
func (c *AdminClient) RemoveExternalAccountKey(provisionerName string, keyID string) error {
|
||||||
var retried bool
|
var retried bool
|
||||||
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join(adminURLPrefix, "acme/eab", keyID)})
|
u := c.endpoint.ResolveReference(&url.URL{Path: path.Join(adminURLPrefix, "acme/eab", provisionerName, "/", keyID)})
|
||||||
tok, err := c.generateAdminToken(u.Path)
|
tok, err := c.generateAdminToken(u.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "error generating admin token")
|
return errors.Wrapf(err, "error generating admin token")
|
||||||
|
|
Loading…
Reference in a new issue