github.com/jlmeeker/kismatic@v1.10.1-0.20180612190640-57f9005a1f1a/integration-tests/tls/cert.go (about)

     1  package tls
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  
     9  	"github.com/cloudflare/cfssl/cli/genkey"
    10  	"github.com/cloudflare/cfssl/config"
    11  	"github.com/cloudflare/cfssl/csr"
    12  	"github.com/cloudflare/cfssl/helpers"
    13  	"github.com/cloudflare/cfssl/signer"
    14  	"github.com/cloudflare/cfssl/signer/local"
    15  )
    16  
    17  // CA contains information about the Certificate Authority
    18  type CA struct {
    19  	// Key is the CA's private key.
    20  	Key []byte
    21  	// Password is the CA's private key password. Can be empty if not password is set.
    22  	Password string
    23  	// Cert is the CA's public certificate.
    24  	Cert []byte
    25  	// ConfigFile contains a cfssl configuration file for the Certificate Authority
    26  	ConfigFile string
    27  	// Profile to be used when signing with this Certificate Authority
    28  	Profile string
    29  }
    30  
    31  // NewCert creates a new certificate/key pair using the CertificateAuthority provided
    32  func NewCert(ca *CA, req csr.CertificateRequest) (key, cert []byte, err error) {
    33  	g := &csr.Generator{Validator: genkey.Validator}
    34  	csrBytes, key, err := g.ProcessRequest(&req)
    35  	if err != nil {
    36  		return nil, nil, fmt.Errorf("error processing CSR: %v", err)
    37  	}
    38  	// Get CA private key
    39  	caPriv, err := helpers.ParsePrivateKeyPEMWithPassword(ca.Key, []byte(ca.Password))
    40  	if err != nil {
    41  		return nil, nil, fmt.Errorf("error parsing private key: %v", err)
    42  	}
    43  	// Parse CA Cert
    44  	caCert, err := helpers.ParseCertificatePEM(ca.Cert)
    45  	if err != nil {
    46  		return nil, nil, fmt.Errorf("error parsing CA cert: %v", err)
    47  	}
    48  	sigAlgo := signer.DefaultSigAlgo(caPriv)
    49  	// Get CA config from file
    50  	caConfig, err := config.LoadFile(ca.ConfigFile)
    51  	if err != nil {
    52  		return nil, nil, fmt.Errorf("error loading CA Config: %v", err)
    53  	}
    54  	// Create signer using CA
    55  	s, err := local.NewSigner(caPriv, caCert, sigAlgo, caConfig.Signing)
    56  	if err != nil {
    57  		return nil, nil, fmt.Errorf("error creating signer: %v", err)
    58  	}
    59  	// Generate cert using CA signer
    60  	signReq := signer.SignRequest{
    61  		Request: string(csrBytes),
    62  		Profile: ca.Profile,
    63  	}
    64  	cert, err = s.Sign(signReq)
    65  	if err != nil {
    66  		return nil, nil, fmt.Errorf("error signing certificate: %v", err)
    67  	}
    68  	return key, cert, nil
    69  }
    70  
    71  // WriteCert writes cert and key files
    72  func WriteCert(key, cert []byte, name, dir string) error {
    73  	// Create destination dir if it doesn't exist
    74  	err := CreateDir(dir, 0744)
    75  	if err != nil {
    76  		return err
    77  	}
    78  	// Write private key with read-only for user
    79  	err = ioutil.WriteFile(filepath.Join(dir, keyName(name)), key, 0600)
    80  	if err != nil {
    81  		return fmt.Errorf("error writing private key: %v", err)
    82  	}
    83  	// Write cert
    84  	err = ioutil.WriteFile(filepath.Join(dir, certName(name)), cert, 0644)
    85  	if err != nil {
    86  		return fmt.Errorf("error writing certificate: %v", err)
    87  	}
    88  	return nil
    89  }
    90  
    91  // CertKeyPairExists returns true if a key and matching certificate exist.
    92  // Matching is defined as having the expected file names. No validation
    93  // is performed on the actual bytes of the cert/key
    94  func CertKeyPairExists(name, dir string) (bool, error) {
    95  	kn := keyName(name)
    96  	var err error
    97  	if _, err = os.Stat(filepath.Join(dir, kn)); os.IsNotExist(err) {
    98  		return false, nil
    99  	}
   100  	if err != nil {
   101  		return false, err
   102  	}
   103  	cn := certName(name)
   104  	if _, err = os.Stat(filepath.Join(dir, cn)); os.IsNotExist(err) {
   105  		return false, nil
   106  	}
   107  	if err != nil {
   108  		return false, err
   109  	}
   110  	return true, nil
   111  }
   112  
   113  func keyName(s string) string { return fmt.Sprintf("%s-key.pem", s) }
   114  
   115  func certName(s string) string { return fmt.Sprintf("%s.pem", s) }
   116  
   117  // CreateDir check if directory exists and create it
   118  func CreateDir(dir string, perm os.FileMode) error {
   119  	if _, err := os.Stat(dir); os.IsNotExist(err) {
   120  		err := os.Mkdir(dir, perm)
   121  		if err != nil {
   122  			return fmt.Errorf("error creating destination dir: %v", err)
   123  		}
   124  	}
   125  
   126  	return nil
   127  }