cert_test.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. package cert
  2. import (
  3. "crypto/rand"
  4. "fmt"
  5. "io"
  6. "net"
  7. "testing"
  8. "time"
  9. "github.com/golang/protobuf/proto"
  10. "github.com/stretchr/testify/assert"
  11. "golang.org/x/crypto/curve25519"
  12. "golang.org/x/crypto/ed25519"
  13. )
  14. func TestMarshalingNebulaCertificate(t *testing.T) {
  15. before := time.Now().Add(time.Second * -60).Round(time.Second)
  16. after := time.Now().Add(time.Second * 60).Round(time.Second)
  17. pubKey := []byte("1234567890abcedfghij1234567890ab")
  18. nc := NebulaCertificate{
  19. Details: NebulaCertificateDetails{
  20. Name: "testing",
  21. Ips: []*net.IPNet{
  22. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  23. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  24. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  25. },
  26. Subnets: []*net.IPNet{
  27. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  28. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  29. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  30. },
  31. Groups: []string{"test-group1", "test-group2", "test-group3"},
  32. NotBefore: before,
  33. NotAfter: after,
  34. PublicKey: pubKey,
  35. IsCA: false,
  36. Issuer: "1234567890abcedfghij1234567890ab",
  37. },
  38. Signature: []byte("1234567890abcedfghij1234567890ab"),
  39. }
  40. b, err := nc.Marshal()
  41. assert.Nil(t, err)
  42. //t.Log("Cert size:", len(b))
  43. nc2, err := UnmarshalNebulaCertificate(b)
  44. assert.Nil(t, err)
  45. assert.Equal(t, nc.Signature, nc2.Signature)
  46. assert.Equal(t, nc.Details.Name, nc2.Details.Name)
  47. assert.Equal(t, nc.Details.NotBefore, nc2.Details.NotBefore)
  48. assert.Equal(t, nc.Details.NotAfter, nc2.Details.NotAfter)
  49. assert.Equal(t, nc.Details.PublicKey, nc2.Details.PublicKey)
  50. assert.Equal(t, nc.Details.IsCA, nc2.Details.IsCA)
  51. // IP byte arrays can be 4 or 16 in length so we have to go this route
  52. assert.Equal(t, len(nc.Details.Ips), len(nc2.Details.Ips))
  53. for i, wIp := range nc.Details.Ips {
  54. assert.Equal(t, wIp.String(), nc2.Details.Ips[i].String())
  55. }
  56. assert.Equal(t, len(nc.Details.Subnets), len(nc2.Details.Subnets))
  57. for i, wIp := range nc.Details.Subnets {
  58. assert.Equal(t, wIp.String(), nc2.Details.Subnets[i].String())
  59. }
  60. assert.EqualValues(t, nc.Details.Groups, nc2.Details.Groups)
  61. }
  62. func TestNebulaCertificate_Sign(t *testing.T) {
  63. before := time.Now().Add(time.Second * -60).Round(time.Second)
  64. after := time.Now().Add(time.Second * 60).Round(time.Second)
  65. pubKey := []byte("1234567890abcedfghij1234567890ab")
  66. nc := NebulaCertificate{
  67. Details: NebulaCertificateDetails{
  68. Name: "testing",
  69. Ips: []*net.IPNet{
  70. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  71. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  72. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  73. },
  74. Subnets: []*net.IPNet{
  75. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  76. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  77. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  78. },
  79. Groups: []string{"test-group1", "test-group2", "test-group3"},
  80. NotBefore: before,
  81. NotAfter: after,
  82. PublicKey: pubKey,
  83. IsCA: false,
  84. Issuer: "1234567890abcedfghij1234567890ab",
  85. },
  86. }
  87. pub, priv, err := ed25519.GenerateKey(rand.Reader)
  88. assert.Nil(t, err)
  89. assert.False(t, nc.CheckSignature(pub))
  90. assert.Nil(t, nc.Sign(priv))
  91. assert.True(t, nc.CheckSignature(pub))
  92. _, err = nc.Marshal()
  93. assert.Nil(t, err)
  94. //t.Log("Cert size:", len(b))
  95. }
  96. func TestNebulaCertificate_Expired(t *testing.T) {
  97. nc := NebulaCertificate{
  98. Details: NebulaCertificateDetails{
  99. NotBefore: time.Now().Add(time.Second * -60).Round(time.Second),
  100. NotAfter: time.Now().Add(time.Second * 60).Round(time.Second),
  101. },
  102. }
  103. assert.True(t, nc.Expired(time.Now().Add(time.Hour)))
  104. assert.True(t, nc.Expired(time.Now().Add(-time.Hour)))
  105. assert.False(t, nc.Expired(time.Now()))
  106. }
  107. func TestNebulaCertificate_MarshalJSON(t *testing.T) {
  108. time.Local = time.UTC
  109. pubKey := []byte("1234567890abcedfghij1234567890ab")
  110. nc := NebulaCertificate{
  111. Details: NebulaCertificateDetails{
  112. Name: "testing",
  113. Ips: []*net.IPNet{
  114. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  115. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  116. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  117. },
  118. Subnets: []*net.IPNet{
  119. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  120. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  121. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  122. },
  123. Groups: []string{"test-group1", "test-group2", "test-group3"},
  124. NotBefore: time.Date(1, 0, 0, 1, 0, 0, 0, time.UTC),
  125. NotAfter: time.Date(1, 0, 0, 2, 0, 0, 0, time.UTC),
  126. PublicKey: pubKey,
  127. IsCA: false,
  128. Issuer: "1234567890abcedfghij1234567890ab",
  129. },
  130. Signature: []byte("1234567890abcedfghij1234567890ab"),
  131. }
  132. b, err := nc.MarshalJSON()
  133. assert.Nil(t, err)
  134. assert.Equal(
  135. t,
  136. "{\"details\":{\"groups\":[\"test-group1\",\"test-group2\",\"test-group3\"],\"ips\":[\"10.1.1.1/24\",\"10.1.1.2/16\",\"10.1.1.3/ff00ff00\"],\"isCa\":false,\"issuer\":\"1234567890abcedfghij1234567890ab\",\"name\":\"testing\",\"notAfter\":\"0000-11-30T02:00:00Z\",\"notBefore\":\"0000-11-30T01:00:00Z\",\"publicKey\":\"313233343536373839306162636564666768696a313233343536373839306162\",\"subnets\":[\"9.1.1.1/ff00ff00\",\"9.1.1.2/24\",\"9.1.1.3/16\"]},\"fingerprint\":\"26cb1c30ad7872c804c166b5150fa372f437aa3856b04edb4334b4470ec728e4\",\"signature\":\"313233343536373839306162636564666768696a313233343536373839306162\"}",
  137. string(b),
  138. )
  139. }
  140. func TestNebulaCertificate_Verify(t *testing.T) {
  141. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  142. assert.Nil(t, err)
  143. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  144. assert.Nil(t, err)
  145. h, err := ca.Sha256Sum()
  146. assert.Nil(t, err)
  147. caPool := NewCAPool()
  148. caPool.CAs[h] = ca
  149. f, err := c.Sha256Sum()
  150. assert.Nil(t, err)
  151. caPool.BlocklistFingerprint(f)
  152. v, err := c.Verify(time.Now(), caPool)
  153. assert.False(t, v)
  154. assert.EqualError(t, err, "certificate has been blocked")
  155. caPool.ResetCertBlocklist()
  156. v, err = c.Verify(time.Now(), caPool)
  157. assert.True(t, v)
  158. assert.Nil(t, err)
  159. v, err = c.Verify(time.Now().Add(time.Hour*1000), caPool)
  160. assert.False(t, v)
  161. assert.EqualError(t, err, "root certificate is expired")
  162. c, _, _, err = newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  163. assert.Nil(t, err)
  164. v, err = c.Verify(time.Now().Add(time.Minute*6), caPool)
  165. assert.False(t, v)
  166. assert.EqualError(t, err, "certificate is expired")
  167. // Test group assertion
  168. ca, _, caKey, err = newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "test2"})
  169. assert.Nil(t, err)
  170. caPem, err := ca.MarshalToPEM()
  171. assert.Nil(t, err)
  172. caPool = NewCAPool()
  173. caPool.AddCACertificate(caPem)
  174. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "bad"})
  175. assert.Nil(t, err)
  176. v, err = c.Verify(time.Now(), caPool)
  177. assert.False(t, v)
  178. assert.EqualError(t, err, "certificate contained a group not present on the signing ca: bad")
  179. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1"})
  180. assert.Nil(t, err)
  181. v, err = c.Verify(time.Now(), caPool)
  182. assert.True(t, v)
  183. assert.Nil(t, err)
  184. }
  185. func TestNebulaCertificate_Verify_IPs(t *testing.T) {
  186. _, caIp1, _ := net.ParseCIDR("10.0.0.0/16")
  187. _, caIp2, _ := net.ParseCIDR("192.168.0.0/24")
  188. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{caIp1, caIp2}, []*net.IPNet{}, []string{"test"})
  189. assert.Nil(t, err)
  190. caPem, err := ca.MarshalToPEM()
  191. assert.Nil(t, err)
  192. caPool := NewCAPool()
  193. caPool.AddCACertificate(caPem)
  194. // ip is outside the network
  195. cIp1 := &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  196. cIp2 := &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 0, 0}}
  197. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  198. assert.Nil(t, err)
  199. v, err := c.Verify(time.Now(), caPool)
  200. assert.False(t, v)
  201. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.1.0.0/24")
  202. // ip is outside the network reversed order of above
  203. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  204. cIp2 = &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  205. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  206. assert.Nil(t, err)
  207. v, err = c.Verify(time.Now(), caPool)
  208. assert.False(t, v)
  209. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.1.0.0/24")
  210. // ip is within the network but mask is outside
  211. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  212. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  213. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  214. assert.Nil(t, err)
  215. v, err = c.Verify(time.Now(), caPool)
  216. assert.False(t, v)
  217. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.0.1.0/15")
  218. // ip is within the network but mask is outside reversed order of above
  219. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  220. cIp2 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  221. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  222. assert.Nil(t, err)
  223. v, err = c.Verify(time.Now(), caPool)
  224. assert.False(t, v)
  225. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.0.1.0/15")
  226. // ip and mask are within the network
  227. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 255, 0, 0}}
  228. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 128}}
  229. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  230. assert.Nil(t, err)
  231. v, err = c.Verify(time.Now(), caPool)
  232. assert.True(t, v)
  233. assert.Nil(t, err)
  234. // Exact matches
  235. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp1, caIp2}, []*net.IPNet{}, []string{"test"})
  236. assert.Nil(t, err)
  237. v, err = c.Verify(time.Now(), caPool)
  238. assert.True(t, v)
  239. assert.Nil(t, err)
  240. // Exact matches reversed
  241. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp2, caIp1}, []*net.IPNet{}, []string{"test"})
  242. assert.Nil(t, err)
  243. v, err = c.Verify(time.Now(), caPool)
  244. assert.True(t, v)
  245. assert.Nil(t, err)
  246. // Exact matches reversed with just 1
  247. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp1}, []*net.IPNet{}, []string{"test"})
  248. assert.Nil(t, err)
  249. v, err = c.Verify(time.Now(), caPool)
  250. assert.True(t, v)
  251. assert.Nil(t, err)
  252. }
  253. func TestNebulaCertificate_Verify_Subnets(t *testing.T) {
  254. _, caIp1, _ := net.ParseCIDR("10.0.0.0/16")
  255. _, caIp2, _ := net.ParseCIDR("192.168.0.0/24")
  256. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1, caIp2}, []string{"test"})
  257. assert.Nil(t, err)
  258. caPem, err := ca.MarshalToPEM()
  259. assert.Nil(t, err)
  260. caPool := NewCAPool()
  261. caPool.AddCACertificate(caPem)
  262. // ip is outside the network
  263. cIp1 := &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  264. cIp2 := &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 0, 0}}
  265. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  266. assert.Nil(t, err)
  267. v, err := c.Verify(time.Now(), caPool)
  268. assert.False(t, v)
  269. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.1.0.0/24")
  270. // ip is outside the network reversed order of above
  271. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  272. cIp2 = &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  273. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  274. assert.Nil(t, err)
  275. v, err = c.Verify(time.Now(), caPool)
  276. assert.False(t, v)
  277. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.1.0.0/24")
  278. // ip is within the network but mask is outside
  279. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  280. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  281. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  282. assert.Nil(t, err)
  283. v, err = c.Verify(time.Now(), caPool)
  284. assert.False(t, v)
  285. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.0.1.0/15")
  286. // ip is within the network but mask is outside reversed order of above
  287. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  288. cIp2 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  289. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  290. assert.Nil(t, err)
  291. v, err = c.Verify(time.Now(), caPool)
  292. assert.False(t, v)
  293. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.0.1.0/15")
  294. // ip and mask are within the network
  295. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 255, 0, 0}}
  296. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 128}}
  297. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  298. assert.Nil(t, err)
  299. v, err = c.Verify(time.Now(), caPool)
  300. assert.True(t, v)
  301. assert.Nil(t, err)
  302. // Exact matches
  303. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1, caIp2}, []string{"test"})
  304. assert.Nil(t, err)
  305. v, err = c.Verify(time.Now(), caPool)
  306. assert.True(t, v)
  307. assert.Nil(t, err)
  308. // Exact matches reversed
  309. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp2, caIp1}, []string{"test"})
  310. assert.Nil(t, err)
  311. v, err = c.Verify(time.Now(), caPool)
  312. assert.True(t, v)
  313. assert.Nil(t, err)
  314. // Exact matches reversed with just 1
  315. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1}, []string{"test"})
  316. assert.Nil(t, err)
  317. v, err = c.Verify(time.Now(), caPool)
  318. assert.True(t, v)
  319. assert.Nil(t, err)
  320. }
  321. func TestNebulaVerifyPrivateKey(t *testing.T) {
  322. ca, _, caKey, err := newTestCaCert(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  323. assert.Nil(t, err)
  324. c, _, priv, err := newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  325. err = c.VerifyPrivateKey(priv)
  326. assert.Nil(t, err)
  327. _, priv2 := x25519Keypair()
  328. err = c.VerifyPrivateKey(priv2)
  329. assert.NotNil(t, err)
  330. }
  331. func TestNewCAPoolFromBytes(t *testing.T) {
  332. noNewLines := `
  333. # Current provisional, Remove once everything moves over to the real root.
  334. -----BEGIN NEBULA CERTIFICATE-----
  335. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  336. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  337. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  338. -----END NEBULA CERTIFICATE-----
  339. # root-ca01
  340. -----BEGIN NEBULA CERTIFICATE-----
  341. CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
  342. BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
  343. 8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
  344. -----END NEBULA CERTIFICATE-----
  345. `
  346. withNewLines := `
  347. # Current provisional, Remove once everything moves over to the real root.
  348. -----BEGIN NEBULA CERTIFICATE-----
  349. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  350. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  351. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  352. -----END NEBULA CERTIFICATE-----
  353. # root-ca01
  354. -----BEGIN NEBULA CERTIFICATE-----
  355. CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
  356. BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
  357. 8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
  358. -----END NEBULA CERTIFICATE-----
  359. `
  360. rootCA := NebulaCertificate{
  361. Details: NebulaCertificateDetails{
  362. Name: "nebula root ca",
  363. },
  364. }
  365. rootCA01 := NebulaCertificate{
  366. Details: NebulaCertificateDetails{
  367. Name: "nebula root ca 01",
  368. },
  369. }
  370. p, err := NewCAPoolFromBytes([]byte(noNewLines))
  371. assert.Nil(t, err)
  372. assert.Equal(t, p.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
  373. assert.Equal(t, p.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
  374. pp, err := NewCAPoolFromBytes([]byte(withNewLines))
  375. assert.Nil(t, err)
  376. assert.Equal(t, pp.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
  377. assert.Equal(t, pp.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
  378. }
  379. // Ensure that upgrading the protobuf library does not change how certificates
  380. // are marshalled, since this would break signature verification
  381. func TestMarshalingNebulaCertificateConsistency(t *testing.T) {
  382. before := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
  383. after := time.Date(2017, time.January, 18, 28, 40, 0, 0, time.UTC)
  384. pubKey := []byte("1234567890abcedfghij1234567890ab")
  385. nc := NebulaCertificate{
  386. Details: NebulaCertificateDetails{
  387. Name: "testing",
  388. Ips: []*net.IPNet{
  389. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  390. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  391. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  392. },
  393. Subnets: []*net.IPNet{
  394. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  395. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  396. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  397. },
  398. Groups: []string{"test-group1", "test-group2", "test-group3"},
  399. NotBefore: before,
  400. NotAfter: after,
  401. PublicKey: pubKey,
  402. IsCA: false,
  403. Issuer: "1234567890abcedfghij1234567890ab",
  404. },
  405. Signature: []byte("1234567890abcedfghij1234567890ab"),
  406. }
  407. b, err := nc.Marshal()
  408. assert.Nil(t, err)
  409. //t.Log("Cert size:", len(b))
  410. assert.Equal(t, "0aa2010a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf1220313233343536373839306162636564666768696a313233343536373839306162", fmt.Sprintf("%x", b))
  411. b, err = proto.Marshal(nc.getRawDetails())
  412. assert.Nil(t, err)
  413. //t.Log("Raw cert size:", len(b))
  414. assert.Equal(t, "0a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf", fmt.Sprintf("%x", b))
  415. }
  416. func newTestCaCert(before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  417. pub, priv, err := ed25519.GenerateKey(rand.Reader)
  418. if before.IsZero() {
  419. before = time.Now().Add(time.Second * -60).Round(time.Second)
  420. }
  421. if after.IsZero() {
  422. after = time.Now().Add(time.Second * 60).Round(time.Second)
  423. }
  424. nc := &NebulaCertificate{
  425. Details: NebulaCertificateDetails{
  426. Name: "test ca",
  427. NotBefore: before,
  428. NotAfter: after,
  429. PublicKey: pub,
  430. IsCA: true,
  431. },
  432. }
  433. if len(ips) > 0 {
  434. nc.Details.Ips = ips
  435. }
  436. if len(subnets) > 0 {
  437. nc.Details.Subnets = subnets
  438. }
  439. if len(groups) > 0 {
  440. nc.Details.Groups = groups
  441. }
  442. err = nc.Sign(priv)
  443. if err != nil {
  444. return nil, nil, nil, err
  445. }
  446. return nc, pub, priv, nil
  447. }
  448. func newTestCert(ca *NebulaCertificate, key []byte, before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  449. issuer, err := ca.Sha256Sum()
  450. if err != nil {
  451. return nil, nil, nil, err
  452. }
  453. if before.IsZero() {
  454. before = time.Now().Add(time.Second * -60).Round(time.Second)
  455. }
  456. if after.IsZero() {
  457. after = time.Now().Add(time.Second * 60).Round(time.Second)
  458. }
  459. if len(groups) == 0 {
  460. groups = []string{"test-group1", "test-group2", "test-group3"}
  461. }
  462. if len(ips) == 0 {
  463. ips = []*net.IPNet{
  464. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  465. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  466. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  467. }
  468. }
  469. if len(subnets) == 0 {
  470. subnets = []*net.IPNet{
  471. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  472. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  473. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  474. }
  475. }
  476. pub, rawPriv := x25519Keypair()
  477. nc := &NebulaCertificate{
  478. Details: NebulaCertificateDetails{
  479. Name: "testing",
  480. Ips: ips,
  481. Subnets: subnets,
  482. Groups: groups,
  483. NotBefore: before,
  484. NotAfter: after,
  485. PublicKey: pub,
  486. IsCA: false,
  487. Issuer: issuer,
  488. },
  489. }
  490. err = nc.Sign(key)
  491. if err != nil {
  492. return nil, nil, nil, err
  493. }
  494. return nc, pub, rawPriv, nil
  495. }
  496. func x25519Keypair() ([]byte, []byte) {
  497. var pubkey, privkey [32]byte
  498. if _, err := io.ReadFull(rand.Reader, privkey[:]); err != nil {
  499. panic(err)
  500. }
  501. curve25519.ScalarBaseMult(&pubkey, &privkey)
  502. return pubkey[:], privkey[:]
  503. }