Skip to content

Commit fcfb524

Browse files
committed
RequestCertificate: reset unconditionally instead of during retrieve
In Venafi#269, I got convinced that it would be a good solution to call "Reset" only if the "Retrieve" call returned a known message. Later on, we realized that there was a bad interaction between "Request" and "Reset(restart=true)". For some reason, when a problem arises (such as CA being down), TPP returns the old certificate, and vcert ends up showing the message "unmatched key modulus". We realized that calling "Reset(restart=false)" before Request prevents this bug. Although that's one extra HTTP call, it seems this call is very inexpensive. One downside that was brought up during the PR Venafi#269 was that any extra HTTP call would slow the TPP server because the HTTP called are "queued" (not concurrently processed).
1 parent 240fe8f commit fcfb524

1 file changed

Lines changed: 34 additions & 2 deletions

File tree

pkg/venafi/tpp/connector.go

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -678,19 +678,51 @@ func (c *Connector) proccessLocation(req *certificate.Request) error {
678678
return nil
679679
}
680680

681-
// RequestCertificate submits the CSR to TPP returning the DN of the requested Certificate
681+
// RequestCertificate requests the certificate to TPP and returns the DN of the
682+
// requested Certificate (this is called the "pickup ID" in the vcert CLI). If
683+
// the certificate is in the middle of an enrollment, the enrollment will be
684+
// reset before requesting (this doesn't affect the existing certificate if one
685+
// was already issued).
682686
func (c *Connector) RequestCertificate(req *certificate.Request) (requestID string, err error) {
683687
if req.Location != nil {
684688
err = c.proccessLocation(req)
685689
if err != nil {
686690
return
687691
}
688692
}
693+
694+
// Let's unconditionally reset any prior pending or failed enrollment. This
695+
// doesn't affect the existing certificate if one was already issued. At
696+
// first, we wanted to decide whether to reset or not by first retrieving
697+
// the certificate, but found that resetting unconditionally is simpler.
698+
// When the response to /reset is 400, we just ignore it; here are the three
699+
// expected responses:
700+
//
701+
// | Happy responses | Description |
702+
// |-----------------------------------------|----------------------------|
703+
// | 200 {"ProcessingResetCompleted": true} | Success |
704+
// | 400 {"Error":"CertificateDN error..."} | Certificate DN not found |
705+
// | 400 {"Error":"No reset is required..."} | No enrollment to be reset |
706+
certDN := getCertificateDN(c.zone, req.Subject.CommonName)
707+
statusCode, status, body, err := c.request("POST", urlResourceCertificateReset, struct {
708+
CertificateDN string `json:"CertificateDN"`
709+
Restart bool `json:"Restart"`
710+
}{
711+
CertificateDN: certDN,
712+
Restart: false,
713+
})
714+
if err != nil {
715+
return "", fmt.Errorf("while resetting certificate in case of previous enrollment: %w", err)
716+
}
717+
if statusCode != http.StatusOK && statusCode != http.StatusBadRequest {
718+
return "", fmt.Errorf("while resetting certificate in case of previous enrollment: %s, body: '%s'", status, body)
719+
}
720+
689721
tppCertificateRequest, err := prepareRequest(req, c.zone)
690722
if err != nil {
691723
return "", err
692724
}
693-
statusCode, status, body, err := c.request("POST", urlResourceCertificateRequest, tppCertificateRequest)
725+
statusCode, status, body, err = c.request("POST", urlResourceCertificateRequest, tppCertificateRequest)
694726
if err != nil {
695727
return "", err
696728
}

0 commit comments

Comments
 (0)