tls_info.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. package server
  2. import (
  3. "crypto/tls"
  4. "crypto/x509"
  5. "encoding/pem"
  6. "fmt"
  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. func (info TLSInfo) Scheme() string {
  16. if info.KeyFile != "" && info.CertFile != "" {
  17. return "https"
  18. } else {
  19. return "http"
  20. }
  21. }
  22. // Generates a tls.Config object for a server from the given files.
  23. func (info TLSInfo) ServerConfig() (*tls.Config, error) {
  24. // Both the key and cert must be present.
  25. if info.KeyFile == "" || info.CertFile == "" {
  26. return nil, fmt.Errorf("KeyFile and CertFile must both be present[key: %v, cert: %v]", info.KeyFile, info.CertFile)
  27. }
  28. var cfg tls.Config
  29. tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
  30. if err != nil {
  31. return nil, err
  32. }
  33. cfg.Certificates = []tls.Certificate{tlsCert}
  34. if info.CAFile != "" {
  35. cfg.ClientAuth = tls.RequireAndVerifyClientCert
  36. cp, err := newCertPool(info.CAFile)
  37. if err != nil {
  38. return nil, err
  39. }
  40. cfg.RootCAs = cp
  41. cfg.ClientCAs = cp
  42. } else {
  43. cfg.ClientAuth = tls.NoClientCert
  44. }
  45. return &cfg, nil
  46. }
  47. // Generates a tls.Config object for a client from the given files.
  48. func (info TLSInfo) ClientConfig() (*tls.Config, error) {
  49. var cfg tls.Config
  50. if info.KeyFile == "" || info.CertFile == "" {
  51. return &cfg, nil
  52. }
  53. tlsCert, err := tls.LoadX509KeyPair(info.CertFile, info.KeyFile)
  54. if err != nil {
  55. return nil, err
  56. }
  57. cfg.Certificates = []tls.Certificate{tlsCert}
  58. if info.CAFile != "" {
  59. cp, err := newCertPool(info.CAFile)
  60. if err != nil {
  61. return nil, err
  62. }
  63. cfg.RootCAs = cp
  64. }
  65. return &cfg, nil
  66. }
  67. // newCertPool creates x509 certPool with provided CA file
  68. func newCertPool(CAFile string) (*x509.CertPool, error) {
  69. certPool := x509.NewCertPool()
  70. pemByte, err := ioutil.ReadFile(CAFile)
  71. if err != nil {
  72. return nil, err
  73. }
  74. for {
  75. var block *pem.Block
  76. block, pemByte = pem.Decode(pemByte)
  77. if block == nil {
  78. return certPool, nil
  79. }
  80. cert, err := x509.ParseCertificate(block.Bytes)
  81. if err != nil {
  82. return nil, err
  83. }
  84. certPool.AddCert(cert)
  85. }
  86. }