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 (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
@ -162,6 +164,18 @@ func (h *Handler) GetCertificate(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
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.Header().Set("Content-Type", "application/pem-certificate-chain; charset=utf-8")
|
||||||
w.Write(certBytes)
|
w.Write(certBytes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -526,6 +526,43 @@ func TestHandlerGetCertificate(t *testing.T) {
|
||||||
problem: acme.ServerInternalErr(errors.New("force")),
|
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 {
|
"ok": func(t *testing.T) test {
|
||||||
acc := &acme.Account{ID: "accID"}
|
acc := &acme.Account{ID: "accID"}
|
||||||
ctx := context.WithValue(context.Background(), acme.AccContextKey, acc)
|
ctx := context.WithValue(context.Background(), acme.AccContextKey, acc)
|
||||||
|
@ -565,7 +602,7 @@ func TestHandlerGetCertificate(t *testing.T) {
|
||||||
prob := tc.problem.ToACME()
|
prob := tc.problem.ToACME()
|
||||||
|
|
||||||
assert.Equals(t, ae.Type, prob.Type)
|
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.Identifier, prob.Identifier)
|
||||||
assert.Equals(t, ae.Subproblems, prob.Subproblems)
|
assert.Equals(t, ae.Subproblems, prob.Subproblems)
|
||||||
assert.Equals(t, res.Header["Content-Type"], []string{"application/problem+json"})
|
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 {
|
if rl, ok := w.(logging.ResponseLogger); ok {
|
||||||
m := map[string]interface{}{
|
m := map[string]interface{}{
|
||||||
"serial": cert.SerialNumber,
|
"serial": cert.SerialNumber,
|
||||||
|
@ -413,7 +414,11 @@ func logCertificate(w http.ResponseWriter, cert *x509.Certificate) {
|
||||||
if err != nil || len(rest) > 0 {
|
if err != nil || len(rest) > 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if len(val.CredentialID) > 0 {
|
||||||
m["provisioner"] = fmt.Sprintf("%s (%s)", val.Name, val.CredentialID)
|
m["provisioner"] = fmt.Sprintf("%s (%s)", val.Name, val.CredentialID)
|
||||||
|
} else {
|
||||||
|
m["provisioner"] = fmt.Sprintf("%s", val.Name)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ func (h *caHandler) Rekey(w http.ResponseWriter, r *http.Request) {
|
||||||
caPEM = certChainPEM[1]
|
caPEM = certChainPEM[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
logCertificate(w, certChain[0])
|
LogCertificate(w, certChain[0])
|
||||||
JSONStatus(w, &SignResponse{
|
JSONStatus(w, &SignResponse{
|
||||||
ServerPEM: certChainPEM[0],
|
ServerPEM: certChainPEM[0],
|
||||||
CaPEM: caPEM,
|
CaPEM: caPEM,
|
||||||
|
|
|
@ -25,7 +25,7 @@ func (h *caHandler) Renew(w http.ResponseWriter, r *http.Request) {
|
||||||
caPEM = certChainPEM[1]
|
caPEM = certChainPEM[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
logCertificate(w, certChain[0])
|
LogCertificate(w, certChain[0])
|
||||||
JSONStatus(w, &SignResponse{
|
JSONStatus(w, &SignResponse{
|
||||||
ServerPEM: certChainPEM[0],
|
ServerPEM: certChainPEM[0],
|
||||||
CaPEM: caPEM,
|
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.
|
// TODO: should probably be checking if the certificate was revoked here.
|
||||||
// Will need to thread that request down to the authority, so will need
|
// Will need to thread that request down to the authority, so will need
|
||||||
// to add API for that.
|
// to add API for that.
|
||||||
logCertificate(w, opts.Crt)
|
LogCertificate(w, opts.Crt)
|
||||||
opts.MTLS = true
|
opts.MTLS = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) {
|
||||||
if len(certChainPEM) > 1 {
|
if len(certChainPEM) > 1 {
|
||||||
caPEM = certChainPEM[1]
|
caPEM = certChainPEM[1]
|
||||||
}
|
}
|
||||||
logCertificate(w, certChain[0])
|
LogCertificate(w, certChain[0])
|
||||||
JSONStatus(w, &SignResponse{
|
JSONStatus(w, &SignResponse{
|
||||||
ServerPEM: certChainPEM[0],
|
ServerPEM: certChainPEM[0],
|
||||||
CaPEM: caPEM,
|
CaPEM: caPEM,
|
||||||
|
|
Loading…
Reference in a new issue