Remove custom ssl code and add TLS support in Ingress rules

This commit is contained in:
Manuel de Brito Fontes 2016-03-16 11:12:45 -03:00
parent 5feb452ce4
commit 6cb0e41737
11 changed files with 190 additions and 226 deletions

View file

@ -17,139 +17,13 @@ limitations under the License.
package ssl
import (
"crypto/tls"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/golang/glog"
)
// Certificate contains the cert, key and the list of valid hostnames
type Certificate struct {
Cert string
Key string
Cname []string
Valid bool
Default bool
}
// CreateSSLCerts reads the content of the /etc/nginx-ssl directory and
// verifies the cert and key extracting the common names for this pair
func CreateSSLCerts(baseDir string) []Certificate {
sslCerts := []Certificate{}
glog.Infof("inspecting directory %v for SSL certificates\n", baseDir)
files, _ := ioutil.ReadDir(baseDir)
for _, file := range files {
if !file.IsDir() {
continue
}
// the name of the secret could be different than the certificate file
cert, key, err := getCert(fmt.Sprintf("%v/%v", baseDir, file.Name()))
if err != nil {
glog.Errorf("error checking certificate: %v", err)
continue
}
hosts, err := checkSSLCertificate(cert, key)
if err == nil {
sslCert := Certificate{
Cert: cert,
Key: key,
Cname: hosts,
Valid: true,
}
if file.Name() == "default" {
sslCert.Default = true
}
sslCerts = append(sslCerts, sslCert)
} else {
glog.Errorf("error checking certificate: %v", err)
}
}
if len(sslCerts) == 1 {
sslCerts[0].Default = true
}
glog.Infof("ssl certificates found: %v", sslCerts)
return sslCerts
}
// checkSSLCertificate check if the certificate and key file are valid
// returning the result of the validation and the list of hostnames
// contained in the common name/s
func checkSSLCertificate(certFile, keyFile string) ([]string, error) {
_, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
glog.Errorf("Error checking certificate and key file %v/%v: %v", certFile, keyFile, err)
return []string{}, err
}
pemCerts, err := ioutil.ReadFile(certFile)
if err != nil {
return []string{}, err
}
var block *pem.Block
block, pemCerts = pem.Decode(pemCerts)
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
glog.Errorf("Error checking certificate and key file %v/%v: %v", certFile, keyFile, err)
return []string{}, err
}
cn := []string{cert.Subject.CommonName}
if len(cert.DNSNames) > 0 {
cn = append(cn, cert.DNSNames...)
}
glog.Infof("DNS %v %v\n", cn, len(cn))
return cn, nil
}
func verifyHostname(certFile, host string) bool {
pemCerts, err := ioutil.ReadFile(certFile)
if err != nil {
return false
}
var block *pem.Block
block, pemCerts = pem.Decode(pemCerts)
cert, err := x509.ParseCertificate(block.Bytes)
err = cert.VerifyHostname(host)
if err == nil {
return true
}
return false
}
// GetSSLHost checks if in one of the secrets that contains SSL
// certificates could be used for the specified server name
func GetSSLHost(serverName string, certs []Certificate) Certificate {
for _, sslCert := range certs {
if verifyHostname(sslCert.Cert, serverName) {
return sslCert
}
}
return Certificate{}
}
// SearchDHParamFile iterates all the secrets mounted inside the /etc/nginx-ssl directory
// in order to find a file with the name dhparam.pem. If such file exists it will
// returns the path. If not it just returns an empty string
@ -170,32 +44,3 @@ func SearchDHParamFile(baseDir string) string {
glog.Warning("no file dhparam.pem found in secrets")
return ""
}
// getCert returns the pair cert-key if exists or an error
func getCert(certDir string) (cert string, key string, err error) {
// we search for a file with extension crt
filepath.Walk(certDir, func(path string, f os.FileInfo, _ error) error {
if !f.IsDir() {
r, err := regexp.MatchString(".crt", f.Name())
if err == nil && r {
cert = f.Name()
return nil
}
}
return nil
})
cert = fmt.Sprintf("%v/%v", certDir, cert)
if _, err := os.Stat(cert); os.IsNotExist(err) {
return "", "", fmt.Errorf("No certificate found in directory %v: %v", certDir, err)
}
key = strings.Replace(cert, ".crt", ".key", 1)
if _, err := os.Stat(key); os.IsNotExist(err) {
return "", "", fmt.Errorf("No certificate key found in directory %v: %v", certDir, err)
}
return
}