config.go 3.1 KB

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