forked from TrueCloudLab/certificates
Add /roots.pem handler (#866)
* Add /roots.pem handler * Review changes * Remove no peer cert test case
This commit is contained in:
parent
750e9ee2f8
commit
52d7f084d2
2 changed files with 65 additions and 0 deletions
25
api/api.go
25
api/api.go
|
@ -21,6 +21,7 @@ import (
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/smallstep/certificates/api/log"
|
||||||
"github.com/smallstep/certificates/authority"
|
"github.com/smallstep/certificates/authority"
|
||||||
"github.com/smallstep/certificates/authority/config"
|
"github.com/smallstep/certificates/authority/config"
|
||||||
"github.com/smallstep/certificates/authority/provisioner"
|
"github.com/smallstep/certificates/authority/provisioner"
|
||||||
|
@ -259,6 +260,7 @@ func (h *caHandler) Route(r Router) {
|
||||||
r.MethodFunc("GET", "/provisioners", h.Provisioners)
|
r.MethodFunc("GET", "/provisioners", h.Provisioners)
|
||||||
r.MethodFunc("GET", "/provisioners/{kid}/encrypted-key", h.ProvisionerKey)
|
r.MethodFunc("GET", "/provisioners/{kid}/encrypted-key", h.ProvisionerKey)
|
||||||
r.MethodFunc("GET", "/roots", h.Roots)
|
r.MethodFunc("GET", "/roots", h.Roots)
|
||||||
|
r.MethodFunc("GET", "/roots.pem", h.RootsPEM)
|
||||||
r.MethodFunc("GET", "/federation", h.Federation)
|
r.MethodFunc("GET", "/federation", h.Federation)
|
||||||
// SSH CA
|
// SSH CA
|
||||||
r.MethodFunc("POST", "/ssh/sign", h.SSHSign)
|
r.MethodFunc("POST", "/ssh/sign", h.SSHSign)
|
||||||
|
@ -364,6 +366,29 @@ func (h *caHandler) Roots(w http.ResponseWriter, r *http.Request) {
|
||||||
}, http.StatusCreated)
|
}, http.StatusCreated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RootsPEM returns all the root certificates for the CA in PEM format.
|
||||||
|
func (h *caHandler) RootsPEM(w http.ResponseWriter, r *http.Request) {
|
||||||
|
roots, err := h.Authority.GetRoots()
|
||||||
|
if err != nil {
|
||||||
|
WriteError(w, errs.InternalServerErr(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/x-pem-file")
|
||||||
|
|
||||||
|
for _, root := range roots {
|
||||||
|
block := pem.EncodeToMemory(&pem.Block{
|
||||||
|
Type: "CERTIFICATE",
|
||||||
|
Bytes: root.Raw,
|
||||||
|
})
|
||||||
|
|
||||||
|
if _, err := w.Write(block); err != nil {
|
||||||
|
log.Error(w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Federation returns all the public certificates in the federation.
|
// Federation returns all the public certificates in the federation.
|
||||||
func (h *caHandler) Federation(w http.ResponseWriter, r *http.Request) {
|
func (h *caHandler) Federation(w http.ResponseWriter, r *http.Request) {
|
||||||
federated, err := h.Authority.GetFederation()
|
federated, err := h.Authority.GetFederation()
|
||||||
|
|
|
@ -1344,6 +1344,46 @@ func Test_caHandler_Roots(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_caHandler_RootsPEM(t *testing.T) {
|
||||||
|
parsedRoot := parseCertificate(rootPEM)
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
roots []*x509.Certificate
|
||||||
|
err error
|
||||||
|
statusCode int
|
||||||
|
expect string
|
||||||
|
}{
|
||||||
|
{"one root", []*x509.Certificate{parsedRoot}, nil, http.StatusOK, rootPEM},
|
||||||
|
{"two roots", []*x509.Certificate{parsedRoot, parsedRoot}, nil, http.StatusOK, rootPEM + "\n" + rootPEM},
|
||||||
|
{"fail", nil, errors.New("an error"), http.StatusInternalServerError, ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
h := New(&mockAuthority{ret1: tt.roots, err: tt.err}).(*caHandler)
|
||||||
|
req := httptest.NewRequest("GET", "https://example.com/roots", nil)
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
h.RootsPEM(w, req)
|
||||||
|
res := w.Result()
|
||||||
|
|
||||||
|
if res.StatusCode != tt.statusCode {
|
||||||
|
t.Errorf("caHandler.RootsPEM StatusCode = %d, wants %d", res.StatusCode, tt.statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(res.Body)
|
||||||
|
res.Body.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("caHandler.RootsPEM unexpected error = %v", err)
|
||||||
|
}
|
||||||
|
if tt.statusCode < http.StatusBadRequest {
|
||||||
|
if !bytes.Equal(bytes.TrimSpace(body), []byte(tt.expect)) {
|
||||||
|
t.Errorf("caHandler.RootsPEM Body = %s, wants %s", body, tt.expect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_caHandler_Federation(t *testing.T) {
|
func Test_caHandler_Federation(t *testing.T) {
|
||||||
cs := &tls.ConnectionState{
|
cs := &tls.ConnectionState{
|
||||||
PeerCertificates: []*x509.Certificate{parseCertificate(certPEM)},
|
PeerCertificates: []*x509.Certificate{parseCertificate(certPEM)},
|
||||||
|
|
Loading…
Reference in a new issue