github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/certpool.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package api
     5  
     6  import (
     7  	"crypto/x509"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/juju/errors"
    12  	"github.com/juju/utils/v3/cert"
    13  
    14  	"github.com/juju/juju/core/paths"
    15  )
    16  
    17  var certDir = filepath.FromSlash(paths.CertDir(paths.CurrentOS()))
    18  
    19  // CreateCertPool creates a new x509.CertPool and adds in the caCert passed
    20  // in.  All certs from the cert directory (/etc/juju/cert.d on ubuntu) are
    21  // also added.
    22  func CreateCertPool(caCert string) (*x509.CertPool, error) {
    23  
    24  	pool := x509.NewCertPool()
    25  	if caCert != "" {
    26  		xcert, err := cert.ParseCert(caCert)
    27  		if err != nil {
    28  			return nil, errors.Annotatef(err, "cannot parse certificate %q", caCert)
    29  		}
    30  		pool.AddCert(xcert)
    31  	}
    32  
    33  	count := processCertDir(pool)
    34  	if count >= 0 {
    35  		logger.Debugf("added %d certs to the pool from %s", count, certDir)
    36  	}
    37  
    38  	return pool, nil
    39  }
    40  
    41  // processCertDir iterates through the certDir looking for *.pem files.
    42  // Each pem file is read in turn and added to the pool.  A count of the number
    43  // of successful certificates processed is returned.
    44  func processCertDir(pool *x509.CertPool) (count int) {
    45  	fileInfo, err := os.Stat(certDir)
    46  	if os.IsNotExist(err) {
    47  		logger.Tracef("cert dir %q does not exist", certDir)
    48  		return -1
    49  	}
    50  	if err != nil {
    51  		logger.Infof("unexpected error reading cert dir: %s", err)
    52  		return -1
    53  	}
    54  	if !fileInfo.IsDir() {
    55  		logger.Infof("cert dir %q is not a directory", certDir)
    56  		return -1
    57  	}
    58  
    59  	matches, err := filepath.Glob(filepath.Join(certDir, "*.pem"))
    60  	if err != nil {
    61  		logger.Infof("globbing files failed: %s", err)
    62  		return -1
    63  	}
    64  
    65  	for _, match := range matches {
    66  		data, err := os.ReadFile(match)
    67  		if err != nil {
    68  			logger.Infof("error reading %q: %v", match, err)
    69  			continue
    70  		}
    71  		certificate, err := cert.ParseCert(string(data))
    72  		if err != nil {
    73  			logger.Infof("error parsing cert %q: %v", match, err)
    74  			continue
    75  		}
    76  		pool.AddCert(certificate)
    77  		count++
    78  	}
    79  	return count
    80  }