From fd48049b50a7ba5456dedb7994e4a3bef5fd4712 Mon Sep 17 00:00:00 2001 From: Matt Keeler Date: Tue, 29 Sep 2020 14:17:24 -0400 Subject: [PATCH] Add capability for the v1/connect/ca/roots endpoint to return a PEM encoded certificate chain --- agent/connect_ca_endpoint.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/agent/connect_ca_endpoint.go b/agent/connect_ca_endpoint.go index 0b58ef72b4fb..1a0266f36cd4 100644 --- a/agent/connect_ca_endpoint.go +++ b/agent/connect_ca_endpoint.go @@ -3,6 +3,7 @@ package agent import ( "fmt" "net/http" + "strconv" "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/consul/agent/structs" @@ -15,13 +16,35 @@ func (s *HTTPHandlers) ConnectCARoots(resp http.ResponseWriter, req *http.Reques return nil, nil } + pemResponse := false + if pemParam := req.URL.Query().Get("pem"); pemParam != "" { + val, err := strconv.ParseBool(pemParam) + if err != nil { + return nil, BadRequestError{Reason: "The 'pem' query paramter must be a boolean value"} + } + pemResponse = val + } + var reply structs.IndexedCARoots defer setMeta(resp, &reply.QueryMeta) if err := s.agent.RPC("ConnectCA.Roots", &args, &reply); err != nil { return nil, err } - return reply, nil + if !pemResponse { + return reply, nil + } + + // defined in RFC 8555 and registered with the IANA + resp.Header().Set("Content-Type", "application/pem-certificate-chain") + for _, root := range reply.Roots { + resp.Write([]byte(root.RootCert)) + for _, intermediate := range root.IntermediateCerts { + resp.Write([]byte(intermediate)) + } + } + + return nil, nil } // /v1/connect/ca/configuration