github.com/matm/etcd@v0.3.1-0.20140328024009-5b4a473f1453/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 }