github.com/openshift/installer@v1.4.17/pkg/asset/tls/certkey.go (about)

     1  package tls
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"crypto/rsa"
     7  	"crypto/x509"
     8  	"os"
     9  
    10  	"github.com/pkg/errors"
    11  	"github.com/sirupsen/logrus"
    12  
    13  	"github.com/openshift/installer/pkg/asset"
    14  )
    15  
    16  // CertInterface contains cert.
    17  type CertInterface interface {
    18  	// Cert returns the certificate.
    19  	Cert() []byte
    20  }
    21  
    22  // CertKeyInterface contains a private key and the associated cert.
    23  type CertKeyInterface interface {
    24  	CertInterface
    25  	// Key returns the private key.
    26  	Key() []byte
    27  }
    28  
    29  // CertKey contains the private key and the cert.
    30  type CertKey struct {
    31  	CertRaw  []byte
    32  	KeyRaw   []byte
    33  	FileList []*asset.File
    34  }
    35  
    36  // Cert returns the certificate.
    37  func (c *CertKey) Cert() []byte {
    38  	return c.CertRaw
    39  }
    40  
    41  // Key returns the private key.
    42  func (c *CertKey) Key() []byte {
    43  	return c.KeyRaw
    44  }
    45  
    46  // Files returns the files generated by the asset.
    47  func (c *CertKey) Files() []*asset.File {
    48  	return c.FileList
    49  }
    50  
    51  // CertFile returns the certificate file.
    52  func (c *CertKey) CertFile() *asset.File {
    53  	return c.FileList[1]
    54  }
    55  
    56  func (c *CertKey) generateFiles(filenameBase string) {
    57  	c.FileList = []*asset.File{
    58  		{
    59  			Filename: assetFilePath(filenameBase + ".key"),
    60  			Data:     c.KeyRaw,
    61  		},
    62  		{
    63  			Filename: assetFilePath(filenameBase + ".crt"),
    64  			Data:     c.CertRaw,
    65  		},
    66  	}
    67  }
    68  
    69  // Load is a no-op because TLS assets are not written to disk.
    70  func (c *CertKey) Load(asset.FileFetcher) (bool, error) {
    71  	return false, nil
    72  }
    73  
    74  func (c *CertKey) loadCertKey(f asset.FileFetcher, filenameBase string) (bool, error) {
    75  	if os.Getenv("OPENSHIFT_INSTALL_LOAD_CLUSTER_CERTS") != "true" {
    76  		return c.Load(f)
    77  	}
    78  
    79  	loadFile := func(suffix string) (*asset.File, error) {
    80  		file, err := f.FetchByName(assetFilePath(filenameBase + suffix))
    81  		if err != nil {
    82  			if os.IsNotExist(err) {
    83  				return nil, nil
    84  			}
    85  			return nil, err
    86  		}
    87  		return file, err
    88  	}
    89  
    90  	key, err := loadFile(".key")
    91  	if key == nil {
    92  		return false, err
    93  	}
    94  
    95  	cert, err := loadFile(".crt")
    96  	if cert == nil {
    97  		return false, err
    98  	}
    99  
   100  	c.KeyRaw = key.Data
   101  	c.CertRaw = cert.Data
   102  	c.FileList = []*asset.File{key, cert}
   103  
   104  	return true, nil
   105  }
   106  
   107  // AppendParentChoice dictates whether the parent's cert is to be added to the
   108  // cert.
   109  type AppendParentChoice bool
   110  
   111  const (
   112  	// AppendParent indicates that the parent's cert should be added.
   113  	AppendParent AppendParentChoice = true
   114  	// DoNotAppendParent indicates that the parent's cert should not be added.
   115  	DoNotAppendParent AppendParentChoice = false
   116  )
   117  
   118  // SignedCertKey contains the private key and the cert that's
   119  // signed by the parent CA.
   120  type SignedCertKey struct {
   121  	CertKey
   122  }
   123  
   124  // Generate generates a cert/key pair signed by the specified parent CA.
   125  func (c *SignedCertKey) Generate(_ context.Context,
   126  	cfg *CertCfg,
   127  	parentCA CertKeyInterface,
   128  	filenameBase string,
   129  	appendParent AppendParentChoice,
   130  ) error {
   131  	var key *rsa.PrivateKey
   132  	var crt *x509.Certificate
   133  	var err error
   134  
   135  	caKey, err := PemToPrivateKey(parentCA.Key())
   136  	if err != nil {
   137  		logrus.Debugf("Failed to parse RSA private key: %s", err)
   138  		return errors.Wrap(err, "failed to parse rsa private key")
   139  	}
   140  
   141  	caCert, err := PemToCertificate(parentCA.Cert())
   142  	if err != nil {
   143  		logrus.Debugf("Failed to parse x509 certificate: %s", err)
   144  		return errors.Wrap(err, "failed to parse x509 certificate")
   145  	}
   146  
   147  	key, crt, err = GenerateSignedCertificate(caKey, caCert, cfg)
   148  	if err != nil {
   149  		logrus.Debugf("Failed to generate signed cert/key pair: %s", err)
   150  		return errors.Wrap(err, "failed to generate signed cert/key pair")
   151  	}
   152  
   153  	c.KeyRaw = PrivateKeyToPem(key)
   154  	c.CertRaw = CertToPem(crt)
   155  
   156  	if appendParent {
   157  		c.CertRaw = bytes.Join([][]byte{c.CertRaw, CertToPem(caCert)}, []byte("\n"))
   158  	}
   159  
   160  	c.generateFiles(filenameBase)
   161  
   162  	return nil
   163  }
   164  
   165  // SelfSignedCertKey contains the private key and the cert that's self-signed.
   166  type SelfSignedCertKey struct {
   167  	CertKey
   168  }
   169  
   170  // Generate generates a cert/key pair signed by the specified parent CA.
   171  func (c *SelfSignedCertKey) Generate(_ context.Context,
   172  	cfg *CertCfg,
   173  	filenameBase string,
   174  ) error {
   175  	key, crt, err := GenerateSelfSignedCertificate(cfg)
   176  	if err != nil {
   177  		return errors.Wrap(err, "failed to generate self-signed cert/key pair")
   178  	}
   179  
   180  	c.KeyRaw = PrivateKeyToPem(key)
   181  	c.CertRaw = CertToPem(crt)
   182  
   183  	c.generateFiles(filenameBase)
   184  
   185  	return nil
   186  }