From 0475a4d26ffdb243bb66eeaf81f7ed317658294f Mon Sep 17 00:00:00 2001 From: Herman Slatman Date: Wed, 12 Jan 2022 10:41:36 +0100 Subject: [PATCH] Refactor extraction of JSON template syntax errors --- authority/ssh.go | 5 ++--- authority/tls.go | 22 ++++++++++++++++++---- authority/tls_test.go | 2 +- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/authority/ssh.go b/authority/ssh.go index e582eddd..4a67b28c 100644 --- a/authority/ssh.go +++ b/authority/ssh.go @@ -200,10 +200,9 @@ func (a *Authority) SignSSH(ctx context.Context, key ssh.PublicKey, opts provisi } // explicitly check for unmarshaling errors, which are most probably caused by JSON template syntax errors if strings.HasPrefix(err.Error(), "error unmarshaling certificate") { - msg := strings.TrimSpace(strings.TrimPrefix(err.Error(), "error unmarshaling certificate:")) - return nil, errs.ApplyOptions( - errs.InternalServer("authority.Sign: failed to apply certificate template: %s", msg), + return nil, errs.InternalServerErr(templatingError(err), errs.WithKeyVal("signOptions", signOpts), + errs.WithMessage("error applying certificate template"), ) } return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.SignSSH") diff --git a/authority/tls.go b/authority/tls.go index 6affd15d..d4838342 100644 --- a/authority/tls.go +++ b/authority/tls.go @@ -7,7 +7,9 @@ import ( "crypto/x509" "encoding/asn1" "encoding/base64" + "encoding/json" "encoding/pem" + "fmt" "net/http" "strings" "time" @@ -127,13 +129,12 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Sign errs.WithKeyVal("signOptions", signOpts), ) } - // explicitly check for unmarshaling errors, which are most probably caused by JSON template syntax errors + // explicitly check for unmarshaling errors, which are most probably caused by JSON template (syntax) errors if strings.HasPrefix(err.Error(), "error unmarshaling certificate") { - msg := strings.TrimSpace(strings.TrimPrefix(err.Error(), "error unmarshaling certificate:")) - return nil, errs.ApplyOptions( - errs.InternalServer("authority.Sign: failed to apply certificate template: %s", msg), + return nil, errs.InternalServerErr(templatingError(err), errs.WithKeyVal("csr", csr), errs.WithKeyVal("signOptions", signOpts), + errs.WithMessage("error applying certificate template"), ) } return nil, errs.Wrap(http.StatusInternalServerError, err, "authority.Sign", opts...) @@ -559,3 +560,16 @@ func (a *Authority) GetTLSCertificate() (*tls.Certificate, error) { tlsCrt.Leaf = resp.Certificate return &tlsCrt, nil } + +// templatingError tries to extract more information about the cause of +// an error related to (most probably) malformed template data and adds +// this to the error message. +func templatingError(err error) error { + cause := errors.Cause(err) + var syntaxError *json.SyntaxError + if errors.As(err, &syntaxError) { + // offset is arguably not super clear to the user, but it's the best we can do here + cause = fmt.Errorf("%s at offset %d", cause.Error(), syntaxError.Offset) + } + return errors.Wrap(cause, "error applying certificate template") +} diff --git a/authority/tls_test.go b/authority/tls_test.go index 1fd3d6cb..bc0f0526 100644 --- a/authority/tls_test.go +++ b/authority/tls_test.go @@ -421,7 +421,7 @@ ZYtQ9Ot36qc= csr: csr, extraOpts: testExtraOpts, signOpts: signOpts, - err: errors.New("authority.Sign: failed to apply certificate template"), + err: errors.New("error applying certificate template"), code: http.StatusInternalServerError, } },