config.go 3.7 KB

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