Refactor TLS code
This commit is contained in:
614
internal/tls/tls.go
Normal file
614
internal/tls/tls.go
Normal file
@@ -0,0 +1,614 @@
|
||||
/*
|
||||
© Copyright IBM Corporation 2019
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
package tls
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
pwr "math/rand"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
|
||||
"github.com/ibm-messaging/mq-container/internal/copy"
|
||||
"github.com/ibm-messaging/mq-container/internal/keystore"
|
||||
pkcs "software.sslmate.com/src/go-pkcs12"
|
||||
)
|
||||
|
||||
// IntegrationDefaultLabel is the default certificate label used by Cloud Integration Platform
|
||||
const IntegrationDefaultLabel = "default"
|
||||
|
||||
// P12TrustStoreName is the name of the PKCS#12 truststore used by the webconsole
|
||||
const P12TrustStoreName = "trust.p12"
|
||||
|
||||
// CMSKeyStoreName is the name of the CMS Keystore used by the queue manager
|
||||
const CMSKeyStoreName = "key.kdb"
|
||||
|
||||
type KeyStoreData struct {
|
||||
Keystore *keystore.KeyStore
|
||||
Password string
|
||||
TrustedCerts []*pem.Block
|
||||
KnownFingerPrints []string
|
||||
KeyLabels []string
|
||||
}
|
||||
|
||||
type P12KeyFiles struct {
|
||||
Keystores []string
|
||||
Password string
|
||||
}
|
||||
|
||||
func getCertFingerPrint(block *pem.Block) (string, error) {
|
||||
// Add to future truststore and known certs (if not already there)
|
||||
cert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("could not parse x509 certificate: %v", err)
|
||||
}
|
||||
sha1Sum := sha1.Sum(cert.Raw)
|
||||
sha1str := string(sha1Sum[:])
|
||||
|
||||
return sha1str, nil
|
||||
}
|
||||
|
||||
// Add to Keystores known certs (if not already there) and add to the
|
||||
// Keystore if "addToKeystore" is true.
|
||||
func addCertToKeyData(block *pem.Block, keyData *KeyStoreData, addToKeystore bool) error {
|
||||
sha1str, err := getCertFingerPrint(block)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
known := false
|
||||
for _, fingerprint := range keyData.KnownFingerPrints {
|
||||
if fingerprint == sha1str {
|
||||
known = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !known {
|
||||
// Sometimes we don't want to add to the keystore trust here.
|
||||
// For example if it will be imported with the key later.
|
||||
if addToKeystore {
|
||||
keyData.TrustedCerts = append(keyData.TrustedCerts, block)
|
||||
}
|
||||
keyData.KnownFingerPrints = append(keyData.KnownFingerPrints, sha1str)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Generates a random 12 character password from the characters a-z, A-Z, 0-9.
|
||||
func generateRandomPassword() string {
|
||||
pwr.Seed(time.Now().Unix())
|
||||
validChars := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
validcharArray := []byte(validChars)
|
||||
password := ""
|
||||
for i := 0; i < 12; i++ {
|
||||
password = password + string(validcharArray[pwr.Intn(len(validcharArray))])
|
||||
}
|
||||
|
||||
return password
|
||||
}
|
||||
|
||||
// Creates the PKCS#12 Truststore and the CMS Keystore.
|
||||
func generateAllStores(dir string) (KeyStoreData, KeyStoreData, error) {
|
||||
var cmsKeystore, p12TrustStore KeyStoreData
|
||||
pw := generateRandomPassword()
|
||||
|
||||
cmsKeystore.Password = pw
|
||||
p12TrustStore.Password = pw
|
||||
|
||||
// Create the keystore Directory (if it doesn't already exist)
|
||||
os.MkdirAll(dir, 0775)
|
||||
|
||||
p12TrustStore.Keystore = keystore.NewPKCS12KeyStore(filepath.Join(dir, P12TrustStoreName), p12TrustStore.Password)
|
||||
err := p12TrustStore.Keystore.Create()
|
||||
if err != nil {
|
||||
return cmsKeystore, p12TrustStore, fmt.Errorf("Failed to create PKCS#12 TrustStore: %v", err)
|
||||
}
|
||||
|
||||
cmsKeystore.Keystore = keystore.NewCMSKeyStore(filepath.Join(dir, CMSKeyStoreName), cmsKeystore.Password)
|
||||
err = cmsKeystore.Keystore.Create()
|
||||
if err != nil {
|
||||
return cmsKeystore, p12TrustStore, fmt.Errorf("Failed to create CMS KeyStore: %v", err)
|
||||
}
|
||||
|
||||
return cmsKeystore, p12TrustStore, nil
|
||||
}
|
||||
|
||||
// processKeys walks through the keyDir directory and imports any keys it finds to individual PKCS#12 keystores
|
||||
// and the CMS KeyStore. The label it uses is the name of the directory if finds the keys in.
|
||||
func processKeys(keyDir, outputDir string, cmsKeyDB, p12TrustDB *KeyStoreData) (string, P12KeyFiles, error) {
|
||||
var p12s P12KeyFiles
|
||||
var firstLabel string
|
||||
|
||||
pwToUse := cmsKeyDB.Password
|
||||
p12s.Password = pwToUse
|
||||
trustStoreReserveredName := P12TrustStoreName[0 : len(P12TrustStoreName)-len(filepath.Ext(P12TrustStoreName))]
|
||||
keyList, err := ioutil.ReadDir(keyDir)
|
||||
|
||||
if err == nil && len(keyList) > 0 {
|
||||
// Found some keys, verify the contents
|
||||
for _, key := range keyList {
|
||||
keys, _ := ioutil.ReadDir(filepath.Join(keyDir, key.Name()))
|
||||
keyLabel := key.Name()
|
||||
if keyLabel == trustStoreReserveredName {
|
||||
return firstLabel, p12s, fmt.Errorf("Found key with same label set as same name as truststore(%s). This is not allowed", trustStoreReserveredName)
|
||||
}
|
||||
|
||||
keyfilename := ""
|
||||
var keyfile interface{}
|
||||
var certFile *x509.Certificate
|
||||
var caFile []*x509.Certificate
|
||||
|
||||
// find the keyfile name
|
||||
for _, a := range keys {
|
||||
if strings.HasSuffix(a.Name(), ".key") {
|
||||
keyFile, err := ioutil.ReadFile(filepath.Join(keyDir, key.Name(), a.Name()))
|
||||
if err != nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not read keyfile %s: %v", filepath.Join(keyDir, key.Name(), a.Name()), err)
|
||||
}
|
||||
block, _ := pem.Decode(keyFile)
|
||||
if block == nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not decode keyfile %s: pem.Decode returned nil", filepath.Join(keyDir, key.Name(), a.Name()))
|
||||
}
|
||||
|
||||
//Test whether it is PKCS1
|
||||
keyfile, err = x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
// Before we fail check whether it is PKCS8
|
||||
keyfile, err = x509.ParsePKCS8PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
fmt.Printf("key %s ParsePKCS1/8PrivateKey ERR: %v\n", filepath.Join(keyDir, key.Name(), a.Name()), err)
|
||||
return firstLabel, p12s, err
|
||||
}
|
||||
//It was PKCS8 afterall
|
||||
}
|
||||
keyfilename = a.Name()
|
||||
}
|
||||
}
|
||||
if keyfile == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find out what the keyfile was called without the extension
|
||||
prefix := keyfilename[0 : len(keyfilename)-len(filepath.Ext(keyfilename))]
|
||||
|
||||
for _, a := range keys {
|
||||
if strings.HasSuffix(a.Name(), ".key") {
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(a.Name(), prefix) && strings.HasSuffix(a.Name(), ".crt") {
|
||||
cert, err := ioutil.ReadFile(filepath.Join(keyDir, key.Name(), a.Name()))
|
||||
if err != nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not read file %s: %v", filepath.Join(keyDir, key.Name(), a.Name()), err)
|
||||
}
|
||||
block, _ := pem.Decode(cert)
|
||||
if block == nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not decode certificate %s: pem.Decode returned nil", filepath.Join(keyDir, key.Name(), a.Name()))
|
||||
}
|
||||
certFile, err = x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not parse certificate %s: %v", filepath.Join(keyDir, key.Name(), a.Name()), err)
|
||||
}
|
||||
// Add to the dup list for the CMS keystore but not the PKCS#12 Truststore
|
||||
err = addCertToKeyData(block, cmsKeyDB, false)
|
||||
|
||||
} else if strings.HasSuffix(a.Name(), ".crt") {
|
||||
remainder, err := ioutil.ReadFile(filepath.Join(keyDir, key.Name(), a.Name()))
|
||||
if err != nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not read file %s: %v", filepath.Join(keyDir, key.Name(), a.Name()), err)
|
||||
}
|
||||
|
||||
for string(remainder) != "" {
|
||||
var block *pem.Block
|
||||
block, remainder = pem.Decode(remainder)
|
||||
// If we can't decode the CA certificate then just exit.
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
|
||||
// Add to the dup list for the CMS keystore
|
||||
err = addCertToKeyData(block, cmsKeyDB, false)
|
||||
|
||||
// Add to the p12 truststore
|
||||
err = addCertToKeyData(block, p12TrustDB, true)
|
||||
|
||||
caCert, err := x509.ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not parse CA certificate %s: %v", filepath.Join(keyDir, key.Name(), a.Name()), err)
|
||||
}
|
||||
|
||||
caFile = append(caFile, caCert)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create p12 keystore
|
||||
file, err := pkcs.Encode(rand.Reader, keyfile, certFile, caFile, pwToUse)
|
||||
if err != nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not encode PKCS#12 Keystore %s: %v", keyLabel+".p12", err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(filepath.Join(outputDir, keyLabel+".p12"), file, 0644)
|
||||
if err != nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not write PKCS#12 Keystore %s: %v", filepath.Join(outputDir, keyLabel+".p12"), err)
|
||||
}
|
||||
|
||||
p12s.Keystores = append(p12s.Keystores, keyLabel+".p12")
|
||||
|
||||
// Add to the CMS keystore
|
||||
err = cmsKeyDB.Keystore.Import(filepath.Join(outputDir, keyLabel+".p12"), pwToUse)
|
||||
if err != nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not import keys from %s into CMS Keystore: %v", filepath.Join(outputDir, keyLabel+".p12"), err)
|
||||
}
|
||||
|
||||
// Relabel it
|
||||
allLabels, err := cmsKeyDB.Keystore.GetCertificateLabels()
|
||||
if err != nil {
|
||||
return firstLabel, p12s, fmt.Errorf("Could not list keys in CMS Keystore: %v", err)
|
||||
}
|
||||
relabelled := false
|
||||
for _, cl := range allLabels {
|
||||
found := false
|
||||
for _, kl := range cmsKeyDB.KeyLabels {
|
||||
if strings.Trim(cl, "\"") == kl {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
// This is the one to rename
|
||||
err = cmsKeyDB.Keystore.RenameCertificate(strings.Trim(cl, "\""), keyLabel)
|
||||
if err != nil {
|
||||
return firstLabel, p12s, err
|
||||
}
|
||||
relabelled = true
|
||||
cmsKeyDB.KeyLabels = append(cmsKeyDB.KeyLabels, keyLabel)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !relabelled {
|
||||
return firstLabel, p12s, fmt.Errorf("Unable to find the added key for %s in CMS keystore", keyLabel)
|
||||
}
|
||||
|
||||
// First key found so mark it as the one to use with the queue manager.
|
||||
if firstLabel == "" {
|
||||
firstLabel = keyLabel
|
||||
}
|
||||
}
|
||||
}
|
||||
return firstLabel, p12s, nil
|
||||
}
|
||||
|
||||
// processTrustCertificates walks through the trustDir directory and adds any certificates it finds
|
||||
// to the PKCS#12 Truststore and the CMS KeyStore as long as has not already been added.
|
||||
func processTrustCertificates(trustDir string, cmsKeyDB, p12TrustDB *KeyStoreData) error {
|
||||
certList, err := ioutil.ReadDir(trustDir)
|
||||
if err == nil && len(certList) > 0 {
|
||||
// Found some keys, verify the contents
|
||||
for _, cert := range certList {
|
||||
certs, _ := ioutil.ReadDir(filepath.Join(trustDir, cert.Name()))
|
||||
for _, a := range certs {
|
||||
if strings.HasSuffix(a.Name(), ".crt") {
|
||||
remainder, err := ioutil.ReadFile(filepath.Join(trustDir, cert.Name(), a.Name()))
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not read file %s: %v", filepath.Join(trustDir, cert.Name(), a.Name()), err)
|
||||
}
|
||||
|
||||
for string(remainder) != "" {
|
||||
var block *pem.Block
|
||||
block, remainder = pem.Decode(remainder)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
|
||||
// Add to the CMS keystore
|
||||
err = addCertToKeyData(block, cmsKeyDB, true)
|
||||
|
||||
// Add to the p12 truststore
|
||||
err = addCertToKeyData(block, p12TrustDB, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// We've potentially created two lists of certificates to import. Add them both to relevant Truststores
|
||||
if len(p12TrustDB.TrustedCerts) > 0 {
|
||||
// Do P12 TrustStore first
|
||||
temporaryPemFile := filepath.Join("/tmp", "trust.pem")
|
||||
os.Remove(temporaryPemFile)
|
||||
|
||||
err := writeCertsToFile(temporaryPemFile, p12TrustDB.TrustedCerts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = p12TrustDB.Keystore.AddNoLabel(temporaryPemFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not add certificates to PKCS#12 Truststore: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(cmsKeyDB.TrustedCerts) > 0 {
|
||||
// Now the CMS Keystore
|
||||
temporaryPemFile := filepath.Join("/tmp", "cmsTrust.pem")
|
||||
os.Remove(temporaryPemFile)
|
||||
|
||||
err = writeCertsToFile(temporaryPemFile, cmsKeyDB.TrustedCerts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = cmsKeyDB.Keystore.AddNoLabel(temporaryPemFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not add certificates to CMS keystore: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Writes a given list of certificates to a file.
|
||||
func writeCertsToFile(file string, certs []*pem.Block) error {
|
||||
f, err := os.Create(file)
|
||||
if err != nil {
|
||||
return fmt.Errorf("writeCertsToFile: Could not create file %s: %v", file, err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
w := bufio.NewWriter(f)
|
||||
|
||||
for i, c := range certs {
|
||||
err := pem.Encode(w, c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("writeCertsToFile: Could not encode certificate number %d: %v", i, err)
|
||||
}
|
||||
w.Flush()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConfigureTLSKeystores sets up the TLS Trust and Keystores for use
|
||||
func ConfigureTLSKeystores(keyDir, certDir, outputDir string) (string, KeyStoreData, KeyStoreData, P12KeyFiles, error) {
|
||||
var returnLabel, label string
|
||||
var cmsKeyDB, p12TrustDB KeyStoreData
|
||||
var keyFiles P12KeyFiles
|
||||
var err error
|
||||
|
||||
cmsKeyDB, p12TrustDB, err = generateAllStores(outputDir)
|
||||
if err != nil {
|
||||
return returnLabel, cmsKeyDB, p12TrustDB, keyFiles, err
|
||||
}
|
||||
|
||||
err = handleIntegrationGeneratedCerts(keyDir)
|
||||
if err != nil {
|
||||
return returnLabel, cmsKeyDB, p12TrustDB, keyFiles, err
|
||||
}
|
||||
|
||||
returnLabel, err = expandOldTLSVarible(keyDir, outputDir, &cmsKeyDB, &p12TrustDB)
|
||||
if err != nil {
|
||||
return returnLabel, cmsKeyDB, p12TrustDB, keyFiles, err
|
||||
}
|
||||
|
||||
label, keyFiles, err = processKeys(keyDir, outputDir, &cmsKeyDB, &p12TrustDB)
|
||||
if err != nil {
|
||||
return returnLabel, cmsKeyDB, p12TrustDB, keyFiles, err
|
||||
}
|
||||
if returnLabel == "" {
|
||||
returnLabel = label
|
||||
}
|
||||
|
||||
err = processTrustCertificates(certDir, &cmsKeyDB, &p12TrustDB)
|
||||
if err != nil {
|
||||
return returnLabel, cmsKeyDB, p12TrustDB, keyFiles, err
|
||||
}
|
||||
|
||||
return returnLabel, cmsKeyDB, p12TrustDB, keyFiles, err
|
||||
}
|
||||
|
||||
// This function supports an old mechanism of importing certificates
|
||||
func handleIntegrationGeneratedCerts(keyDir string) error {
|
||||
dir := "/mnt/tls"
|
||||
outputdir := filepath.Join(keyDir, IntegrationDefaultLabel)
|
||||
keyfile := "tls.key"
|
||||
crtfile := "tls.crt"
|
||||
|
||||
// check that the files exist, if not just quietly leave as there's nothing to import
|
||||
_, err := os.Stat(filepath.Join(dir, keyfile))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = os.Stat(filepath.Join(dir, crtfile))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check the destination directory DOES not exist ahead of time
|
||||
_, err = os.Stat(outputdir)
|
||||
if err == nil {
|
||||
return fmt.Errorf("Found CIP certificates to import but a TLS secret called %s is already present", IntegrationDefaultLabel)
|
||||
} else if !os.IsNotExist(err) {
|
||||
return fmt.Errorf("Failed to check that %s does not exist: %v", outputdir, err)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(outputdir, 0775)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not create %s: %v", outputdir, err)
|
||||
}
|
||||
|
||||
err = copy.CopyFileMode(filepath.Join(dir, keyfile), filepath.Join(outputdir, keyfile), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not copy %s: %v", keyfile, err)
|
||||
}
|
||||
|
||||
err = copy.CopyFileMode(filepath.Join(dir, crtfile), filepath.Join(outputdir, crtfile), 0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Could not copy %s: %v", keyfile, err)
|
||||
}
|
||||
|
||||
// With certificates copied into place the rest of the TLS handling code will import them into the correct place
|
||||
return nil
|
||||
}
|
||||
|
||||
// This function supports the old mechanism of importing certificates supplied by the MQ_TLS_KEYSTORE envvar
|
||||
func expandOldTLSVarible(keyDir, outputDir string, cmsKeyDB, p12TrustDB *KeyStoreData) (string, error) {
|
||||
// TODO: Change this or find a way to set it
|
||||
outputDirName := "acopiedcertificate"
|
||||
|
||||
// Check whether the old variable is set. If not exit quietly
|
||||
keyfile := os.Getenv("MQ_TLS_KEYSTORE")
|
||||
if keyfile == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// There is a file to read and process
|
||||
keyfilepw := os.Getenv("MQ_TLS_PASSPHRASE")
|
||||
|
||||
if !strings.HasSuffix(keyfile, ".p12") {
|
||||
return "", fmt.Errorf("MQ_TLS_KEYSTORE (%s) does not point to a PKCS#12 file ending with the suffix .p12", keyfile)
|
||||
}
|
||||
|
||||
_, err := os.Stat(keyfile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("File %s referenced by MQ_TLS_KEYSTORE does not exist", keyfile)
|
||||
}
|
||||
|
||||
readkey, err := ioutil.ReadFile(keyfile)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to read %s: %v", keyfile, err)
|
||||
}
|
||||
|
||||
// File has been checked and read, decode it.
|
||||
pk, cert, cas, err := pkcs.DecodeChain(readkey, keyfilepw)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to decode %s: %v", keyfile, err)
|
||||
}
|
||||
|
||||
// Find a directory name that doesn't exist
|
||||
for {
|
||||
_, err := os.Stat(filepath.Join(keyDir, outputDirName))
|
||||
if err == nil {
|
||||
outputDirName = outputDirName + "0"
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
//Bceause they supplied this certificate using the old method we should use this for qm & webconsole
|
||||
overrideLabel := outputDirName
|
||||
|
||||
// Write out the certificate for the private key
|
||||
if cert != nil {
|
||||
block := pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Headers: nil,
|
||||
Bytes: cert.Raw,
|
||||
}
|
||||
err = addCertToKeyData(&block, cmsKeyDB, false)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("expandOldTLSVarible: Failed to add cert to CMS Keystore duplicate list: %v", err)
|
||||
}
|
||||
err = addCertToKeyData(&block, p12TrustDB, true)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("expandOldTLSVarible: Failed to add cert to P12 Truststore duplicate list: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// now write out all the ca certificates
|
||||
if cas != nil || len(cas) > 0 {
|
||||
for i, c := range cas {
|
||||
block := pem.Block{
|
||||
Type: "CERTIFICATE",
|
||||
Headers: nil,
|
||||
Bytes: c.Raw,
|
||||
}
|
||||
|
||||
// Add to the dup list for the CMS keystore
|
||||
err = addCertToKeyData(&block, cmsKeyDB, false)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("expandOldTLSVarible: Failed to add CA cert %d to CMS Keystore duplicate list: %v", i, err)
|
||||
}
|
||||
|
||||
// Add to the p12 truststore
|
||||
err = addCertToKeyData(&block, p12TrustDB, true)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("expandOldTLSVarible: Failed to add CA cert %d to P12 Truststore duplicate list: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now we've handled the certificates copy the keystore into place
|
||||
destination := filepath.Join(outputDir, outputDirName+".p12")
|
||||
|
||||
// Create p12 keystore
|
||||
file, err := pkcs.Encode(rand.Reader, pk, cert, cas, p12TrustDB.Password)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to re-encode p12 keystore: %v", err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile(destination, file, 0644)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to write p12 keystore: %v", err)
|
||||
}
|
||||
|
||||
// Add to the CMS keystore
|
||||
err = cmsKeyDB.Keystore.Import(destination, p12TrustDB.Password)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Failed to import p12 keystore %s: %v", destination, err)
|
||||
}
|
||||
|
||||
if pk != nil {
|
||||
// Relabel the key
|
||||
allLabels, err := cmsKeyDB.Keystore.GetCertificateLabels()
|
||||
if err != nil {
|
||||
fmt.Printf("cms GetCertificateLabels: %v\n", err)
|
||||
return "", err
|
||||
}
|
||||
relabelled := false
|
||||
for _, cl := range allLabels {
|
||||
found := false
|
||||
for _, kl := range cmsKeyDB.KeyLabels {
|
||||
if strings.Trim(cl, "\"") == kl {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
// This is the one to rename
|
||||
err = cmsKeyDB.Keystore.RenameCertificate(strings.Trim(cl, "\""), outputDirName)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
relabelled = true
|
||||
cmsKeyDB.KeyLabels = append(cmsKeyDB.KeyLabels, outputDirName)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !relabelled {
|
||||
return "", fmt.Errorf("Unable to find the added key in CMS keystore")
|
||||
}
|
||||
}
|
||||
|
||||
return overrideLabel, nil
|
||||
}
|
||||
Reference in New Issue
Block a user