config.go 3.0 KB

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