SSH Certificate Authority Toolkit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
4.1 KiB

4 years ago
  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "net"
  6. "os"
  7. "os/user"
  8. "path/filepath"
  9. "regexp"
  10. "time"
  11. "github.com/jinzhu/configor"
  12. "github.com/urfave/cli"
  13. )
  14. // Configuration Structure.
  15. type Config struct {
  16. BindAddr string `default:""`
  17. Port uint `default:"7789"`
  18. KeyDefaults struct {
  19. Type string `default:"OKP"`
  20. Curve string `default:"Ed25519"`
  21. Size int `default:"2048"`
  22. }
  23. Evironments []struct {
  24. Name string `required:"true"`
  25. CAKeyFile string `required:"true"`
  26. SystemGroup string
  27. APIServer bool `default:"false"`
  28. APIKey string
  29. APIWhitelist []string
  30. HostKey bool `default:"false"`
  31. UserKey bool `default:"false"`
  32. SignOptions struct {
  33. KeyID string `default:"USERNAME"`
  34. AllowAPIOverrideKeyID bool `default:"false"`
  35. ValidPrincipals []string
  36. AllowAPIOverrideValidPrincipals bool `default:"false"`
  37. Options map[string]string
  38. AllowAPIOverrideOptions bool `default:"false"`
  39. Extensions map[string]string
  40. AllowAPIOverrideExtensions bool `default:"false"`
  41. Duration time.Duration `default:"3600"`
  42. AllowAPIOverrideDuration bool `default:"false"`
  43. }
  44. }
  45. }
  46. // Load the configuration.
  47. func initConfig(c *cli.Context) Config {
  48. usr, err := user.Current()
  49. if err != nil {
  50. log.Fatal(err)
  51. }
  52. // Configuration paths.
  53. localConfig, _ := filepath.Abs("./config.json")
  54. homeDirConfig := usr.HomeDir + "/.config/ssh-ca/config.json"
  55. etcConfig := "/etc/ssh-ca/config.json"
  56. // Determine which configuration to use.
  57. var configFile string
  58. if _, err := os.Stat(c.String("config")); err == nil {
  59. configFile = c.String("config")
  60. } else if _, err := os.Stat(localConfig); err == nil {
  61. configFile = localConfig
  62. } else if _, err := os.Stat(homeDirConfig); err == nil {
  63. configFile = homeDirConfig
  64. } else if _, err := os.Stat(etcConfig); err == nil {
  65. configFile = etcConfig
  66. } else {
  67. log.Fatal("Unable to find a configuration file.")
  68. }
  69. // Load the configuration file.
  70. config := Config{}
  71. err = configor.Load(&config, configFile)
  72. if config.Port == 0 {
  73. fmt.Println(err)
  74. log.Fatal("Unable to load the configuration file.")
  75. }
  76. return config
  77. }
  78. // Flags for the server command.
  79. func configTestFlags() []cli.Flag {
  80. return []cli.Flag{}
  81. }
  82. func configTest(c *cli.Context) error {
  83. config := initConfig(c)
  84. foundError := false
  85. if config.BindAddr != "" && net.ParseIP(config.BindAddr) == nil {
  86. fmt.Println("Invalid bind address.")
  87. foundError = true
  88. }
  89. if config.Port > 65535 {
  90. fmt.Println("Invalid port number.")
  91. foundError = true
  92. }
  93. switch config.KeyDefaults.Type {
  94. case "EC":
  95. switch config.KeyDefaults.Curve {
  96. case "P-256":
  97. case "P-384":
  98. case "P-521":
  99. // We are valid.
  100. break
  101. default:
  102. fmt.Println("Invalid curve setting in KeyDefaults.")
  103. foundError = true
  104. }
  105. break
  106. case "RSA":
  107. switch config.KeyDefaults.Size {
  108. case 512:
  109. case 1024:
  110. case 2048:
  111. case 4096:
  112. case 8192:
  113. case 16384:
  114. // We are valid.
  115. break
  116. default:
  117. fmt.Println("Invalid size setting in KeyDefaults.")
  118. foundError = true
  119. }
  120. break
  121. case "OKP":
  122. if config.KeyDefaults.Curve != "Ed25519" {
  123. fmt.Println("Invalid curve setting in KeyDefaults.")
  124. foundError = true
  125. }
  126. break
  127. case "oct":
  128. // We are valid.
  129. break
  130. default:
  131. fmt.Println("Invalid key type in KeyDefaults.")
  132. foundError = true
  133. }
  134. var validName = regexp.MustCompile(`^[a-zA-Z0-9_-]+$`)
  135. for _, environment := range config.Evironments {
  136. if !validName.MatchString(environment.Name) {
  137. fmt.Println("Invalid environment name:", environment.Name)
  138. foundError = true
  139. }
  140. if environment.SystemGroup != "" && !validName.MatchString(environment.SystemGroup) {
  141. fmt.Println("Invalid environment system group:", environment.SystemGroup)
  142. foundError = true
  143. }
  144. if _, err := os.Stat(environment.CAKeyFile); err != nil {
  145. fmt.Println("Key file does not exist:", environment.CAKeyFile)
  146. foundError = true
  147. }
  148. }
  149. if !foundError {
  150. fmt.Println("All configurations appear to be fine.")
  151. }
  152. return nil
  153. }