3
0

cert.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package nebula
  2. import (
  3. "errors"
  4. "fmt"
  5. "io/ioutil"
  6. "strings"
  7. "time"
  8. "github.com/slackhq/nebula/cert"
  9. )
  10. var trustedCAs *cert.NebulaCAPool
  11. type CertState struct {
  12. certificate *cert.NebulaCertificate
  13. rawCertificate []byte
  14. rawCertificateNoKey []byte
  15. publicKey []byte
  16. privateKey []byte
  17. }
  18. func NewCertState(certificate *cert.NebulaCertificate, privateKey []byte) (*CertState, error) {
  19. // Marshal the certificate to ensure it is valid
  20. rawCertificate, err := certificate.Marshal()
  21. if err != nil {
  22. return nil, fmt.Errorf("invalid nebula certificate on interface: %s", err)
  23. }
  24. publicKey := certificate.Details.PublicKey
  25. cs := &CertState{
  26. rawCertificate: rawCertificate,
  27. certificate: certificate, // PublicKey has been set to nil above
  28. privateKey: privateKey,
  29. publicKey: publicKey,
  30. }
  31. cs.certificate.Details.PublicKey = nil
  32. rawCertNoKey, err := cs.certificate.Marshal()
  33. if err != nil {
  34. return nil, fmt.Errorf("error marshalling certificate no key: %s", err)
  35. }
  36. cs.rawCertificateNoKey = rawCertNoKey
  37. // put public key back
  38. cs.certificate.Details.PublicKey = cs.publicKey
  39. return cs, nil
  40. }
  41. func NewCertStateFromConfig(c *Config) (*CertState, error) {
  42. var pemPrivateKey []byte
  43. var err error
  44. privPathOrPEM := c.GetString("pki.key", "")
  45. if privPathOrPEM == "" {
  46. // Support backwards compat with the old x509
  47. //TODO: remove after this is rolled out everywhere - NB 2018/02/23
  48. privPathOrPEM = c.GetString("x509.key", "")
  49. }
  50. if privPathOrPEM == "" {
  51. return nil, errors.New("no pki.key path or PEM data provided")
  52. }
  53. if strings.Contains(privPathOrPEM, "-----BEGIN") {
  54. pemPrivateKey = []byte(privPathOrPEM)
  55. privPathOrPEM = "<inline>"
  56. } else {
  57. pemPrivateKey, err = ioutil.ReadFile(privPathOrPEM)
  58. if err != nil {
  59. return nil, fmt.Errorf("unable to read pki.key file %s: %s", privPathOrPEM, err)
  60. }
  61. }
  62. rawKey, _, err := cert.UnmarshalX25519PrivateKey(pemPrivateKey)
  63. if err != nil {
  64. return nil, fmt.Errorf("error while unmarshaling pki.key %s: %s", privPathOrPEM, err)
  65. }
  66. var rawCert []byte
  67. pubPathOrPEM := c.GetString("pki.cert", "")
  68. if pubPathOrPEM == "" {
  69. // Support backwards compat with the old x509
  70. //TODO: remove after this is rolled out everywhere - NB 2018/02/23
  71. pubPathOrPEM = c.GetString("x509.cert", "")
  72. }
  73. if pubPathOrPEM == "" {
  74. return nil, errors.New("no pki.cert path or PEM data provided")
  75. }
  76. if strings.Contains(pubPathOrPEM, "-----BEGIN") {
  77. rawCert = []byte(pubPathOrPEM)
  78. pubPathOrPEM = "<inline>"
  79. } else {
  80. rawCert, err = ioutil.ReadFile(pubPathOrPEM)
  81. if err != nil {
  82. return nil, fmt.Errorf("unable to read pki.cert file %s: %s", pubPathOrPEM, err)
  83. }
  84. }
  85. nebulaCert, _, err := cert.UnmarshalNebulaCertificateFromPEM(rawCert)
  86. if err != nil {
  87. return nil, fmt.Errorf("error while unmarshaling pki.cert %s: %s", pubPathOrPEM, err)
  88. }
  89. if nebulaCert.Expired(time.Now()) {
  90. return nil, fmt.Errorf("nebula certificate for this host is expired")
  91. }
  92. if len(nebulaCert.Details.Ips) == 0 {
  93. return nil, fmt.Errorf("no IPs encoded in certificate")
  94. }
  95. if err = nebulaCert.VerifyPrivateKey(rawKey); err != nil {
  96. return nil, fmt.Errorf("private key is not a pair with public key in nebula cert")
  97. }
  98. return NewCertState(nebulaCert, rawKey)
  99. }
  100. func loadCAFromConfig(c *Config) (*cert.NebulaCAPool, error) {
  101. var rawCA []byte
  102. var err error
  103. caPathOrPEM := c.GetString("pki.ca", "")
  104. if caPathOrPEM == "" {
  105. // Support backwards compat with the old x509
  106. //TODO: remove after this is rolled out everywhere - NB 2018/02/23
  107. caPathOrPEM = c.GetString("x509.ca", "")
  108. }
  109. if caPathOrPEM == "" {
  110. return nil, errors.New("no pki.ca path or PEM data provided")
  111. }
  112. if strings.Contains(caPathOrPEM, "-----BEGIN") {
  113. rawCA = []byte(caPathOrPEM)
  114. caPathOrPEM = "<inline>"
  115. } else {
  116. rawCA, err = ioutil.ReadFile(caPathOrPEM)
  117. if err != nil {
  118. return nil, fmt.Errorf("unable to read pki.ca file %s: %s", caPathOrPEM, err)
  119. }
  120. }
  121. CAs, err := cert.NewCAPoolFromBytes(rawCA)
  122. if err != nil {
  123. return nil, fmt.Errorf("error while adding CA certificate to CA trust store: %s", err)
  124. }
  125. // pki.blacklist entered the scene at about the same time we aliased x509 to pki, not supporting backwards compat
  126. for _, fp := range c.GetStringSlice("pki.blacklist", []string{}) {
  127. l.WithField("fingerprint", fp).Infof("Blacklisting cert")
  128. CAs.BlacklistFingerprint(fp)
  129. }
  130. return CAs, nil
  131. }