github.com/blend/go-sdk@v1.20220411.3/certutil/key_pair.go (about)

     1  /*
     2  
     3  Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package certutil
     9  
    10  import (
    11  	"crypto/tls"
    12  	"crypto/x509"
    13  	"os"
    14  
    15  	"github.com/blend/go-sdk/ex"
    16  )
    17  
    18  // NewKeyPairFromPaths returns a key pair from paths.
    19  func NewKeyPairFromPaths(certPath, keyPath string) KeyPair {
    20  	return KeyPair{CertPath: certPath, KeyPath: keyPath}
    21  }
    22  
    23  // KeyPair is an x509 pem key pair as strings.
    24  type KeyPair struct {
    25  	Cert     string `json:"cert,omitempty" yaml:"cert,omitempty"`
    26  	CertPath string `json:"certPath,omitempty" yaml:"certPath,omitempty"`
    27  	Key      string `json:"key,omitempty" yaml:"key,omitempty"`
    28  	KeyPath  string `json:"keyPath,omitempty" yaml:"keyPath,omitempty"`
    29  }
    30  
    31  // IsZero returns if the key pair is set or not.
    32  func (kp KeyPair) IsZero() bool {
    33  	return kp.Cert == "" &&
    34  		kp.Key == "" &&
    35  		kp.CertPath == "" &&
    36  		kp.KeyPath == ""
    37  }
    38  
    39  // IsCertPath returns if the keypair cert is a path.
    40  func (kp KeyPair) IsCertPath() bool {
    41  	return kp.Cert == "" && kp.CertPath != ""
    42  }
    43  
    44  // IsKeyPath returns if the keypair key is a path.
    45  func (kp KeyPair) IsKeyPath() bool {
    46  	return kp.Key == "" && kp.KeyPath != ""
    47  }
    48  
    49  // CertBytes returns the key pair cert bytes.
    50  func (kp KeyPair) CertBytes() ([]byte, error) {
    51  	if kp.Cert != "" {
    52  		return []byte(kp.Cert), nil
    53  	}
    54  	if kp.CertPath == "" {
    55  		return nil, ex.New("error loading cert; cert path unset")
    56  	}
    57  	contents, err := os.ReadFile(os.ExpandEnv(kp.CertPath))
    58  	if err != nil {
    59  		return nil, ex.New("error loading cert from path", ex.OptInner(err), ex.OptMessage(kp.CertPath))
    60  	}
    61  	return contents, nil
    62  }
    63  
    64  // KeyBytes returns the key pair key bytes.
    65  func (kp KeyPair) KeyBytes() ([]byte, error) {
    66  	if kp.Key != "" {
    67  		return []byte(kp.Key), nil
    68  	}
    69  	if kp.KeyPath == "" {
    70  		return nil, ex.New("error loading key; key path unset")
    71  	}
    72  	contents, err := os.ReadFile(os.ExpandEnv(kp.KeyPath))
    73  	if err != nil {
    74  		return nil, ex.New("error loading key from path", ex.OptInner(err), ex.OptMessage(kp.KeyPath))
    75  	}
    76  	return contents, nil
    77  }
    78  
    79  // String returns a string representation of the key pair.
    80  func (kp KeyPair) String() (output string) {
    81  	output = "[ "
    82  	if kp.Cert != "" {
    83  		output += "cert: <literal>"
    84  	} else if kp.CertPath != "" {
    85  		output += ("cert: " + os.ExpandEnv(kp.CertPath))
    86  	}
    87  	if kp.Key != "" {
    88  		output += ", key: <literal>"
    89  	} else if kp.KeyPath != "" {
    90  		output += (", key: " + os.ExpandEnv(kp.KeyPath))
    91  	}
    92  	output += " ]"
    93  	return output
    94  }
    95  
    96  // TLSCertificate returns the KeyPair as a tls.Certificate.
    97  func (kp KeyPair) TLSCertificate() (*tls.Certificate, error) {
    98  	certBytes, err := kp.CertBytes()
    99  	if err != nil {
   100  		return nil, ex.New(err)
   101  	}
   102  	keyBytes, err := kp.KeyBytes()
   103  	if err != nil {
   104  		return nil, ex.New(err)
   105  	}
   106  	cert, err := tls.X509KeyPair(certBytes, keyBytes)
   107  	if err != nil {
   108  		return nil, ex.New(err)
   109  	}
   110  	return &cert, nil
   111  }
   112  
   113  // TLSCertificateWithLeaf returns the KeyPair as a tls.Certificate.
   114  func (kp KeyPair) TLSCertificateWithLeaf() (*tls.Certificate, error) {
   115  	cert, err := kp.TLSCertificate()
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	if len(cert.Certificate) == 0 {
   120  		return nil, ex.New("invalid certificate; empty certificate list")
   121  	}
   122  	if cert.Leaf == nil {
   123  		cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
   124  		if err != nil {
   125  			return nil, ex.New(err)
   126  		}
   127  	}
   128  	return cert, nil
   129  }