Add ssl certificate checksum to template
This commit is contained in:
parent
8a652e94f5
commit
c4228a150f
5 changed files with 61 additions and 30 deletions
|
@ -733,11 +733,12 @@ func (lbc *loadBalancerController) createServers(data []interface{}) map[string]
|
|||
servers[host] = &nginx.Server{Name: host, Locations: locs}
|
||||
}
|
||||
|
||||
if pemFile, ok := pems[host]; ok {
|
||||
if ngxCert, ok := pems[host]; ok {
|
||||
server := servers[host]
|
||||
server.SSL = true
|
||||
server.SSLCertificate = pemFile
|
||||
server.SSLCertificateKey = pemFile
|
||||
server.SSLCertificate = ngxCert.PemFileName
|
||||
server.SSLCertificateKey = ngxCert.PemFileName
|
||||
server.SSLPemChecksum = ngxCert.PemSHA
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -745,8 +746,8 @@ func (lbc *loadBalancerController) createServers(data []interface{}) map[string]
|
|||
return servers
|
||||
}
|
||||
|
||||
func (lbc *loadBalancerController) getPemsFromIngress(data []interface{}) map[string]string {
|
||||
pems := make(map[string]string)
|
||||
func (lbc *loadBalancerController) getPemsFromIngress(data []interface{}) map[string]nginx.SSLCert {
|
||||
pems := make(map[string]nginx.SSLCert)
|
||||
|
||||
for _, ingIf := range data {
|
||||
ing := ingIf.(*extensions.Ingress)
|
||||
|
@ -769,12 +770,7 @@ func (lbc *loadBalancerController) getPemsFromIngress(data []interface{}) map[st
|
|||
continue
|
||||
}
|
||||
|
||||
pemFileName, err := lbc.nginx.AddOrUpdateCertAndKey(fmt.Sprintf("%v-%v", ing.Namespace, secretName), string(cert), string(key))
|
||||
if err != nil {
|
||||
glog.Errorf("No valid SSL certificate found in secret %v: %v", secretName, err)
|
||||
continue
|
||||
}
|
||||
cn, err := lbc.nginx.CheckSSLCertificate(pemFileName)
|
||||
ngxCert, err := lbc.nginx.AddOrUpdateCertAndKey(fmt.Sprintf("%v-%v", ing.Namespace, secretName), string(cert), string(key))
|
||||
if err != nil {
|
||||
glog.Errorf("No valid SSL certificate found in secret %v: %v", secretName, err)
|
||||
continue
|
||||
|
@ -786,14 +782,14 @@ func (lbc *loadBalancerController) getPemsFromIngress(data []interface{}) map[st
|
|||
continue
|
||||
}
|
||||
|
||||
pems["_"] = pemFileName
|
||||
pems["_"] = ngxCert
|
||||
glog.Infof("Using the secret %v as source for the default SSL certificate", secretName)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, host := range tls.Hosts {
|
||||
if isHostValid(host, cn) {
|
||||
pems[host] = pemFileName
|
||||
if isHostValid(host, ngxCert.CN) {
|
||||
pems[host] = ngxCert
|
||||
} else {
|
||||
glog.Warningf("SSL Certificate stored in secret %v is not valid for the host %v defined in the Ingress rule %v", secretName, host, ing.Name)
|
||||
}
|
||||
|
|
|
@ -155,6 +155,8 @@ http {
|
|||
server {
|
||||
listen 80{{ if $cfg.useProxyProtocol }} proxy_protocol{{ end }};
|
||||
{{ if $server.SSL }}listen 443{{ if $cfg.useProxyProtocol }} proxy_protocol{{ end }} ssl http2;
|
||||
{{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}}
|
||||
# PEM sha: {{ $server.SSLPemChecksum }}
|
||||
ssl_certificate {{ $server.SSLCertificate }};
|
||||
ssl_certificate_key {{ $server.SSLCertificateKey }};{{ end }}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ type Server struct {
|
|||
SSL bool
|
||||
SSLCertificate string
|
||||
SSLCertificateKey string
|
||||
SSLPemChecksum string
|
||||
}
|
||||
|
||||
// ServerByName sorts server by name
|
||||
|
|
|
@ -17,7 +17,9 @@ limitations under the License.
|
|||
package nginx
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"encoding/hex"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
@ -26,28 +28,52 @@ import (
|
|||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
// SSLCert describes a SSL certificate to be used in NGINX
|
||||
type SSLCert struct {
|
||||
CertFileName string
|
||||
KeyFileName string
|
||||
// PemFileName contains the path to the file with the certificate and key concatenated
|
||||
PemFileName string
|
||||
// PemSHA contains the sha1 of the pem file.
|
||||
// This is used to detect changes in the secret that contains the certificates
|
||||
PemSHA string
|
||||
// CN contains all the common names defined in the SSL certificate
|
||||
CN []string
|
||||
}
|
||||
|
||||
// AddOrUpdateCertAndKey creates a .pem file wth the cert and the key with the specified name
|
||||
func (nginx *Manager) AddOrUpdateCertAndKey(name string, cert string, key string) (string, error) {
|
||||
func (nginx *Manager) AddOrUpdateCertAndKey(name string, cert string, key string) (SSLCert, error) {
|
||||
pemFileName := sslDirectory + "/" + name + ".pem"
|
||||
|
||||
pem, err := os.Create(pemFileName)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Couldn't create pem file %v: %v", pemFileName, err)
|
||||
return SSLCert{}, fmt.Errorf("Couldn't create pem file %v: %v", pemFileName, err)
|
||||
}
|
||||
defer pem.Close()
|
||||
|
||||
_, err = pem.WriteString(fmt.Sprintf("%v\n%v", cert, key))
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Couldn't write to pem file %v: %v", pemFileName, err)
|
||||
return SSLCert{}, fmt.Errorf("Couldn't write to pem file %v: %v", pemFileName, err)
|
||||
}
|
||||
|
||||
return pemFileName, nil
|
||||
cn, err := nginx.commonNames(pemFileName)
|
||||
if err != nil {
|
||||
return SSLCert{}, err
|
||||
}
|
||||
|
||||
// CheckSSLCertificate checks if the certificate and key file are valid
|
||||
return SSLCert{
|
||||
CertFileName: cert,
|
||||
KeyFileName: key,
|
||||
PemFileName: pemFileName,
|
||||
PemSHA: nginx.pemSHA1(pemFileName),
|
||||
CN: cn,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// commonNames checks 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 (nginx *Manager) CheckSSLCertificate(pemFileName string) ([]string, error) {
|
||||
func (nginx *Manager) commonNames(pemFileName string) ([]string, error) {
|
||||
pemCerts, err := ioutil.ReadFile(pemFileName)
|
||||
if err != nil {
|
||||
return []string{}, err
|
||||
|
@ -92,3 +118,14 @@ func (nginx *Manager) SearchDHParamFile(baseDir string) string {
|
|||
glog.Warning("no file dhparam.pem found in secrets")
|
||||
return ""
|
||||
}
|
||||
|
||||
func (nginx *Manager) pemSHA1(filename string) string {
|
||||
hasher := sha1.New()
|
||||
s, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
hasher.Write(s)
|
||||
return hex.EncodeToString(hasher.Sum(nil))
|
||||
}
|
||||
|
|
|
@ -44,25 +44,20 @@ func TestAddOrUpdateCertAndKey(t *testing.T) {
|
|||
ngx := &Manager{}
|
||||
|
||||
name := fmt.Sprintf("test-%v", time.Now().UnixNano())
|
||||
pemPath, err := ngx.AddOrUpdateCertAndKey(name, string(dCrt), string(dKey))
|
||||
ngxCert, err := ngx.AddOrUpdateCertAndKey(name, string(dCrt), string(dKey))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error checking SSL certificate: %v", err)
|
||||
}
|
||||
|
||||
if pemPath == "" {
|
||||
if ngxCert.PemFileName == "" {
|
||||
t.Fatalf("expected path to pem file but returned empty")
|
||||
}
|
||||
|
||||
cnames, err := ngx.CheckSSLCertificate(pemPath)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error checking SSL certificate: %v", err)
|
||||
}
|
||||
|
||||
if len(cnames) == 0 {
|
||||
if len(ngxCert.CN) == 0 {
|
||||
t.Fatalf("expected at least one cname but none returned")
|
||||
}
|
||||
|
||||
if cnames[0] != "echoheaders" {
|
||||
t.Fatalf("expected cname echoheaders but %v returned", cnames[0])
|
||||
if ngxCert.CN[0] != "echoheaders" {
|
||||
t.Fatalf("expected cname echoheaders but %v returned", ngxCert.CN[0])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue