tls_info.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package server
  2. import (
  3. "crypto/tls"
  4. "crypto/x509"
  5. "encoding/pem"
  6. "errors"
  7. "io/ioutil"
  8. )
  9. // TLSInfo holds the SSL certificates paths.
  10. type TLSInfo struct {
  11. CertFile string `json:"CertFile"`
  12. KeyFile string `json:"KeyFile"`
  13. CAFile string `json:"CAFile"`
  14. }
  15. // Generates a TLS configuration from the given files.
  16. func (info TLSInfo) Config() (TLSConfig, error) {
  17. var t TLSConfig
  18. t.Scheme = "http"
  19. // If the user do not specify key file, cert file and CA file, the type will be HTTP
  20. if info.KeyFile == "" && info.CertFile == "" && info.CAFile == "" {
  21. return t, nil
  22. }
  23. // Both the key and cert must be present.
  24. if info.KeyFile == "" || info.CertFile == "" {
  25. return t, errors.New("KeyFile and CertFile must both be present")
  26. }
  27. tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
  28. if err != nil {
  29. return t, err
  30. }
  31. t.Scheme = "https"
  32. t.Server.ClientAuth, t.Server.ClientCAs, err = newCertPool(info.CAFile)
  33. if err != nil {
  34. return t, err
  35. }
  36. // The client should trust the RootCA that the Server uses since
  37. // everyone is a peer in the network.
  38. t.Client.Certificates = []tls.Certificate{tlsCert}
  39. t.Client.RootCAs = t.Server.ClientCAs
  40. return t, nil
  41. }
  42. // newCertPool creates x509 certPool and corresponding Auth Type.
  43. // If the given CAfile is valid, add the cert into the pool and verify the clients'
  44. // certs against the cert in the pool.
  45. // If the given CAfile is empty, do not verify the clients' cert.
  46. // If the given CAfile is not valid, fatal.
  47. func newCertPool(CAFile string) (tls.ClientAuthType, *x509.CertPool, error) {
  48. if CAFile == "" {
  49. return tls.NoClientCert, nil, nil
  50. }
  51. pemByte, err := ioutil.ReadFile(CAFile)
  52. if err != nil {
  53. return 0, nil, err
  54. }
  55. block, pemByte := pem.Decode(pemByte)
  56. cert, err := x509.ParseCertificate(block.Bytes)
  57. if err != nil {
  58. return 0, nil, err
  59. }
  60. certPool := x509.NewCertPool()
  61. certPool.AddCert(cert)
  62. return tls.RequireAndVerifyClientCert, certPool, nil
  63. }