config.go 3.2 KB

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