Added NativeHA TLS keystore

This commit is contained in:
Luke Powlett
2021-01-06 16:02:00 +00:00
committed by Luke J Powlett
parent e1c96655b1
commit 1d41f4b138
4 changed files with 113 additions and 47 deletions

View File

@@ -144,19 +144,19 @@ func doMain() error {
// Print out versioning information // Print out versioning information
logVersionInfo() logVersionInfo()
keyLabel, cmsKeystore, p12Truststore, err := tls.ConfigureTLSKeystores() keyLabel, defaultCmsKeystore, defaultP12Truststore, err := tls.ConfigureDefaultTLSKeystores()
if err != nil { if err != nil {
logTermination(err) logTermination(err)
return err return err
} }
err = tls.ConfigureTLS(keyLabel, cmsKeystore, *devFlag, log) err = tls.ConfigureTLS(keyLabel, defaultCmsKeystore, *devFlag, log)
if err != nil { if err != nil {
logTermination(err) logTermination(err)
return err return err
} }
err = postInit(name, keyLabel, p12Truststore) err = postInit(name, keyLabel, defaultP12Truststore)
if err != nil { if err != nil {
logTermination(err) logTermination(err)
return err return err

View File

@@ -21,6 +21,7 @@ import (
"os" "os"
"github.com/ibm-messaging/mq-container/internal/mqtemplate" "github.com/ibm-messaging/mq-container/internal/mqtemplate"
"github.com/ibm-messaging/mq-container/internal/tls"
"github.com/ibm-messaging/mq-container/pkg/logger" "github.com/ibm-messaging/mq-container/pkg/logger"
) )
@@ -40,11 +41,20 @@ func ConfigureNativeHA(log *logger.Logger) error {
templateMap["NativeHAInstance2_ReplicationAddress"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS") templateMap["NativeHAInstance2_ReplicationAddress"] = os.Getenv("MQ_NATIVE_HA_INSTANCE_2_REPLICATION_ADDRESS")
if os.Getenv("MQ_NATIVE_HA_TLS") == "true" { if os.Getenv("MQ_NATIVE_HA_TLS") == "true" {
templateMap["CertificateLabel"] = os.Getenv("MQ_NATIVE_HA_TLS_CERTLABEL") keyLabel, _, err := tls.ConfigureHATLSKeystore()
if err != nil {
return err
}
certLabel, ok := os.LookupEnv("MQ_NATIVE_HA_TLS_CERTLABEL")
if !ok {
certLabel = keyLabel
}
templateMap["CertificateLabel"] = certLabel
keyRepository, ok := os.LookupEnv("MQ_NATIVE_HA_KEY_REPOSITORY") keyRepository, ok := os.LookupEnv("MQ_NATIVE_HA_KEY_REPOSITORY")
if !ok { if !ok {
keyRepository = "/run/runmqserver/tls/key" keyRepository = "/run/runmqserver/ha/tls/key"
} }
templateMap["KeyRepository"] = keyRepository templateMap["KeyRepository"] = keyRepository

View File

@@ -43,14 +43,20 @@ const cmsKeystoreName = "key.kdb"
// p12TruststoreName is the name of the PKCS#12 Truststore // p12TruststoreName is the name of the PKCS#12 Truststore
const p12TruststoreName = "trust.p12" const p12TruststoreName = "trust.p12"
// keystoreDir is the location for the CMS Keystore & PKCS#12 Truststore // keystoreDir is the location for the default CMS Keystore & PKCS#12 Truststore
const keystoreDir = "/run/runmqserver/tls/" const keystoreDirDefault = "/run/runmqserver/tls/"
// keystoreDirHA is the location for the HA CMS Keystore
const keystoreDirHA = "/run/runmqserver/ha/tls/"
// keyDir is the location of the keys to import // keyDir is the location of the keys to import
const keyDir = "/etc/mqm/pki/keys" const keyDirDefault = "/etc/mqm/pki/keys"
// keyDir is the location of the HA keys to import
const keyDirHA = "/etc/mqm/ha/pki/keys"
// trustDir is the location of the trust certificates to import // trustDir is the location of the trust certificates to import
const trustDir = "/etc/mqm/pki/trust" const trustDirDefault = "/etc/mqm/pki/trust"
type KeyStoreData struct { type KeyStoreData struct {
Keystore *keystore.KeyStore Keystore *keystore.KeyStore
@@ -65,28 +71,51 @@ type P12KeyFiles struct {
Password string Password string
} }
// ConfigureTLSKeystores configures the CMS Keystore & PKCS#12 Truststore type TLSStore struct {
func ConfigureTLSKeystores() (string, KeyStoreData, KeyStoreData, error) { Keystore KeyStoreData
Truststore KeyStoreData
}
// ConfigureDefaultTLSKeystores configures the CMS Keystore & PKCS#12 Truststore
func ConfigureDefaultTLSKeystores() (string, KeyStoreData, KeyStoreData, error) {
// Create the CMS Keystore & PKCS#12 Truststore // Create the CMS Keystore & PKCS#12 Truststore
cmsKeystore, p12Truststore, err := generateAllKeystores() tlsStore, err := generateAllDefaultKeystores()
if err != nil { if err != nil {
return "", cmsKeystore, p12Truststore, err return "", tlsStore.Keystore, tlsStore.Truststore, err
} }
// Process all keys - add them to the CMS KeyStore // Process all keys - add them to the CMS KeyStore
keyLabel, err := processKeys(&cmsKeystore, &p12Truststore) keyLabel, err := processKeys(&tlsStore, keystoreDirDefault, keyDirDefault)
if err != nil { if err != nil {
return "", cmsKeystore, p12Truststore, err return "", tlsStore.Keystore, tlsStore.Truststore, err
} }
// Process all trust certificates - add them to the CMS KeyStore & PKCS#12 Truststore // Process all trust certificates - add them to the CMS KeyStore & PKCS#12 Truststore
err = processTrustCertificates(&cmsKeystore, &p12Truststore) err = processTrustCertificates(&tlsStore, trustDirDefault)
if err != nil { if err != nil {
return "", cmsKeystore, p12Truststore, err return "", tlsStore.Keystore, tlsStore.Truststore, err
} }
return keyLabel, cmsKeystore, p12Truststore, err return keyLabel, tlsStore.Keystore, tlsStore.Truststore, err
}
// ConfigureHATLSKeystore configures the CMS Keystore & PKCS#12 Truststore
func ConfigureHATLSKeystore() (string, KeyStoreData, error) {
// Create the CMS Keystore & PKCS#12 Truststore
tlsStore, err := generateHAKeystore()
if err != nil {
return "", tlsStore.Keystore, err
}
// Process all keys - add them to the CMS KeyStore
keyLabel, err := processKeys(&tlsStore, keystoreDirHA, keyDirHA)
if err != nil {
return "", tlsStore.Keystore, err
}
return keyLabel, tlsStore.Keystore, err
} }
// ConfigureTLS configures TLS for the queue manager // ConfigureTLS configures TLS for the queue manager
@@ -137,8 +166,9 @@ func configureTLSDev(log *logger.Logger) error {
return nil return nil
} }
// generateAllKeystores creates the CMS Keystore & PKCS#12 Truststore // generateAllDefaultKeystores creates the CMS Keystore & PKCS#12 Truststore
func generateAllKeystores() (KeyStoreData, KeyStoreData, error) { func generateAllDefaultKeystores() (TLSStore, error) {
var cmsKeystore, p12Truststore KeyStoreData var cmsKeystore, p12Truststore KeyStoreData
// Generate a pasword for use with both the CMS Keystore & PKCS#12 Truststore // Generate a pasword for use with both the CMS Keystore & PKCS#12 Truststore
@@ -148,30 +178,54 @@ func generateAllKeystores() (KeyStoreData, KeyStoreData, error) {
// Create the Keystore directory - if it does not already exist // Create the Keystore directory - if it does not already exist
// #nosec G301 - write group permissions are required // #nosec G301 - write group permissions are required
err := os.MkdirAll(keystoreDir, 0770) err := os.MkdirAll(keystoreDirDefault, 0770)
if err != nil { if err != nil {
return cmsKeystore, p12Truststore, fmt.Errorf("Failed to create Keystore directory: %v", err) return TLSStore{cmsKeystore, p12Truststore}, fmt.Errorf("Failed to create Keystore directory: %v", err)
} }
// Create the CMS Keystore // Create the CMS Keystore
cmsKeystore.Keystore = keystore.NewCMSKeyStore(filepath.Join(keystoreDir, cmsKeystoreName), cmsKeystore.Password) cmsKeystore.Keystore = keystore.NewCMSKeyStore(filepath.Join(keystoreDirDefault, cmsKeystoreName), cmsKeystore.Password)
err = cmsKeystore.Keystore.Create() err = cmsKeystore.Keystore.Create()
if err != nil { if err != nil {
return cmsKeystore, p12Truststore, fmt.Errorf("Failed to create CMS Keystore: %v", err) return TLSStore{cmsKeystore, p12Truststore}, fmt.Errorf("Failed to create CMS Keystore: %v", err)
} }
// Create the PKCS#12 Truststore // Create the PKCS#12 Truststore
p12Truststore.Keystore = keystore.NewPKCS12KeyStore(filepath.Join(keystoreDir, p12TruststoreName), p12Truststore.Password) p12Truststore.Keystore = keystore.NewPKCS12KeyStore(filepath.Join(keystoreDirDefault, p12TruststoreName), p12Truststore.Password)
err = p12Truststore.Keystore.Create() err = p12Truststore.Keystore.Create()
if err != nil { if err != nil {
return cmsKeystore, p12Truststore, fmt.Errorf("Failed to create PKCS#12 Truststore: %v", err) return TLSStore{cmsKeystore, p12Truststore}, fmt.Errorf("Failed to create PKCS#12 Truststore: %v", err)
}
return TLSStore{cmsKeystore, p12Truststore}, nil
}
// generateHAKeystore creates the CMS Keystore for Native HA replication
func generateHAKeystore() (TLSStore, error) {
var cmsKeystore KeyStoreData
// Generate a pasword for use with the CMS Keystore
pw := generateRandomPassword()
cmsKeystore.Password = pw
// Create the Keystore directory - if it does not already exist
// #nosec G301 - write group permissions are required
err := os.MkdirAll(keystoreDirHA, 0770)
if err != nil {
return TLSStore{Keystore: cmsKeystore}, fmt.Errorf("Failed to create HA Keystore directory: %v", err)
} }
return cmsKeystore, p12Truststore, nil // Create the CMS Keystore
cmsKeystore.Keystore = keystore.NewCMSKeyStore(filepath.Join(keystoreDirHA, cmsKeystoreName), cmsKeystore.Password)
err = cmsKeystore.Keystore.Create()
if err != nil {
return TLSStore{Keystore: cmsKeystore}, fmt.Errorf("Failed to create CMS Keystore: %v", err)
}
return TLSStore{Keystore: cmsKeystore}, nil
} }
// processKeys processes all keys - adding them to the CMS KeyStore // processKeys processes all keys - adding them to the CMS KeyStore
func processKeys(cmsKeystore, p12Truststore *KeyStoreData) (string, error) { func processKeys(tlsStore *TLSStore, keystoreDir string, keyDir string) (string, error) {
// Key label - will be set to the label of the first set of keys // Key label - will be set to the label of the first set of keys
keyLabel := "" keyLabel := ""
@@ -190,7 +244,7 @@ func processKeys(cmsKeystore, p12Truststore *KeyStoreData) (string, error) {
} }
// Process private key (*.key) // Process private key (*.key)
privateKey, keyPrefix, err := processPrivateKey(keySet.Name(), keys) privateKey, keyPrefix, err := processPrivateKey(keyDir, keySet.Name(), keys)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -201,13 +255,13 @@ func processKeys(cmsKeystore, p12Truststore *KeyStoreData) (string, error) {
} }
// Process certificates (*.crt) - public certificate & optional CA certificate // Process certificates (*.crt) - public certificate & optional CA certificate
publicCertificate, caCertificate, err := processCertificates(keySet.Name(), keyPrefix, keys, cmsKeystore, p12Truststore) publicCertificate, caCertificate, err := processCertificates(keyDir, keySet.Name(), keyPrefix, keys, &tlsStore.Keystore, &tlsStore.Truststore)
if err != nil { if err != nil {
return "", err return "", err
} }
// Create a new PKCS#12 Keystore - containing private key, public certificate & optional CA certificate // Create a new PKCS#12 Keystore - containing private key, public certificate & optional CA certificate
file, err := pkcs.Encode(rand.Reader, privateKey, publicCertificate, caCertificate, cmsKeystore.Password) file, err := pkcs.Encode(rand.Reader, privateKey, publicCertificate, caCertificate, tlsStore.Keystore.Password)
if err != nil { if err != nil {
return "", fmt.Errorf("Failed to encode PKCS#12 Keystore %s: %v", keySet.Name()+".p12", err) return "", fmt.Errorf("Failed to encode PKCS#12 Keystore %s: %v", keySet.Name()+".p12", err)
} }
@@ -217,13 +271,13 @@ func processKeys(cmsKeystore, p12Truststore *KeyStoreData) (string, error) {
} }
// Import the new PKCS#12 Keystore into the CMS Keystore // Import the new PKCS#12 Keystore into the CMS Keystore
err = cmsKeystore.Keystore.Import(filepath.Join(keystoreDir, keySet.Name()+".p12"), cmsKeystore.Password) err = tlsStore.Keystore.Keystore.Import(filepath.Join(keystoreDir, keySet.Name()+".p12"), tlsStore.Keystore.Password)
if err != nil { if err != nil {
return "", fmt.Errorf("Failed tp import keys from %s into CMS Keystore: %v", filepath.Join(keystoreDir, keySet.Name()+".p12"), err) return "", fmt.Errorf("Failed tp import keys from %s into CMS Keystore: %v", filepath.Join(keystoreDir, keySet.Name()+".p12"), err)
} }
// Relabel the certificate in the CMS Keystore // Relabel the certificate in the CMS Keystore
err = relabelCertificate(keySet.Name(), cmsKeystore) err = relabelCertificate(keySet.Name(), &tlsStore.Keystore)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -239,7 +293,7 @@ func processKeys(cmsKeystore, p12Truststore *KeyStoreData) (string, error) {
} }
// processTrustCertificates processes all trust certificates - adding them to the CMS KeyStore & PKCS#12 Truststore // processTrustCertificates processes all trust certificates - adding them to the CMS KeyStore & PKCS#12 Truststore
func processTrustCertificates(cmsKeystore, p12Truststore *KeyStoreData) error { func processTrustCertificates(tlsStore *TLSStore, trustDir string) error {
// Process all trust certiifcates // Process all trust certiifcates
trustList, err := ioutil.ReadDir(trustDir) trustList, err := ioutil.ReadDir(trustDir)
@@ -265,13 +319,13 @@ func processTrustCertificates(cmsKeystore, p12Truststore *KeyStoreData) error {
} }
// Add to known certificates for the CMS Keystore // Add to known certificates for the CMS Keystore
err = addToKnownCertificates(block, cmsKeystore, true) err = addToKnownCertificates(block, &tlsStore.Keystore, true)
if err != nil { if err != nil {
return fmt.Errorf("Failed to add to know certificates for CMS Keystore") return fmt.Errorf("Failed to add to know certificates for CMS Keystore")
} }
// Add to known certificates for the PKCS#12 Truststore // Add to known certificates for the PKCS#12 Truststore
err = addToKnownCertificates(block, p12Truststore, true) err = addToKnownCertificates(block, &tlsStore.Truststore, true)
if err != nil { if err != nil {
return fmt.Errorf("Failed to add to know certificates for PKCS#12 Truststore") return fmt.Errorf("Failed to add to know certificates for PKCS#12 Truststore")
} }
@@ -282,16 +336,16 @@ func processTrustCertificates(cmsKeystore, p12Truststore *KeyStoreData) error {
} }
// Add all trust certificates to PKCS#12 Truststore // Add all trust certificates to PKCS#12 Truststore
if len(p12Truststore.TrustedCerts) > 0 { if len(tlsStore.Truststore.TrustedCerts) > 0 {
err = addCertificatesToTruststore(p12Truststore) err = addCertificatesToTruststore(&tlsStore.Truststore)
if err != nil { if err != nil {
return err return err
} }
} }
// Add all trust certificates to CMS Keystore // Add all trust certificates to CMS Keystore
if len(cmsKeystore.TrustedCerts) > 0 { if len(tlsStore.Keystore.TrustedCerts) > 0 {
err = addCertificatesToCMSKeystore(cmsKeystore) err = addCertificatesToCMSKeystore(&tlsStore.Keystore)
if err != nil { if err != nil {
return err return err
} }
@@ -301,7 +355,7 @@ func processTrustCertificates(cmsKeystore, p12Truststore *KeyStoreData) error {
} }
// processPrivateKey processes the private key (*.key) from a set of keys // processPrivateKey processes the private key (*.key) from a set of keys
func processPrivateKey(keySetName string, keys []os.FileInfo) (interface{}, string, error) { func processPrivateKey(keyDir string, keySetName string, keys []os.FileInfo) (interface{}, string, error) {
var privateKey interface{} var privateKey interface{}
keyPrefix := "" keyPrefix := ""
@@ -336,7 +390,7 @@ func processPrivateKey(keySetName string, keys []os.FileInfo) (interface{}, stri
} }
// processCertificates processes the certificates (*.crt) from a set of keys // processCertificates processes the certificates (*.crt) from a set of keys
func processCertificates(keySetName, keyPrefix string, keys []os.FileInfo, cmsKeystore, p12Truststore *KeyStoreData) (*x509.Certificate, []*x509.Certificate, error) { func processCertificates(keyDir string, keySetName, keyPrefix string, keys []os.FileInfo, cmsKeystore, p12Truststore *KeyStoreData) (*x509.Certificate, []*x509.Certificate, error) {
var publicCertificate *x509.Certificate var publicCertificate *x509.Certificate
var caCertificate []*x509.Certificate var caCertificate []*x509.Certificate
@@ -384,10 +438,12 @@ func processCertificates(keySetName, keyPrefix string, keys []os.FileInfo, cmsKe
return nil, nil, fmt.Errorf("Failed to add to know certificates for CMS Keystore") return nil, nil, fmt.Errorf("Failed to add to know certificates for CMS Keystore")
} }
// Add to known certificates for the PKCS#12 Truststore if p12Truststore != nil {
err = addToKnownCertificates(block, p12Truststore, true) // Add to known certificates for the PKCS#12 Truststore
if err != nil { err = addToKnownCertificates(block, p12Truststore, true)
return nil, nil, fmt.Errorf("Failed to add to know certificates for PKCS#12 Truststore") if err != nil {
return nil, nil, fmt.Errorf("Failed to add to know certificates for PKCS#12 Truststore")
}
} }
certificate, err := x509.ParseCertificate(block.Bytes) certificate, err := x509.ParseCertificate(block.Bytes)

View File

@@ -60,7 +60,7 @@ func ConfigureWebKeystore(p12Truststore KeyStoreData, webKeystore string) (strin
if webKeystore == "" { if webKeystore == "" {
webKeystore = webKeystoreDefault webKeystore = webKeystoreDefault
} }
webKeystoreFile := filepath.Join(keystoreDir, webKeystore) webKeystoreFile := filepath.Join(keystoreDirDefault, webKeystore)
// Check if a new self-signed certificate should be generated // Check if a new self-signed certificate should be generated
genHostName := os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME") genHostName := os.Getenv("MQ_GENERATE_CERTIFICATE_HOSTNAME")