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