key_manager.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package libtrust
  2. import (
  3. "crypto/tls"
  4. "crypto/x509"
  5. "fmt"
  6. "io/ioutil"
  7. "net"
  8. "os"
  9. "path"
  10. "sync"
  11. )
  12. // ClientKeyManager manages client keys on the filesystem
  13. type ClientKeyManager struct {
  14. key PrivateKey
  15. clientFile string
  16. clientDir string
  17. clientLock sync.RWMutex
  18. clients []PublicKey
  19. configLock sync.Mutex
  20. configs []*tls.Config
  21. }
  22. // NewClientKeyManager loads a new manager from a set of key files
  23. // and managed by the given private key.
  24. func NewClientKeyManager(trustKey PrivateKey, clientFile, clientDir string) (*ClientKeyManager, error) {
  25. m := &ClientKeyManager{
  26. key: trustKey,
  27. clientFile: clientFile,
  28. clientDir: clientDir,
  29. }
  30. if err := m.loadKeys(); err != nil {
  31. return nil, err
  32. }
  33. // TODO Start watching file and directory
  34. return m, nil
  35. }
  36. func (c *ClientKeyManager) loadKeys() (err error) {
  37. // Load authorized keys file
  38. var clients []PublicKey
  39. if c.clientFile != "" {
  40. clients, err = LoadKeySetFile(c.clientFile)
  41. if err != nil {
  42. return fmt.Errorf("unable to load authorized keys: %s", err)
  43. }
  44. }
  45. // Add clients from authorized keys directory
  46. files, err := ioutil.ReadDir(c.clientDir)
  47. if err != nil && !os.IsNotExist(err) {
  48. return fmt.Errorf("unable to open authorized keys directory: %s", err)
  49. }
  50. for _, f := range files {
  51. if !f.IsDir() {
  52. publicKey, err := LoadPublicKeyFile(path.Join(c.clientDir, f.Name()))
  53. if err != nil {
  54. return fmt.Errorf("unable to load authorized key file: %s", err)
  55. }
  56. clients = append(clients, publicKey)
  57. }
  58. }
  59. c.clientLock.Lock()
  60. c.clients = clients
  61. c.clientLock.Unlock()
  62. return nil
  63. }
  64. // RegisterTLSConfig registers a tls configuration to manager
  65. // such that any changes to the keys may be reflected in
  66. // the tls client CA pool
  67. func (c *ClientKeyManager) RegisterTLSConfig(tlsConfig *tls.Config) error {
  68. c.clientLock.RLock()
  69. certPool, err := GenerateCACertPool(c.key, c.clients)
  70. if err != nil {
  71. return fmt.Errorf("CA pool generation error: %s", err)
  72. }
  73. c.clientLock.RUnlock()
  74. tlsConfig.ClientCAs = certPool
  75. c.configLock.Lock()
  76. c.configs = append(c.configs, tlsConfig)
  77. c.configLock.Unlock()
  78. return nil
  79. }
  80. // NewIdentityAuthTLSConfig creates a tls.Config for the server to use for
  81. // libtrust identity authentication for the domain specified
  82. func NewIdentityAuthTLSConfig(trustKey PrivateKey, clients *ClientKeyManager, addr string, domain string) (*tls.Config, error) {
  83. tlsConfig := newTLSConfig()
  84. tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
  85. if err := clients.RegisterTLSConfig(tlsConfig); err != nil {
  86. return nil, err
  87. }
  88. // Generate cert
  89. ips, domains, err := parseAddr(addr)
  90. if err != nil {
  91. return nil, err
  92. }
  93. // add domain that it expects clients to use
  94. domains = append(domains, domain)
  95. x509Cert, err := GenerateSelfSignedServerCert(trustKey, domains, ips)
  96. if err != nil {
  97. return nil, fmt.Errorf("certificate generation error: %s", err)
  98. }
  99. tlsConfig.Certificates = []tls.Certificate{{
  100. Certificate: [][]byte{x509Cert.Raw},
  101. PrivateKey: trustKey.CryptoPrivateKey(),
  102. Leaf: x509Cert,
  103. }}
  104. return tlsConfig, nil
  105. }
  106. // NewCertAuthTLSConfig creates a tls.Config for the server to use for
  107. // certificate authentication
  108. func NewCertAuthTLSConfig(caPath, certPath, keyPath string) (*tls.Config, error) {
  109. tlsConfig := newTLSConfig()
  110. cert, err := tls.LoadX509KeyPair(certPath, keyPath)
  111. if err != nil {
  112. return nil, fmt.Errorf("Couldn't load X509 key pair (%s, %s): %s. Key encrypted?", certPath, keyPath, err)
  113. }
  114. tlsConfig.Certificates = []tls.Certificate{cert}
  115. // Verify client certificates against a CA?
  116. if caPath != "" {
  117. certPool := x509.NewCertPool()
  118. file, err := ioutil.ReadFile(caPath)
  119. if err != nil {
  120. return nil, fmt.Errorf("Couldn't read CA certificate: %s", err)
  121. }
  122. certPool.AppendCertsFromPEM(file)
  123. tlsConfig.ClientAuth = tls.RequireAndVerifyClientCert
  124. tlsConfig.ClientCAs = certPool
  125. }
  126. return tlsConfig, nil
  127. }
  128. func newTLSConfig() *tls.Config {
  129. return &tls.Config{
  130. NextProtos: []string{"http/1.1"},
  131. // Avoid fallback on insecure SSL protocols
  132. MinVersion: tls.VersionTLS10,
  133. }
  134. }
  135. // parseAddr parses an address into an array of IPs and domains
  136. func parseAddr(addr string) ([]net.IP, []string, error) {
  137. host, _, err := net.SplitHostPort(addr)
  138. if err != nil {
  139. return nil, nil, err
  140. }
  141. var domains []string
  142. var ips []net.IP
  143. ip := net.ParseIP(host)
  144. if ip != nil {
  145. ips = []net.IP{ip}
  146. } else {
  147. domains = []string{host}
  148. }
  149. return ips, domains, nil
  150. }