github.com/soulinfo/etcd@v0.1.2-0.20130922053317-3a0a8c89e859/config.go (about) 1 package main 2 3 import ( 4 "crypto/tls" 5 "crypto/x509" 6 "encoding/json" 7 "encoding/pem" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 ) 12 13 //-------------------------------------- 14 // Config 15 //-------------------------------------- 16 17 // Get the server info from previous conf file 18 // or from the user 19 func getInfo(path string) *Info { 20 21 infoPath := filepath.Join(path, "info") 22 23 if force { 24 // Delete the old configuration if exist 25 logPath := filepath.Join(path, "log") 26 confPath := filepath.Join(path, "conf") 27 snapshotPath := filepath.Join(path, "snapshot") 28 os.Remove(infoPath) 29 os.Remove(logPath) 30 os.Remove(confPath) 31 os.RemoveAll(snapshotPath) 32 } else if info := readInfo(infoPath); info != nil { 33 infof("Found node configuration in '%s'. Ignoring flags", infoPath) 34 return info 35 } 36 37 // Read info from command line 38 info := &argInfo 39 40 // Write to file. 41 content, _ := json.MarshalIndent(info, "", " ") 42 content = []byte(string(content) + "\n") 43 if err := ioutil.WriteFile(infoPath, content, 0644); err != nil { 44 fatalf("Unable to write info to file: %v", err) 45 } 46 47 infof("Wrote node configuration to '%s'", infoPath) 48 49 return info 50 } 51 52 // readInfo reads from info file and decode to Info struct 53 func readInfo(path string) *Info { 54 file, err := os.Open(path) 55 56 if err != nil { 57 if os.IsNotExist(err) { 58 return nil 59 } 60 fatal(err) 61 } 62 defer file.Close() 63 64 info := &Info{} 65 66 content, err := ioutil.ReadAll(file) 67 if err != nil { 68 fatalf("Unable to read info: %v", err) 69 return nil 70 } 71 72 if err = json.Unmarshal(content, &info); err != nil { 73 fatalf("Unable to parse info: %v", err) 74 return nil 75 } 76 77 return info 78 } 79 80 func tlsConfigFromInfo(info TLSInfo) (t TLSConfig, ok bool) { 81 var keyFile, certFile, CAFile string 82 var tlsCert tls.Certificate 83 var err error 84 85 t.Scheme = "http" 86 87 keyFile = info.KeyFile 88 certFile = info.CertFile 89 CAFile = info.CAFile 90 91 // If the user do not specify key file, cert file and 92 // CA file, the type will be HTTP 93 if keyFile == "" && certFile == "" && CAFile == "" { 94 return t, true 95 } 96 97 // both the key and cert must be present 98 if keyFile == "" || certFile == "" { 99 return t, false 100 } 101 102 tlsCert, err = tls.LoadX509KeyPair(certFile, keyFile) 103 if err != nil { 104 fatal(err) 105 } 106 107 t.Scheme = "https" 108 t.Server.ClientAuth, t.Server.ClientCAs = newCertPool(CAFile) 109 110 // The client should trust the RootCA that the Server uses since 111 // everyone is a peer in the network. 112 t.Client.Certificates = []tls.Certificate{tlsCert} 113 t.Client.RootCAs = t.Server.ClientCAs 114 115 return t, true 116 } 117 118 // newCertPool creates x509 certPool and corresponding Auth Type. 119 // If the given CAfile is valid, add the cert into the pool and verify the clients' 120 // certs against the cert in the pool. 121 // If the given CAfile is empty, do not verify the clients' cert. 122 // If the given CAfile is not valid, fatal. 123 func newCertPool(CAFile string) (tls.ClientAuthType, *x509.CertPool) { 124 if CAFile == "" { 125 return tls.NoClientCert, nil 126 } 127 pemByte, err := ioutil.ReadFile(CAFile) 128 check(err) 129 130 block, pemByte := pem.Decode(pemByte) 131 132 cert, err := x509.ParseCertificate(block.Bytes) 133 check(err) 134 135 certPool := x509.NewCertPool() 136 137 certPool.AddCert(cert) 138 139 return tls.RequireAndVerifyClientCert, certPool 140 }