certificates/acme/api/revoke.go
2021-07-02 22:51:15 +02:00

79 lines
2.2 KiB
Go

package api
import (
"crypto/x509"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"github.com/smallstep/certificates/api"
"github.com/smallstep/certificates/authority"
)
func (h *Handler) RevokeCert(w http.ResponseWriter, r *http.Request) {
// TODO: support the non-kid case, i.e. JWK with the public key of the cert
// base the account + certificate JWK instead of the kid (which is now the case)
// TODO: handle errors; sent the right ACME response back
ctx := r.Context()
_, err := accountFromContext(ctx)
if err != nil {
api.WriteError(w, err)
return
}
// TODO: do checks on account, i.e. is it still valid? is it allowed to do revocations? Revocations on the to be revoked cert?
_, err = provisionerFromContext(ctx)
if err != nil {
fmt.Println(err)
}
// TODO: let provisioner authorize the revocation? Necessary per provisioner? Or can it be done by the CA, like the Revoke itself.
p, err := payloadFromContext(ctx)
if err != nil {
fmt.Println(err)
}
type revokedCert struct {
Certificate string `json:"certificate"`
Reason int `json:"reason"` // TODO: is optional; handle accordingly
}
var rc revokedCert
err = json.Unmarshal(p.value, &rc)
if err != nil {
fmt.Println("error:", err)
}
c, err := base64.RawURLEncoding.DecodeString(rc.Certificate)
if err != nil {
fmt.Println("error:", err)
}
certToBeRevoked, err := x509.ParseCertificate(c)
if err != nil {
fmt.Println("error: failed to parse certificate: " + err.Error())
}
// TODO: check reason code; should be allowed; otherwise send error
options := &authority.RevokeOptions{
Serial: certToBeRevoked.SerialNumber.String(),
Reason: "test", // TODO: map it to the reason based on code?
ReasonCode: rc.Reason,
PassiveOnly: false,
MTLS: true, // TODO: should be false, I guess, but results in error: authority.Revoke; error parsing token: square/go-jose: compact JWS format must have three parts (OTT)
Crt: certToBeRevoked,
OTT: "",
}
err = h.ca.Revoke(ctx, options)
if err != nil {
fmt.Println("error: ", err.Error()) // TODO: send the right error; 400; alreadyRevoked (or something else went wrong, of course)
}
w.Write(nil)
}