forked from TrueCloudLab/certificates
parent
37d7231ee0
commit
b974957868
2 changed files with 62 additions and 2 deletions
59
api/api.go
59
api/api.go
|
@ -1,10 +1,15 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/rsa"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
|
"encoding/asn1"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -13,6 +18,7 @@ import (
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/smallstep/certificates/authority"
|
"github.com/smallstep/certificates/authority"
|
||||||
|
"github.com/smallstep/certificates/logging"
|
||||||
"github.com/smallstep/cli/crypto/tlsutil"
|
"github.com/smallstep/cli/crypto/tlsutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -275,6 +281,7 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
logCertificate(w, cert, body.OTT)
|
||||||
JSON(w, &SignResponse{
|
JSON(w, &SignResponse{
|
||||||
ServerPEM: Certificate{cert},
|
ServerPEM: Certificate{cert},
|
||||||
CaPEM: Certificate{root},
|
CaPEM: Certificate{root},
|
||||||
|
@ -297,6 +304,7 @@ func (h *caHandler) Renew(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusCreated)
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
logCertificate(w, cert, "")
|
||||||
JSON(w, &SignResponse{
|
JSON(w, &SignResponse{
|
||||||
ServerPEM: Certificate{cert},
|
ServerPEM: Certificate{cert},
|
||||||
CaPEM: Certificate{root},
|
CaPEM: Certificate{root},
|
||||||
|
@ -372,6 +380,43 @@ func (h *caHandler) Federation(w http.ResponseWriter, r *http.Request) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var oidStepProvisioner = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64, 1}
|
||||||
|
|
||||||
|
type stepProvisioner struct {
|
||||||
|
Type int
|
||||||
|
Name []byte
|
||||||
|
CredentialID []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func logCertificate(w http.ResponseWriter, cert *x509.Certificate, token string) {
|
||||||
|
if rl, ok := w.(logging.ResponseLogger); ok {
|
||||||
|
m := map[string]interface{}{
|
||||||
|
"serial": cert.SerialNumber,
|
||||||
|
"subject": cert.Subject.CommonName,
|
||||||
|
"issuer": cert.Issuer.CommonName,
|
||||||
|
"valid-from": cert.NotBefore.Format(time.RFC3339),
|
||||||
|
"valid-to": cert.NotAfter.Format(time.RFC3339),
|
||||||
|
"public-key": fmtPublicKey(cert),
|
||||||
|
"certificate": base64.StdEncoding.EncodeToString(cert.Raw),
|
||||||
|
}
|
||||||
|
if len(token) > 0 {
|
||||||
|
m["ott"] = token
|
||||||
|
}
|
||||||
|
for _, ext := range cert.Extensions {
|
||||||
|
if ext.Id.Equal(oidStepProvisioner) {
|
||||||
|
val := &stepProvisioner{}
|
||||||
|
rest, err := asn1.Unmarshal(ext.Value, val)
|
||||||
|
if err != nil || len(rest) > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
m["provisioner"] = fmt.Sprintf("%s (%s)", val.Name, val.CredentialID)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rl.WithFields(m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func parseCursor(r *http.Request) (cursor string, limit int, err error) {
|
func parseCursor(r *http.Request) (cursor string, limit int, err error) {
|
||||||
q := r.URL.Query()
|
q := r.URL.Query()
|
||||||
cursor = q.Get("cursor")
|
cursor = q.Get("cursor")
|
||||||
|
@ -383,3 +428,17 @@ func parseCursor(r *http.Request) (cursor string, limit int, err error) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add support for Ed25519 once it's supported
|
||||||
|
func fmtPublicKey(cert *x509.Certificate) string {
|
||||||
|
var params string
|
||||||
|
switch pk := cert.PublicKey.(type) {
|
||||||
|
case *ecdsa.PublicKey:
|
||||||
|
params = pk.Curve.Params().Name
|
||||||
|
case *rsa.PublicKey:
|
||||||
|
params = strconv.Itoa(pk.Size())
|
||||||
|
default:
|
||||||
|
params = "unknown"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s %s", cert.PublicKeyAlgorithm, params)
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
|
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
"github.com/smallstep/certificates/authority"
|
"github.com/smallstep/certificates/authority"
|
||||||
|
"github.com/smallstep/certificates/logging"
|
||||||
"github.com/smallstep/cli/crypto/tlsutil"
|
"github.com/smallstep/cli/crypto/tlsutil"
|
||||||
"github.com/smallstep/cli/jose"
|
"github.com/smallstep/cli/jose"
|
||||||
)
|
)
|
||||||
|
@ -598,7 +599,7 @@ func Test_caHandler_Sign(t *testing.T) {
|
||||||
}).(*caHandler)
|
}).(*caHandler)
|
||||||
req := httptest.NewRequest("POST", "http://example.com/sign", strings.NewReader(tt.input))
|
req := httptest.NewRequest("POST", "http://example.com/sign", strings.NewReader(tt.input))
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
h.Sign(w, req)
|
h.Sign(logging.NewResponseLogger(w), req)
|
||||||
res := w.Result()
|
res := w.Result()
|
||||||
|
|
||||||
if res.StatusCode != tt.statusCode {
|
if res.StatusCode != tt.statusCode {
|
||||||
|
@ -650,7 +651,7 @@ func Test_caHandler_Renew(t *testing.T) {
|
||||||
req := httptest.NewRequest("POST", "http://example.com/renew", nil)
|
req := httptest.NewRequest("POST", "http://example.com/renew", nil)
|
||||||
req.TLS = tt.tls
|
req.TLS = tt.tls
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
h.Renew(w, req)
|
h.Renew(logging.NewResponseLogger(w), req)
|
||||||
res := w.Result()
|
res := w.Result()
|
||||||
|
|
||||||
if res.StatusCode != tt.statusCode {
|
if res.StatusCode != tt.statusCode {
|
||||||
|
|
Loading…
Reference in a new issue