102 lines
2.6 KiB
Go
102 lines
2.6 KiB
Go
|
package x509_cert
|
||
|
|
||
|
import (
|
||
|
"crypto/x509"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
"path/filepath"
|
||
|
|
||
|
"github.com/pavlo-v-chernykh/keystore-go/v4"
|
||
|
"software.sslmate.com/src/go-pkcs12"
|
||
|
)
|
||
|
|
||
|
func normalizePath(path string) string {
|
||
|
normalized := filepath.ToSlash(path)
|
||
|
|
||
|
// Removing leading slash in Windows path containing a drive-letter
|
||
|
// like "file:///C:/Windows/..."
|
||
|
normalized = reDriveLetter.ReplaceAllString(normalized, "$1")
|
||
|
|
||
|
return filepath.FromSlash(normalized)
|
||
|
}
|
||
|
|
||
|
func (c *X509Cert) processPKCS12(path string) ([]*x509.Certificate, error) {
|
||
|
data, err := os.ReadFile(normalizePath(path))
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("failed to read PKCS#12 file: %w", err)
|
||
|
}
|
||
|
|
||
|
// Get the password string from config.Secret
|
||
|
password, err := c.Password.Get()
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("failed to get password: %w", err)
|
||
|
}
|
||
|
passwordStr := password.String()
|
||
|
password.Destroy()
|
||
|
|
||
|
_, cert, caCerts, err := pkcs12.DecodeChain(data, passwordStr)
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("failed to decode PKCS#12 keystore: %w", err)
|
||
|
}
|
||
|
|
||
|
// Ensure Root CA pool exists
|
||
|
if c.tlsCfg.RootCAs == nil {
|
||
|
c.tlsCfg.RootCAs = x509.NewCertPool()
|
||
|
}
|
||
|
|
||
|
// Add CA certificates to RootCAs
|
||
|
for _, caCert := range caCerts {
|
||
|
c.tlsCfg.RootCAs.AddCert(caCert)
|
||
|
}
|
||
|
|
||
|
return append([]*x509.Certificate{cert}, caCerts...), nil
|
||
|
}
|
||
|
|
||
|
func (c *X509Cert) processJKS(path string) ([]*x509.Certificate, error) {
|
||
|
file, err := os.Open(normalizePath(path))
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("failed to open JKS file: %w", err)
|
||
|
}
|
||
|
defer file.Close()
|
||
|
|
||
|
// Get the password string from config.Secret
|
||
|
password, err := c.Password.Get()
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("failed to get password: %w", err)
|
||
|
}
|
||
|
defer password.Destroy()
|
||
|
|
||
|
ks := keystore.New()
|
||
|
if err := ks.Load(file, password.Bytes()); err != nil {
|
||
|
return nil, fmt.Errorf("failed to decode JKS: %w", err)
|
||
|
}
|
||
|
|
||
|
// Ensure Root CA pool exists
|
||
|
if c.tlsCfg.RootCAs == nil {
|
||
|
c.tlsCfg.RootCAs = x509.NewCertPool()
|
||
|
}
|
||
|
|
||
|
certs := make([]*x509.Certificate, 0, len(ks.Aliases()))
|
||
|
|
||
|
for _, alias := range ks.Aliases() {
|
||
|
// Check for both trusted certificates and private key entries
|
||
|
if entry, err := ks.GetTrustedCertificateEntry(alias); err == nil {
|
||
|
cert, err := x509.ParseCertificate(entry.Certificate.Content)
|
||
|
if err == nil {
|
||
|
c.tlsCfg.RootCAs.AddCert(cert)
|
||
|
certs = append(certs, cert)
|
||
|
}
|
||
|
} else if entry, err := ks.GetPrivateKeyEntry(alias, password.Bytes()); err == nil {
|
||
|
for _, certData := range entry.CertificateChain {
|
||
|
cert, err := x509.ParseCertificate(certData.Content)
|
||
|
if err == nil {
|
||
|
c.tlsCfg.RootCAs.AddCert(cert)
|
||
|
certs = append(certs, cert)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return certs, nil
|
||
|
}
|