github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/lib/srpc/load.go (about)

     1  package srpc
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"fmt"
     7  	"os"
     8  	"path"
     9  	"sort"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/Cloud-Foundations/Dominator/lib/format"
    14  	"github.com/Cloud-Foundations/Dominator/lib/x509util"
    15  )
    16  
    17  func loadCertificates(directory string) ([]tls.Certificate, error) {
    18  	dir, err := os.Open(directory)
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  	names, err := dir.Readdirnames(0)
    23  	defer dir.Close()
    24  	if err != nil {
    25  		return nil, err
    26  	}
    27  	certs := make([]tls.Certificate, 0, len(names)/2)
    28  	now := time.Now()
    29  	for _, keyName := range names {
    30  		if !strings.HasSuffix(keyName, ".key") {
    31  			continue
    32  		}
    33  		certName := keyName[:len(keyName)-3] + "cert"
    34  		cert, err := tls.LoadX509KeyPair(
    35  			path.Join(directory, certName),
    36  			path.Join(directory, keyName))
    37  		if err != nil {
    38  			return nil, fmt.Errorf("unable to load keypair: %s", err)
    39  		}
    40  		x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
    41  		if err != nil {
    42  			return nil, err
    43  		}
    44  		if notYet := x509Cert.NotBefore.Sub(now); notYet > 0 {
    45  			return nil, fmt.Errorf("%s will not be valid for %s",
    46  				certName, format.Duration(notYet))
    47  		}
    48  		if expired := now.Sub(x509Cert.NotAfter); expired > 0 {
    49  			return nil, fmt.Errorf("%s expired %s ago",
    50  				certName, format.Duration(expired))
    51  		}
    52  		cert.Leaf = x509Cert
    53  		certs = append(certs, cert)
    54  	}
    55  	if len(certs) < 1 {
    56  		return nil, nil
    57  	}
    58  	// Sort list so that certificates with the most permitted methods are listed
    59  	// first and in turn should be tried first when doing the TLS handshake.
    60  	sort.Slice(certs, func(leftIndex, rightIndex int) bool {
    61  		leftMethods, _ := x509util.GetPermittedMethods(certs[leftIndex].Leaf)
    62  		rightMethods, _ := x509util.GetPermittedMethods(certs[rightIndex].Leaf)
    63  		return len(leftMethods) > len(rightMethods)
    64  	})
    65  	return certs, nil
    66  }