forked from TrueCloudLab/certificates
Merge pull request #345 from smallstep/max/acmeLogCert
Add cert logging for acme/certificate api
This commit is contained in:
commit
393f3efe69
7 changed files with 63 additions and 7 deletions
|
@ -2,6 +2,8 @@ package api
|
|||
|
||||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
|
@ -162,6 +164,18 @@ func (h *Handler) GetCertificate(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
block, _ := pem.Decode(certBytes)
|
||||
if block == nil {
|
||||
api.WriteError(w, acme.ServerInternalErr(errors.New("failed to decode any certificates from generated certBytes")))
|
||||
return
|
||||
}
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
api.WriteError(w, acme.Wrap(err, "failed to parse generated leaf certificate"))
|
||||
return
|
||||
}
|
||||
|
||||
api.LogCertificate(w, cert)
|
||||
w.Header().Set("Content-Type", "application/pem-certificate-chain; charset=utf-8")
|
||||
w.Write(certBytes)
|
||||
}
|
||||
|
|
|
@ -526,6 +526,43 @@ func TestHandlerGetCertificate(t *testing.T) {
|
|||
problem: acme.ServerInternalErr(errors.New("force")),
|
||||
}
|
||||
},
|
||||
"fail/decode-leaf-for-loggger": func(t *testing.T) test {
|
||||
acc := &acme.Account{ID: "accID"}
|
||||
ctx := context.WithValue(context.Background(), acme.AccContextKey, acc)
|
||||
ctx = context.WithValue(ctx, chi.RouteCtxKey, chiCtx)
|
||||
return test{
|
||||
auth: &mockAcmeAuthority{
|
||||
getCertificate: func(accID, id string) ([]byte, error) {
|
||||
assert.Equals(t, accID, acc.ID)
|
||||
assert.Equals(t, id, certID)
|
||||
return []byte("foo"), nil
|
||||
},
|
||||
},
|
||||
ctx: ctx,
|
||||
statusCode: 500,
|
||||
problem: acme.ServerInternalErr(errors.New("failed to decode any certificates from generated certBytes")),
|
||||
}
|
||||
},
|
||||
"fail/parse-x509-leaf-for-logger": func(t *testing.T) test {
|
||||
acc := &acme.Account{ID: "accID"}
|
||||
ctx := context.WithValue(context.Background(), acme.AccContextKey, acc)
|
||||
ctx = context.WithValue(ctx, chi.RouteCtxKey, chiCtx)
|
||||
return test{
|
||||
auth: &mockAcmeAuthority{
|
||||
getCertificate: func(accID, id string) ([]byte, error) {
|
||||
assert.Equals(t, accID, acc.ID)
|
||||
assert.Equals(t, id, certID)
|
||||
return pem.EncodeToMemory(&pem.Block{
|
||||
Type: "CERTIFICATE REQUEST",
|
||||
Bytes: []byte("foo"),
|
||||
}), nil
|
||||
},
|
||||
},
|
||||
ctx: ctx,
|
||||
statusCode: 500,
|
||||
problem: acme.ServerInternalErr(errors.New("failed to parse generated leaf certificate")),
|
||||
}
|
||||
},
|
||||
"ok": func(t *testing.T) test {
|
||||
acc := &acme.Account{ID: "accID"}
|
||||
ctx := context.WithValue(context.Background(), acme.AccContextKey, acc)
|
||||
|
@ -565,7 +602,7 @@ func TestHandlerGetCertificate(t *testing.T) {
|
|||
prob := tc.problem.ToACME()
|
||||
|
||||
assert.Equals(t, ae.Type, prob.Type)
|
||||
assert.Equals(t, ae.Detail, prob.Detail)
|
||||
assert.HasPrefix(t, ae.Detail, prob.Detail)
|
||||
assert.Equals(t, ae.Identifier, prob.Identifier)
|
||||
assert.Equals(t, ae.Subproblems, prob.Subproblems)
|
||||
assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"})
|
||||
|
|
|
@ -395,7 +395,8 @@ func logOtt(w http.ResponseWriter, token string) {
|
|||
}
|
||||
}
|
||||
|
||||
func logCertificate(w http.ResponseWriter, cert *x509.Certificate) {
|
||||
// LogCertificate add certificate fields to the log message.
|
||||
func LogCertificate(w http.ResponseWriter, cert *x509.Certificate) {
|
||||
if rl, ok := w.(logging.ResponseLogger); ok {
|
||||
m := map[string]interface{}{
|
||||
"serial": cert.SerialNumber,
|
||||
|
@ -413,7 +414,11 @@ func logCertificate(w http.ResponseWriter, cert *x509.Certificate) {
|
|||
if err != nil || len(rest) > 0 {
|
||||
break
|
||||
}
|
||||
m["provisioner"] = fmt.Sprintf("%s (%s)", val.Name, val.CredentialID)
|
||||
if len(val.CredentialID) > 0 {
|
||||
m["provisioner"] = fmt.Sprintf("%s (%s)", val.Name, val.CredentialID)
|
||||
} else {
|
||||
m["provisioner"] = fmt.Sprintf("%s", val.Name)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ func (h *caHandler) Rekey(w http.ResponseWriter, r *http.Request) {
|
|||
caPEM = certChainPEM[1]
|
||||
}
|
||||
|
||||
logCertificate(w, certChain[0])
|
||||
LogCertificate(w, certChain[0])
|
||||
JSONStatus(w, &SignResponse{
|
||||
ServerPEM: certChainPEM[0],
|
||||
CaPEM: caPEM,
|
||||
|
|
|
@ -25,7 +25,7 @@ func (h *caHandler) Renew(w http.ResponseWriter, r *http.Request) {
|
|||
caPEM = certChainPEM[1]
|
||||
}
|
||||
|
||||
logCertificate(w, certChain[0])
|
||||
LogCertificate(w, certChain[0])
|
||||
JSONStatus(w, &SignResponse{
|
||||
ServerPEM: certChainPEM[0],
|
||||
CaPEM: caPEM,
|
||||
|
|
|
@ -91,7 +91,7 @@ func (h *caHandler) Revoke(w http.ResponseWriter, r *http.Request) {
|
|||
// TODO: should probably be checking if the certificate was revoked here.
|
||||
// Will need to thread that request down to the authority, so will need
|
||||
// to add API for that.
|
||||
logCertificate(w, opts.Crt)
|
||||
LogCertificate(w, opts.Crt)
|
||||
opts.MTLS = true
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) {
|
|||
if len(certChainPEM) > 1 {
|
||||
caPEM = certChainPEM[1]
|
||||
}
|
||||
logCertificate(w, certChain[0])
|
||||
LogCertificate(w, certChain[0])
|
||||
JSONStatus(w, &SignResponse{
|
||||
ServerPEM: certChainPEM[0],
|
||||
CaPEM: caPEM,
|
||||
|
|
Loading…
Reference in a new issue