api: refactored to support api/render

This commit is contained in:
Panagiotis Siatras 2022-03-18 17:19:12 +02:00
parent 833ea1e695
commit 9aa480a09a
No known key found for this signature in database
GPG key ID: 529695F03A572804
11 changed files with 30 additions and 131 deletions

View file

@ -21,6 +21,7 @@ import (
"github.com/go-chi/chi"
"github.com/pkg/errors"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/config"
"github.com/smallstep/certificates/authority/provisioner"
@ -282,7 +283,7 @@ func (h *caHandler) Route(r Router) {
// Version is an HTTP handler that returns the version of the server.
func (h *caHandler) Version(w http.ResponseWriter, r *http.Request) {
v := h.Authority.Version()
JSON(w, VersionResponse{
render.JSON(w, VersionResponse{
Version: v.Version,
RequireClientAuthentication: v.RequireClientAuthentication,
})
@ -290,7 +291,7 @@ func (h *caHandler) Version(w http.ResponseWriter, r *http.Request) {
// Health is an HTTP handler that returns the status of the server.
func (h *caHandler) Health(w http.ResponseWriter, r *http.Request) {
JSON(w, HealthResponse{Status: "ok"})
render.JSON(w, HealthResponse{Status: "ok"})
}
// Root is an HTTP handler that using the SHA256 from the URL, returns the root
@ -305,7 +306,7 @@ func (h *caHandler) Root(w http.ResponseWriter, r *http.Request) {
return
}
JSON(w, &RootResponse{RootPEM: Certificate{cert}})
render.JSON(w, &RootResponse{RootPEM: Certificate{cert}})
}
func certChainToPEM(certChain []*x509.Certificate) []Certificate {
@ -329,7 +330,7 @@ func (h *caHandler) Provisioners(w http.ResponseWriter, r *http.Request) {
WriteError(w, errs.InternalServerErr(err))
return
}
JSON(w, &ProvisionersResponse{
render.JSON(w, &ProvisionersResponse{
Provisioners: p,
NextCursor: next,
})
@ -343,7 +344,7 @@ func (h *caHandler) ProvisionerKey(w http.ResponseWriter, r *http.Request) {
WriteError(w, errs.NotFoundErr(err))
return
}
JSON(w, &ProvisionerKeyResponse{key})
render.JSON(w, &ProvisionerKeyResponse{key})
}
// Roots returns all the root certificates for the CA.
@ -359,7 +360,7 @@ func (h *caHandler) Roots(w http.ResponseWriter, r *http.Request) {
certs[i] = Certificate{roots[i]}
}
JSONStatus(w, &RootsResponse{
render.JSONStatus(w, &RootsResponse{
Certificates: certs,
}, http.StatusCreated)
}
@ -377,7 +378,7 @@ func (h *caHandler) Federation(w http.ResponseWriter, r *http.Request) {
certs[i] = Certificate{federated[i]}
}
JSONStatus(w, &FederationResponse{
render.JSONStatus(w, &FederationResponse{
Certificates: certs,
}, http.StatusCreated)
}

View file

@ -4,6 +4,7 @@ import (
"net/http"
"github.com/smallstep/certificates/api/read"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/errs"
)
@ -55,7 +56,7 @@ func (h *caHandler) Rekey(w http.ResponseWriter, r *http.Request) {
}
LogCertificate(w, certChain[0])
JSONStatus(w, &SignResponse{
render.JSONStatus(w, &SignResponse{
ServerPEM: certChainPEM[0],
CaPEM: caPEM,
CertChainPEM: certChainPEM,

View file

@ -5,6 +5,7 @@ import (
"net/http"
"strings"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/errs"
)
@ -34,7 +35,7 @@ func (h *caHandler) Renew(w http.ResponseWriter, r *http.Request) {
}
LogCertificate(w, certChain[0])
JSONStatus(w, &SignResponse{
render.JSONStatus(w, &SignResponse{
ServerPEM: certChainPEM[0],
CaPEM: caPEM,
CertChainPEM: certChainPEM,

View file

@ -7,6 +7,7 @@ import (
"golang.org/x/crypto/ocsp"
"github.com/smallstep/certificates/api/read"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/errs"
@ -103,7 +104,7 @@ func (h *caHandler) Revoke(w http.ResponseWriter, r *http.Request) {
}
logRevoke(w, opts)
JSON(w, &RevokeResponse{Status: "ok"})
render.JSON(w, &RevokeResponse{Status: "ok"})
}
func logRevoke(w http.ResponseWriter, ri *authority.RevokeOptions) {

View file

@ -6,6 +6,7 @@ import (
"net/http"
"github.com/smallstep/certificates/api/read"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/authority/config"
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/errs"
@ -84,7 +85,7 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) {
caPEM = certChainPEM[1]
}
LogCertificate(w, certChain[0])
JSONStatus(w, &SignResponse{
render.JSONStatus(w, &SignResponse{
ServerPEM: certChainPEM[0],
CaPEM: caPEM,
CertChainPEM: certChainPEM,

View file

@ -12,6 +12,7 @@ import (
"golang.org/x/crypto/ssh"
"github.com/smallstep/certificates/api/read"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/config"
"github.com/smallstep/certificates/authority/provisioner"
@ -334,7 +335,7 @@ func (h *caHandler) SSHSign(w http.ResponseWriter, r *http.Request) {
identityCertificate = certChainToPEM(certChain)
}
JSONStatus(w, &SSHSignResponse{
render.JSONStatus(w, &SSHSignResponse{
Certificate: SSHCertificate{cert},
AddUserCertificate: addUserCertificate,
IdentityCertificate: identityCertificate,
@ -363,7 +364,7 @@ func (h *caHandler) SSHRoots(w http.ResponseWriter, r *http.Request) {
resp.UserKeys = append(resp.UserKeys, SSHPublicKey{PublicKey: k})
}
JSON(w, resp)
render.JSON(w, resp)
}
// SSHFederation is an HTTP handler that returns the federated SSH public keys
@ -388,7 +389,7 @@ func (h *caHandler) SSHFederation(w http.ResponseWriter, r *http.Request) {
resp.UserKeys = append(resp.UserKeys, SSHPublicKey{PublicKey: k})
}
JSON(w, resp)
render.JSON(w, resp)
}
// SSHConfig is an HTTP handler that returns rendered templates for ssh clients
@ -421,7 +422,7 @@ func (h *caHandler) SSHConfig(w http.ResponseWriter, r *http.Request) {
return
}
JSON(w, cfg)
render.JSON(w, cfg)
}
// SSHCheckHost is the HTTP handler that returns if a hosts certificate exists or not.
@ -441,7 +442,7 @@ func (h *caHandler) SSHCheckHost(w http.ResponseWriter, r *http.Request) {
WriteError(w, errs.InternalServerErr(err))
return
}
JSON(w, &SSHCheckPrincipalResponse{
render.JSON(w, &SSHCheckPrincipalResponse{
Exists: exists,
})
}
@ -458,7 +459,7 @@ func (h *caHandler) SSHGetHosts(w http.ResponseWriter, r *http.Request) {
WriteError(w, errs.InternalServerErr(err))
return
}
JSON(w, &SSHGetHostsResponse{
render.JSON(w, &SSHGetHostsResponse{
Hosts: hosts,
})
}
@ -481,7 +482,7 @@ func (h *caHandler) SSHBastion(w http.ResponseWriter, r *http.Request) {
return
}
JSON(w, &SSHBastionResponse{
render.JSON(w, &SSHBastionResponse{
Hostname: body.Hostname,
Bastion: bastion,
})

View file

@ -7,6 +7,7 @@ import (
"golang.org/x/crypto/ssh"
"github.com/smallstep/certificates/api/read"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/errs"
)
@ -84,7 +85,7 @@ func (h *caHandler) SSHRekey(w http.ResponseWriter, r *http.Request) {
return
}
JSONStatus(w, &SSHRekeyResponse{
render.JSONStatus(w, &SSHRekeyResponse{
Certificate: SSHCertificate{newCert},
IdentityCertificate: identity,
}, http.StatusCreated)

View file

@ -8,6 +8,7 @@ import (
"github.com/pkg/errors"
"github.com/smallstep/certificates/api/read"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/errs"
)
@ -76,7 +77,7 @@ func (h *caHandler) SSHRenew(w http.ResponseWriter, r *http.Request) {
return
}
JSONStatus(w, &SSHSignResponse{
render.JSONStatus(w, &SSHSignResponse{
Certificate: SSHCertificate{newCert},
IdentityCertificate: identity,
}, http.StatusCreated)

View file

@ -6,6 +6,7 @@ import (
"golang.org/x/crypto/ocsp"
"github.com/smallstep/certificates/api/read"
"github.com/smallstep/certificates/api/render"
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/errs"
@ -82,7 +83,7 @@ func (h *caHandler) SSHRevoke(w http.ResponseWriter, r *http.Request) {
}
logSSHRevoke(w, opts)
JSON(w, &SSHRevokeResponse{Status: "ok"})
render.JSON(w, &SSHRevokeResponse{Status: "ok"})
}
func logSSHRevoke(w http.ResponseWriter, ri *authority.RevokeOptions) {

View file

@ -1,57 +0,0 @@
package api
import (
"encoding/json"
"net/http"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"github.com/smallstep/certificates/api/log"
)
// JSON writes the passed value into the http.ResponseWriter.
func JSON(w http.ResponseWriter, v interface{}) {
JSONStatus(w, v, http.StatusOK)
}
// JSONStatus writes the given value into the http.ResponseWriter and the
// given status is written as the status code of the response.
func JSONStatus(w http.ResponseWriter, v interface{}, status int) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
if err := json.NewEncoder(w).Encode(v); err != nil {
log.Error(w, err)
return
}
log.EnabledResponse(w, v)
}
// ProtoJSON writes the passed value into the http.ResponseWriter.
func ProtoJSON(w http.ResponseWriter, m proto.Message) {
ProtoJSONStatus(w, m, http.StatusOK)
}
// ProtoJSONStatus writes the given value into the http.ResponseWriter and the
// given status is written as the status code of the response.
func ProtoJSONStatus(w http.ResponseWriter, m proto.Message, status int) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
b, err := protojson.Marshal(m)
if err != nil {
log.Error(w, err)
return
}
if _, err := w.Write(b); err != nil {
log.Error(w, err)
return
}
// log.EnabledResponse(w, v)
}

View file

@ -1,53 +0,0 @@
package api
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/smallstep/certificates/logging"
)
func TestJSON(t *testing.T) {
type args struct {
rw http.ResponseWriter
v interface{}
}
tests := []struct {
name string
args args
ok bool
}{
{"ok", args{httptest.NewRecorder(), map[string]interface{}{"foo": "bar"}}, true},
{"fail", args{httptest.NewRecorder(), make(chan int)}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rw := logging.NewResponseLogger(tt.args.rw)
JSON(rw, tt.args.v)
rr, ok := tt.args.rw.(*httptest.ResponseRecorder)
if !ok {
t.Error("ResponseWriter does not implement *httptest.ResponseRecorder")
return
}
fields := rw.Fields()
if tt.ok {
if body := rr.Body.String(); body != "{\"foo\":\"bar\"}\n" {
t.Errorf(`Unexpected body = %v, want {"foo":"bar"}`, body)
}
if len(fields) != 0 {
t.Errorf("ResponseLogger fields = %v, wants 0 elements", fields)
}
} else {
if body := rr.Body.String(); body != "" {
t.Errorf("Unexpected body = %s, want empty string", body)
}
if len(fields) != 1 {
t.Errorf("ResponseLogger fields = %v, wants 1 element", fields)
}
}
})
}
}