Introduce /tls/validate and validateCertificates() that will also be used by /tls/configure

This commit is contained in:
Eugene Bujak 2019-02-12 20:08:11 +03:00 committed by Eugene Bujak
parent 876bec5a65
commit 5cbaeb82a8

View File

@ -1050,6 +1050,20 @@ func handleTLSStatus(w http.ResponseWriter, r *http.Request) {
} }
} }
func handleTLSValidate(w http.ResponseWriter, r *http.Request) {
data, err := unmarshalTLS(r)
if err != nil {
httpError(w, http.StatusBadRequest, "Failed to unmarshal TLS config: %s", err)
return
}
data, err = validateCertificates(data)
if err != nil {
httpError(w, http.StatusBadRequest, "New TLS configuration does not validate: %s", err)
return
}
}
func handleTLSConfigure(w http.ResponseWriter, r *http.Request) { func handleTLSConfigure(w http.ResponseWriter, r *http.Request) {
data, err := unmarshalTLS(r) data, err := unmarshalTLS(r)
if err != nil { if err != nil {
@ -1057,14 +1071,25 @@ func handleTLSConfigure(w http.ResponseWriter, r *http.Request) {
return return
} }
data, err = validateCertificates(data)
if err != nil {
httpError(w, http.StatusBadRequest, "New TLS configuration does not validate: %s", err)
return
}
config.TLS = data
httpUpdateConfigReloadDNSReturnOK(w, r)
}
func validateCertificates(data tlsConfig) (tlsConfig, error) {
var err error
if data.CertificateChain != "" { if data.CertificateChain != "" {
log.Printf("got certificate: %s", data.CertificateChain) log.Printf("got certificate: %s", data.CertificateChain)
if data.PrivateKey != "" { if data.PrivateKey != "" {
_, err = tls.X509KeyPair([]byte(data.CertificateChain), []byte(data.PrivateKey)) _, err = tls.X509KeyPair([]byte(data.CertificateChain), []byte(data.PrivateKey))
if err != nil { if err != nil {
httpError(w, http.StatusBadRequest, "Invalid certificate or key: %s", err) return data, errorx.Decorate(err, "Invalid certificate or key")
return
} }
} }
@ -1091,15 +1116,13 @@ func handleTLSConfigure(w http.ResponseWriter, r *http.Request) {
for _, cert := range certs { for _, cert := range certs {
parsed, err := x509.ParseCertificate(cert.Bytes) parsed, err := x509.ParseCertificate(cert.Bytes)
if err != nil { if err != nil {
httpError(w, http.StatusBadRequest, "failed to parse certificate: %s", err) return data, errorx.Decorate(err, "Failed to parse certificate")
return
} }
parsedCerts = append(parsedCerts, parsed) parsedCerts = append(parsedCerts, parsed)
} }
if len(parsedCerts) == 0 { if len(parsedCerts) == 0 {
httpError(w, http.StatusBadRequest, "You have specified an empty certificate") return data, fmt.Errorf("You have specified an empty certificate")
return
} }
// spew.Dump(parsedCerts) // spew.Dump(parsedCerts)
@ -1121,11 +1144,10 @@ func handleTLSConfigure(w http.ResponseWriter, r *http.Request) {
// TODO: save it as a warning rather than error it out -- shouldn't be a big problem // TODO: save it as a warning rather than error it out -- shouldn't be a big problem
mainCert := parsedCerts[0] mainCert := parsedCerts[0]
_, err = mainCert.Verify(opts) _, err := mainCert.Verify(opts)
if err != nil { if err != nil {
// TODO: let self-signed certs through // TODO: let self-signed certs through
httpError(w, http.StatusBadRequest, "Your certificate does not verify: %s", err) return data, errorx.Decorate(err, "Your certificate does not verify")
return
} }
// spew.Dump(chains) // spew.Dump(chains)
@ -1151,8 +1173,7 @@ func handleTLSConfigure(w http.ResponseWriter, r *http.Request) {
} }
} }
config.TLS = data return data, nil
httpUpdateConfigReloadDNSReturnOK(w, r)
} }
// unmarshalTLS handles base64-encoded certificates transparently // unmarshalTLS handles base64-encoded certificates transparently
@ -1232,4 +1253,5 @@ func registerControlHandlers() {
http.HandleFunc("/control/tls/status", postInstall(optionalAuth(ensureGET(handleTLSStatus)))) http.HandleFunc("/control/tls/status", postInstall(optionalAuth(ensureGET(handleTLSStatus))))
http.HandleFunc("/control/tls/configure", postInstall(optionalAuth(ensurePOST(handleTLSConfigure)))) http.HandleFunc("/control/tls/configure", postInstall(optionalAuth(ensurePOST(handleTLSConfigure))))
http.HandleFunc("/control/tls/validate", postInstall(optionalAuth(ensurePOST(handleTLSValidate))))
} }