tls.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package serverctl
  2. import (
  3. "crypto/ed25519"
  4. ssl "crypto/tls"
  5. "crypto/x509"
  6. "encoding/json"
  7. "encoding/pem"
  8. "errors"
  9. "fmt"
  10. "github.com/gravitl/netmaker/database"
  11. "github.com/gravitl/netmaker/tls"
  12. )
  13. // TlsConfig - holds this servers TLS conf in memory
  14. var TlsConfig ssl.Config
  15. // SaveCert - save a certificate to file and DB
  16. func SaveCert(path, name string, cert *x509.Certificate) error {
  17. if err := SaveCertToDB(name, cert); err != nil {
  18. return err
  19. }
  20. return tls.SaveCertToFile(path, name, cert)
  21. }
  22. // SaveCertToDB - save a certificate to the certs database
  23. func SaveCertToDB(name string, cert *x509.Certificate) error {
  24. if certBytes := pem.EncodeToMemory(&pem.Block{
  25. Type: "CERTIFICATE",
  26. Bytes: cert.Raw,
  27. }); len(certBytes) > 0 {
  28. data, err := json.Marshal(&certBytes)
  29. if err != nil {
  30. return fmt.Errorf("failed to marshal certificate - %v ", err)
  31. }
  32. return database.Insert(name, string(data), database.CERTS_TABLE_NAME)
  33. } else {
  34. return fmt.Errorf("failed to write cert to DB - %s ", name)
  35. }
  36. }
  37. // SaveKey - save a private key (ed25519) to file and DB
  38. func SaveKey(path, name string, key ed25519.PrivateKey) error {
  39. if err := SaveKeyToDB(name, key); err != nil {
  40. return err
  41. }
  42. return tls.SaveKeyToFile(path, name, key)
  43. }
  44. // SaveKeyToDB - save a private key (ed25519) to the specified path
  45. func SaveKeyToDB(name string, key ed25519.PrivateKey) error {
  46. privBytes, err := x509.MarshalPKCS8PrivateKey(key)
  47. if err != nil {
  48. return fmt.Errorf("failed to marshal key %v ", err)
  49. }
  50. if pemBytes := pem.EncodeToMemory(&pem.Block{
  51. Type: "PRIVATE KEY",
  52. Bytes: privBytes,
  53. }); len(pemBytes) > 0 {
  54. data, err := json.Marshal(&pemBytes)
  55. if err != nil {
  56. return fmt.Errorf("failed to marshal key %v ", err)
  57. }
  58. return database.Insert(name, string(data), database.CERTS_TABLE_NAME)
  59. } else {
  60. return fmt.Errorf("failed to write key to DB - %v ", err)
  61. }
  62. }
  63. // ReadCertFromDB - reads a certificate from the database
  64. func ReadCertFromDB(name string) (*x509.Certificate, error) {
  65. certString, err := database.FetchRecord(database.CERTS_TABLE_NAME, name)
  66. if err != nil {
  67. return nil, fmt.Errorf("unable to read file %w", err)
  68. }
  69. var certBytes []byte
  70. if err = json.Unmarshal([]byte(certString), &certBytes); err != nil {
  71. return nil, fmt.Errorf("unable to unmarshal db cert %w", err)
  72. }
  73. block, _ := pem.Decode(certBytes)
  74. if block == nil || block.Type != "CERTIFICATE" {
  75. return nil, errors.New("not a cert " + block.Type)
  76. }
  77. cert, err := x509.ParseCertificate(block.Bytes)
  78. if err != nil {
  79. return nil, fmt.Errorf("unable to parse cert %w", err)
  80. }
  81. return cert, nil
  82. }
  83. // ReadKeyFromDB - reads a private key (ed25519) from the database
  84. func ReadKeyFromDB(name string) (*ed25519.PrivateKey, error) {
  85. keyString, err := database.FetchRecord(database.CERTS_TABLE_NAME, name)
  86. if err != nil {
  87. return nil, fmt.Errorf("unable to read key value from db - %w", err)
  88. }
  89. var bytes []byte
  90. if err = json.Unmarshal([]byte(keyString), &bytes); err != nil {
  91. return nil, fmt.Errorf("unable to unmarshal db key - %w", err)
  92. }
  93. keyBytes, _ := pem.Decode(bytes)
  94. key, err := x509.ParsePKCS8PrivateKey(keyBytes.Bytes)
  95. if err != nil {
  96. return nil, fmt.Errorf("unable to parse key from DB - %w", err)
  97. }
  98. private := key.(ed25519.PrivateKey)
  99. return &private, nil
  100. }
  101. // SetClientTLSConf - saves client cert for servers to connect to MQ broker with
  102. func SetClientTLSConf(serverClientPemPath, serverClientKeyPath string, ca *x509.Certificate) error {
  103. certpool := x509.NewCertPool()
  104. if caData := pem.EncodeToMemory(&pem.Block{
  105. Type: "CERTIFICATE",
  106. Bytes: ca.Raw,
  107. }); len(caData) <= 0 {
  108. return fmt.Errorf("could not encode CA cert to memory for server client")
  109. } else {
  110. ok := certpool.AppendCertsFromPEM(caData)
  111. if !ok {
  112. return fmt.Errorf("failed to append root cert to server client cert")
  113. }
  114. }
  115. clientKeyPair, err := ssl.LoadX509KeyPair(serverClientPemPath, serverClientKeyPath)
  116. if err != nil {
  117. return err
  118. }
  119. certs := []ssl.Certificate{clientKeyPair}
  120. TlsConfig = ssl.Config{
  121. RootCAs: certpool,
  122. ClientAuth: ssl.NoClientCert,
  123. ClientCAs: nil,
  124. Certificates: certs,
  125. InsecureSkipVerify: false,
  126. }
  127. return nil
  128. }