Merge branch 'dcow/key-change-error'

Fixes: https://github.com/smallstep/certificates/pull/276
This commit is contained in:
David Cowden 2020-05-28 17:10:06 -07:00
commit 30bfba48d5
2 changed files with 50 additions and 1 deletions

View file

@ -59,6 +59,7 @@ func (h *Handler) Route(r api.Router) {
r.MethodFunc("POST", getLink(acme.NewAccountLink, "{provisionerID}", false, nil), extractPayloadByJWK(h.NewAccount)) r.MethodFunc("POST", getLink(acme.NewAccountLink, "{provisionerID}", false, nil), extractPayloadByJWK(h.NewAccount))
r.MethodFunc("POST", getLink(acme.AccountLink, "{provisionerID}", false, nil, "{accID}"), extractPayloadByKid(h.GetUpdateAccount)) r.MethodFunc("POST", getLink(acme.AccountLink, "{provisionerID}", false, nil, "{accID}"), extractPayloadByKid(h.GetUpdateAccount))
r.MethodFunc("POST", getLink(acme.KeyChangeLink, "{provisionerID}", false, nil, "{accID}"), extractPayloadByKid(h.NotImplemented))
r.MethodFunc("POST", getLink(acme.NewOrderLink, "{provisionerID}", false, nil), extractPayloadByKid(h.NewOrder)) r.MethodFunc("POST", getLink(acme.NewOrderLink, "{provisionerID}", false, nil), extractPayloadByKid(h.NewOrder))
r.MethodFunc("POST", getLink(acme.OrderLink, "{provisionerID}", false, nil, "{ordID}"), extractPayloadByKid(h.isPostAsGet(h.GetOrder))) r.MethodFunc("POST", getLink(acme.OrderLink, "{provisionerID}", false, nil, "{ordID}"), extractPayloadByKid(h.isPostAsGet(h.GetOrder)))
r.MethodFunc("POST", getLink(acme.OrdersByAccountLink, "{provisionerID}", false, nil, "{accID}"), extractPayloadByKid(h.isPostAsGet(h.GetOrdersByAccount))) r.MethodFunc("POST", getLink(acme.OrdersByAccountLink, "{provisionerID}", false, nil, "{accID}"), extractPayloadByKid(h.isPostAsGet(h.GetOrdersByAccount)))
@ -89,6 +90,12 @@ func (h *Handler) GetDirectory(w http.ResponseWriter, r *http.Request) {
api.JSON(w, dir) api.JSON(w, dir)
} }
// NotImplemented returns a 501 and is generally a placeholder for functionality which
// MAY be added at some point in the future but is not in any way a guarantee of such.
func (h *Handler) NotImplemented(w http.ResponseWriter, r *http.Request) {
api.WriteError(w, acme.NotImplemented(nil).ToACME())
}
// GetAuthz ACME api for retrieving an Authz. // GetAuthz ACME api for retrieving an Authz.
func (h *Handler) GetAuthz(w http.ResponseWriter, r *http.Request) { func (h *Handler) GetAuthz(w http.ResponseWriter, r *http.Request) {
acc, err := acme.AccountFromContext(r.Context()) acc, err := acme.AccountFromContext(r.Context())

View file

@ -194,6 +194,16 @@ func ServerInternalErr(err error) *Error {
} }
} }
// NotImplemented returns a new acme error.
func NotImplemented(err error) *Error {
return &Error{
Type: notImplemented,
Detail: "The requested operation is not implemented",
Status: 501,
Err: err,
}
}
// TLSErr returns a new acme error. // TLSErr returns a new acme error.
func TLSErr(err error) *Error { func TLSErr(err error) *Error {
return &Error{ return &Error{
@ -296,6 +306,8 @@ const (
unsupportedIdentifierErr unsupportedIdentifierErr
// Visit the “instance” URL and take actions specified there // Visit the “instance” URL and take actions specified there
userActionRequiredErr userActionRequiredErr
// The operation is not implemented
notImplemented
) )
// String returns the string representation of the acme problem type, // String returns the string representation of the acme problem type,
@ -350,6 +362,8 @@ func (ap ProbType) String() string {
return "unsupportedIdentifier" return "unsupportedIdentifier"
case userActionRequiredErr: case userActionRequiredErr:
return "userActionRequired" return "userActionRequired"
case notImplemented:
return "notImplemented"
default: default:
return "unsupported type" return "unsupported type"
} }
@ -398,10 +412,38 @@ func (e *Error) Cause() error {
return e.Err return e.Err
} }
// Official returns true if this error's type is listed in §6.7 of RFC 8555.
// Error types in §6.7 are registered under IETF urn namespace:
//
// "urn:ietf:params:acme:error:"
//
// and should include the namespace as a prefix when appearing as a problem
// document.
//
// RFC 8555 also says:
//
// This list is not exhaustive. The server MAY return errors whose
// "type" field is set to a URI other than those defined above. Servers
// MUST NOT use the ACME URN namespace for errors not listed in the
// appropriate IANA registry (see Section 9.6). Clients SHOULD display
// the "detail" field of all errors.
//
// In this case Official returns `false` so that a different namespace can
// be used.
func (e *Error) Official() bool {
return e.Type != notImplemented
}
// ToACME returns an acme representation of the problem type. // ToACME returns an acme representation of the problem type.
// For official errors, the IETF ACME namespace is prepended to the error type.
// For our own errors, we use an (yet) unregistered smallstep acme namespace.
func (e *Error) ToACME() *AError { func (e *Error) ToACME() *AError {
prefix := "urn:step:acme:error"
if e.Official() {
prefix = "urn:ietf:params:acme:error:"
}
ae := &AError{ ae := &AError{
Type: "urn:ietf:params:acme:error:" + e.Type.String(), Type: prefix + e.Type.String(),
Detail: e.Error(), Detail: e.Error(),
Status: e.Status, Status: e.Status,
} }