config.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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. if os.IsNotExist(err) {
  47. return nil
  48. }
  49. fatal(err)
  50. }
  51. defer file.Close()
  52. info := &Info{}
  53. content, err := ioutil.ReadAll(file)
  54. if err != nil {
  55. fatalf("Unable to read info: %v", err)
  56. return nil
  57. }
  58. if err = json.Unmarshal(content, &info); err != nil {
  59. fatalf("Unable to parse info: %v", err)
  60. return nil
  61. }
  62. return info
  63. }
  64. func tlsConfigFromInfo(info TLSInfo) (t TLSConfig, ok bool) {
  65. var keyFile, certFile, CAFile string
  66. var tlsCert tls.Certificate
  67. var err error
  68. t.Scheme = "http"
  69. keyFile = info.KeyFile
  70. certFile = info.CertFile
  71. CAFile = info.CAFile
  72. // If the user do not specify key file, cert file and
  73. // CA file, the type will be HTTP
  74. if keyFile == "" && certFile == "" && CAFile == "" {
  75. return t, true
  76. }
  77. // both the key and cert must be present
  78. if keyFile == "" || certFile == "" {
  79. return t, false
  80. }
  81. tlsCert, err = tls.LoadX509KeyPair(certFile, keyFile)
  82. if err != nil {
  83. fatal(err)
  84. }
  85. t.Scheme = "https"
  86. t.Server.ClientAuth, t.Server.ClientCAs = newCertPool(CAFile)
  87. // The client should trust the RootCA that the Server uses since
  88. // everyone is a peer in the network.
  89. t.Client.Certificates = []tls.Certificate{tlsCert}
  90. t.Client.RootCAs = t.Server.ClientCAs
  91. return t, true
  92. }
  93. // newCertPool creates x509 certPool and corresponding Auth Type.
  94. // If the given CAfile is valid, add the cert into the pool and verify the clients'
  95. // certs against the cert in the pool.
  96. // If the given CAfile is empty, do not verify the clients' cert.
  97. // If the given CAfile is not valid, fatal.
  98. func newCertPool(CAFile string) (tls.ClientAuthType, *x509.CertPool) {
  99. if CAFile == "" {
  100. return tls.NoClientCert, nil
  101. }
  102. pemByte, err := ioutil.ReadFile(CAFile)
  103. check(err)
  104. block, pemByte := pem.Decode(pemByte)
  105. cert, err := x509.ParseCertificate(block.Bytes)
  106. check(err)
  107. certPool := x509.NewCertPool()
  108. certPool.AddCert(cert)
  109. return tls.RequireAndVerifyClientCert, certPool
  110. }