github.com/hashicorp/vault/sdk@v0.11.0/helper/testcluster/docker/cert.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package docker
     5  
     6  import (
     7  	"crypto/tls"
     8  	"crypto/x509"
     9  	"encoding/pem"
    10  	"errors"
    11  	"fmt"
    12  	"io/ioutil"
    13  	"sync"
    14  
    15  	"github.com/hashicorp/errwrap"
    16  )
    17  
    18  // ReloadFunc are functions that are called when a reload is requested
    19  type ReloadFunc func() error
    20  
    21  // CertificateGetter satisfies ReloadFunc and its GetCertificate method
    22  // satisfies the tls.GetCertificate function signature.  Currently it does not
    23  // allow changing paths after the fact.
    24  type CertificateGetter struct {
    25  	sync.RWMutex
    26  
    27  	cert *tls.Certificate
    28  
    29  	certFile   string
    30  	keyFile    string
    31  	passphrase string
    32  }
    33  
    34  func NewCertificateGetter(certFile, keyFile, passphrase string) *CertificateGetter {
    35  	return &CertificateGetter{
    36  		certFile:   certFile,
    37  		keyFile:    keyFile,
    38  		passphrase: passphrase,
    39  	}
    40  }
    41  
    42  func (cg *CertificateGetter) Reload() error {
    43  	certPEMBlock, err := ioutil.ReadFile(cg.certFile)
    44  	if err != nil {
    45  		return err
    46  	}
    47  	keyPEMBlock, err := ioutil.ReadFile(cg.keyFile)
    48  	if err != nil {
    49  		return err
    50  	}
    51  
    52  	// Check for encrypted pem block
    53  	keyBlock, _ := pem.Decode(keyPEMBlock)
    54  	if keyBlock == nil {
    55  		return errors.New("decoded PEM is blank")
    56  	}
    57  
    58  	if x509.IsEncryptedPEMBlock(keyBlock) {
    59  		keyBlock.Bytes, err = x509.DecryptPEMBlock(keyBlock, []byte(cg.passphrase))
    60  		if err != nil {
    61  			return errwrap.Wrapf("Decrypting PEM block failed {{err}}", err)
    62  		}
    63  		keyPEMBlock = pem.EncodeToMemory(keyBlock)
    64  	}
    65  
    66  	cert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock)
    67  	if err != nil {
    68  		return err
    69  	}
    70  
    71  	cg.Lock()
    72  	defer cg.Unlock()
    73  
    74  	cg.cert = &cert
    75  
    76  	return nil
    77  }
    78  
    79  func (cg *CertificateGetter) GetCertificate(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
    80  	cg.RLock()
    81  	defer cg.RUnlock()
    82  
    83  	if cg.cert == nil {
    84  		return nil, fmt.Errorf("nil certificate")
    85  	}
    86  
    87  	return cg.cert, nil
    88  }