github.com/ghodss/etcd@v0.3.1-0.20140417172404-cc329bfa55cb/server/tls_info.go (about)

     1  package server
     2  
     3  import (
     4  	"crypto/tls"
     5  	"crypto/x509"
     6  	"encoding/pem"
     7  	"fmt"
     8  	"io/ioutil"
     9  )
    10  
    11  // TLSInfo holds the SSL certificates paths.
    12  type TLSInfo struct {
    13  	CertFile string `json:"CertFile"`
    14  	KeyFile  string `json:"KeyFile"`
    15  	CAFile   string `json:"CAFile"`
    16  }
    17  
    18  func (info TLSInfo) Scheme() string {
    19  	if info.KeyFile != "" && info.CertFile != "" {
    20  		return "https"
    21  	} else {
    22  		return "http"
    23  	}
    24  }
    25  
    26  // Generates a tls.Config object for a server from the given files.
    27  func (info TLSInfo) ServerConfig() (*tls.Config, error) {
    28  	// Both the key and cert must be present.
    29  	if info.KeyFile == "" || info.CertFile == "" {
    30  		return nil, fmt.Errorf("KeyFile and CertFile must both be present[key: %v, cert: %v]", info.KeyFile, info.CertFile)
    31  	}
    32  
    33  	var cfg tls.Config
    34  
    35  	tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  
    40  	cfg.Certificates = []tls.Certificate{tlsCert}
    41  
    42  	if info.CAFile != "" {
    43  		cfg.ClientAuth = tls.RequireAndVerifyClientCert
    44  		cp, err := newCertPool(info.CAFile)
    45  		if err != nil {
    46  			return nil, err
    47  		}
    48  
    49  		cfg.RootCAs = cp
    50  		cfg.ClientCAs = cp
    51  	} else {
    52  		cfg.ClientAuth = tls.NoClientCert
    53  	}
    54  
    55  	return &cfg, nil
    56  }
    57  
    58  // Generates a tls.Config object for a client from the given files.
    59  func (info TLSInfo) ClientConfig() (*tls.Config, error) {
    60  	var cfg tls.Config
    61  
    62  	if info.KeyFile == "" || info.CertFile == "" {
    63  		return &cfg, nil
    64  	}
    65  
    66  	tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  
    71  	cfg.Certificates = []tls.Certificate{tlsCert}
    72  
    73  	if info.CAFile != "" {
    74  		cp, err := newCertPool(info.CAFile)
    75  		if err != nil {
    76  			return nil, err
    77  		}
    78  
    79  		cfg.RootCAs = cp
    80  	}
    81  
    82  	return &cfg, nil
    83  }
    84  
    85  // newCertPool creates x509 certPool with provided CA file
    86  func newCertPool(CAFile string) (*x509.CertPool, error) {
    87  	certPool := x509.NewCertPool()
    88  	pemByte, err := ioutil.ReadFile(CAFile)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  
    93  	for {
    94  		var block *pem.Block
    95  		block, pemByte = pem.Decode(pemByte)
    96  		if block == nil {
    97  			return certPool, nil
    98  		}
    99  		cert, err := x509.ParseCertificate(block.Bytes)
   100  		if err != nil {
   101  			return nil, err
   102  		}
   103  		certPool.AddCert(cert)
   104  	}
   105  
   106  }