cert_test.go 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874
  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/slackhq/nebula/test"
  11. "github.com/stretchr/testify/assert"
  12. "golang.org/x/crypto/curve25519"
  13. "golang.org/x/crypto/ed25519"
  14. )
  15. func TestMarshalingNebulaCertificate(t *testing.T) {
  16. before := time.Now().Add(time.Second * -60).Round(time.Second)
  17. after := time.Now().Add(time.Second * 60).Round(time.Second)
  18. pubKey := []byte("1234567890abcedfghij1234567890ab")
  19. nc := NebulaCertificate{
  20. Details: NebulaCertificateDetails{
  21. Name: "testing",
  22. Ips: []*net.IPNet{
  23. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  24. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  25. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  26. },
  27. Subnets: []*net.IPNet{
  28. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  29. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  30. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  31. },
  32. Groups: []string{"test-group1", "test-group2", "test-group3"},
  33. NotBefore: before,
  34. NotAfter: after,
  35. PublicKey: pubKey,
  36. IsCA: false,
  37. Issuer: "1234567890abcedfghij1234567890ab",
  38. },
  39. Signature: []byte("1234567890abcedfghij1234567890ab"),
  40. }
  41. b, err := nc.Marshal()
  42. assert.Nil(t, err)
  43. //t.Log("Cert size:", len(b))
  44. nc2, err := UnmarshalNebulaCertificate(b)
  45. assert.Nil(t, err)
  46. assert.Equal(t, nc.Signature, nc2.Signature)
  47. assert.Equal(t, nc.Details.Name, nc2.Details.Name)
  48. assert.Equal(t, nc.Details.NotBefore, nc2.Details.NotBefore)
  49. assert.Equal(t, nc.Details.NotAfter, nc2.Details.NotAfter)
  50. assert.Equal(t, nc.Details.PublicKey, nc2.Details.PublicKey)
  51. assert.Equal(t, nc.Details.IsCA, nc2.Details.IsCA)
  52. // IP byte arrays can be 4 or 16 in length so we have to go this route
  53. assert.Equal(t, len(nc.Details.Ips), len(nc2.Details.Ips))
  54. for i, wIp := range nc.Details.Ips {
  55. assert.Equal(t, wIp.String(), nc2.Details.Ips[i].String())
  56. }
  57. assert.Equal(t, len(nc.Details.Subnets), len(nc2.Details.Subnets))
  58. for i, wIp := range nc.Details.Subnets {
  59. assert.Equal(t, wIp.String(), nc2.Details.Subnets[i].String())
  60. }
  61. assert.EqualValues(t, nc.Details.Groups, nc2.Details.Groups)
  62. }
  63. func TestNebulaCertificate_Sign(t *testing.T) {
  64. before := time.Now().Add(time.Second * -60).Round(time.Second)
  65. after := time.Now().Add(time.Second * 60).Round(time.Second)
  66. pubKey := []byte("1234567890abcedfghij1234567890ab")
  67. nc := NebulaCertificate{
  68. Details: NebulaCertificateDetails{
  69. Name: "testing",
  70. Ips: []*net.IPNet{
  71. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  72. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  73. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  74. },
  75. Subnets: []*net.IPNet{
  76. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  77. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  78. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  79. },
  80. Groups: []string{"test-group1", "test-group2", "test-group3"},
  81. NotBefore: before,
  82. NotAfter: after,
  83. PublicKey: pubKey,
  84. IsCA: false,
  85. Issuer: "1234567890abcedfghij1234567890ab",
  86. },
  87. }
  88. pub, priv, err := ed25519.GenerateKey(rand.Reader)
  89. assert.Nil(t, err)
  90. assert.False(t, nc.CheckSignature(pub))
  91. assert.Nil(t, nc.Sign(priv))
  92. assert.True(t, nc.CheckSignature(pub))
  93. _, err = nc.Marshal()
  94. assert.Nil(t, err)
  95. //t.Log("Cert size:", len(b))
  96. }
  97. func TestNebulaCertificate_Expired(t *testing.T) {
  98. nc := NebulaCertificate{
  99. Details: NebulaCertificateDetails{
  100. NotBefore: time.Now().Add(time.Second * -60).Round(time.Second),
  101. NotAfter: time.Now().Add(time.Second * 60).Round(time.Second),
  102. },
  103. }
  104. assert.True(t, nc.Expired(time.Now().Add(time.Hour)))
  105. assert.True(t, nc.Expired(time.Now().Add(-time.Hour)))
  106. assert.False(t, nc.Expired(time.Now()))
  107. }
  108. func TestNebulaCertificate_MarshalJSON(t *testing.T) {
  109. time.Local = time.UTC
  110. pubKey := []byte("1234567890abcedfghij1234567890ab")
  111. nc := NebulaCertificate{
  112. Details: NebulaCertificateDetails{
  113. Name: "testing",
  114. Ips: []*net.IPNet{
  115. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  116. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  117. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  118. },
  119. Subnets: []*net.IPNet{
  120. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  121. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  122. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  123. },
  124. Groups: []string{"test-group1", "test-group2", "test-group3"},
  125. NotBefore: time.Date(1, 0, 0, 1, 0, 0, 0, time.UTC),
  126. NotAfter: time.Date(1, 0, 0, 2, 0, 0, 0, time.UTC),
  127. PublicKey: pubKey,
  128. IsCA: false,
  129. Issuer: "1234567890abcedfghij1234567890ab",
  130. },
  131. Signature: []byte("1234567890abcedfghij1234567890ab"),
  132. }
  133. b, err := nc.MarshalJSON()
  134. assert.Nil(t, err)
  135. assert.Equal(
  136. t,
  137. "{\"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\"}",
  138. string(b),
  139. )
  140. }
  141. func TestNebulaCertificate_Verify(t *testing.T) {
  142. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  143. assert.Nil(t, err)
  144. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  145. assert.Nil(t, err)
  146. h, err := ca.Sha256Sum()
  147. assert.Nil(t, err)
  148. caPool := NewCAPool()
  149. caPool.CAs[h] = ca
  150. f, err := c.Sha256Sum()
  151. assert.Nil(t, err)
  152. caPool.BlocklistFingerprint(f)
  153. v, err := c.Verify(time.Now(), caPool)
  154. assert.False(t, v)
  155. assert.EqualError(t, err, "certificate has been blocked")
  156. caPool.ResetCertBlocklist()
  157. v, err = c.Verify(time.Now(), caPool)
  158. assert.True(t, v)
  159. assert.Nil(t, err)
  160. v, err = c.Verify(time.Now().Add(time.Hour*1000), caPool)
  161. assert.False(t, v)
  162. assert.EqualError(t, err, "root certificate is expired")
  163. c, _, _, err = newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  164. assert.Nil(t, err)
  165. v, err = c.Verify(time.Now().Add(time.Minute*6), caPool)
  166. assert.False(t, v)
  167. assert.EqualError(t, err, "certificate is expired")
  168. // Test group assertion
  169. ca, _, caKey, err = newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "test2"})
  170. assert.Nil(t, err)
  171. caPem, err := ca.MarshalToPEM()
  172. assert.Nil(t, err)
  173. caPool = NewCAPool()
  174. caPool.AddCACertificate(caPem)
  175. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1", "bad"})
  176. assert.Nil(t, err)
  177. v, err = c.Verify(time.Now(), caPool)
  178. assert.False(t, v)
  179. assert.EqualError(t, err, "certificate contained a group not present on the signing ca: bad")
  180. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{"test1"})
  181. assert.Nil(t, err)
  182. v, err = c.Verify(time.Now(), caPool)
  183. assert.True(t, v)
  184. assert.Nil(t, err)
  185. }
  186. func TestNebulaCertificate_Verify_IPs(t *testing.T) {
  187. _, caIp1, _ := net.ParseCIDR("10.0.0.0/16")
  188. _, caIp2, _ := net.ParseCIDR("192.168.0.0/24")
  189. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{caIp1, caIp2}, []*net.IPNet{}, []string{"test"})
  190. assert.Nil(t, err)
  191. caPem, err := ca.MarshalToPEM()
  192. assert.Nil(t, err)
  193. caPool := NewCAPool()
  194. caPool.AddCACertificate(caPem)
  195. // ip is outside the network
  196. cIp1 := &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  197. cIp2 := &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 0, 0}}
  198. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  199. assert.Nil(t, err)
  200. v, err := c.Verify(time.Now(), caPool)
  201. assert.False(t, v)
  202. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.1.0.0/24")
  203. // ip is outside the network reversed order of above
  204. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  205. cIp2 = &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  206. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  207. assert.Nil(t, err)
  208. v, err = c.Verify(time.Now(), caPool)
  209. assert.False(t, v)
  210. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.1.0.0/24")
  211. // ip is within the network but mask is outside
  212. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  213. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  214. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  215. assert.Nil(t, err)
  216. v, err = c.Verify(time.Now(), caPool)
  217. assert.False(t, v)
  218. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.0.1.0/15")
  219. // ip is within the network but mask is outside reversed order of above
  220. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  221. cIp2 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  222. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  223. assert.Nil(t, err)
  224. v, err = c.Verify(time.Now(), caPool)
  225. assert.False(t, v)
  226. assert.EqualError(t, err, "certificate contained an ip assignment outside the limitations of the signing ca: 10.0.1.0/15")
  227. // ip and mask are within the network
  228. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 255, 0, 0}}
  229. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 128}}
  230. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{cIp1, cIp2}, []*net.IPNet{}, []string{"test"})
  231. assert.Nil(t, err)
  232. v, err = c.Verify(time.Now(), caPool)
  233. assert.True(t, v)
  234. assert.Nil(t, err)
  235. // Exact matches
  236. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp1, caIp2}, []*net.IPNet{}, []string{"test"})
  237. assert.Nil(t, err)
  238. v, err = c.Verify(time.Now(), caPool)
  239. assert.True(t, v)
  240. assert.Nil(t, err)
  241. // Exact matches reversed
  242. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp2, caIp1}, []*net.IPNet{}, []string{"test"})
  243. assert.Nil(t, err)
  244. v, err = c.Verify(time.Now(), caPool)
  245. assert.True(t, v)
  246. assert.Nil(t, err)
  247. // Exact matches reversed with just 1
  248. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{caIp1}, []*net.IPNet{}, []string{"test"})
  249. assert.Nil(t, err)
  250. v, err = c.Verify(time.Now(), caPool)
  251. assert.True(t, v)
  252. assert.Nil(t, err)
  253. }
  254. func TestNebulaCertificate_Verify_Subnets(t *testing.T) {
  255. _, caIp1, _ := net.ParseCIDR("10.0.0.0/16")
  256. _, caIp2, _ := net.ParseCIDR("192.168.0.0/24")
  257. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1, caIp2}, []string{"test"})
  258. assert.Nil(t, err)
  259. caPem, err := ca.MarshalToPEM()
  260. assert.Nil(t, err)
  261. caPool := NewCAPool()
  262. caPool.AddCACertificate(caPem)
  263. // ip is outside the network
  264. cIp1 := &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  265. cIp2 := &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 0, 0}}
  266. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  267. assert.Nil(t, err)
  268. v, err := c.Verify(time.Now(), caPool)
  269. assert.False(t, v)
  270. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.1.0.0/24")
  271. // ip is outside the network reversed order of above
  272. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  273. cIp2 = &net.IPNet{IP: net.ParseIP("10.1.0.0"), Mask: []byte{255, 255, 255, 0}}
  274. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  275. assert.Nil(t, err)
  276. v, err = c.Verify(time.Now(), caPool)
  277. assert.False(t, v)
  278. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.1.0.0/24")
  279. // ip is within the network but mask is outside
  280. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  281. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  282. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  283. assert.Nil(t, err)
  284. v, err = c.Verify(time.Now(), caPool)
  285. assert.False(t, v)
  286. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.0.1.0/15")
  287. // ip is within the network but mask is outside reversed order of above
  288. cIp1 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 0}}
  289. cIp2 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 254, 0, 0}}
  290. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  291. assert.Nil(t, err)
  292. v, err = c.Verify(time.Now(), caPool)
  293. assert.False(t, v)
  294. assert.EqualError(t, err, "certificate contained a subnet assignment outside the limitations of the signing ca: 10.0.1.0/15")
  295. // ip and mask are within the network
  296. cIp1 = &net.IPNet{IP: net.ParseIP("10.0.1.0"), Mask: []byte{255, 255, 0, 0}}
  297. cIp2 = &net.IPNet{IP: net.ParseIP("192.168.0.1"), Mask: []byte{255, 255, 255, 128}}
  298. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{cIp1, cIp2}, []string{"test"})
  299. assert.Nil(t, err)
  300. v, err = c.Verify(time.Now(), caPool)
  301. assert.True(t, v)
  302. assert.Nil(t, err)
  303. // Exact matches
  304. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1, caIp2}, []string{"test"})
  305. assert.Nil(t, err)
  306. v, err = c.Verify(time.Now(), caPool)
  307. assert.True(t, v)
  308. assert.Nil(t, err)
  309. // Exact matches reversed
  310. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp2, caIp1}, []string{"test"})
  311. assert.Nil(t, err)
  312. v, err = c.Verify(time.Now(), caPool)
  313. assert.True(t, v)
  314. assert.Nil(t, err)
  315. // Exact matches reversed with just 1
  316. c, _, _, err = newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{caIp1}, []string{"test"})
  317. assert.Nil(t, err)
  318. v, err = c.Verify(time.Now(), caPool)
  319. assert.True(t, v)
  320. assert.Nil(t, err)
  321. }
  322. func TestNebulaCertificate_VerifyPrivateKey(t *testing.T) {
  323. ca, _, caKey, err := newTestCaCert(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  324. assert.Nil(t, err)
  325. err = ca.VerifyPrivateKey(caKey)
  326. assert.Nil(t, err)
  327. _, _, caKey2, err := newTestCaCert(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  328. assert.Nil(t, err)
  329. err = ca.VerifyPrivateKey(caKey2)
  330. assert.NotNil(t, err)
  331. c, _, priv, err := newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  332. err = c.VerifyPrivateKey(priv)
  333. assert.Nil(t, err)
  334. _, priv2 := x25519Keypair()
  335. err = c.VerifyPrivateKey(priv2)
  336. assert.NotNil(t, err)
  337. }
  338. func TestNewCAPoolFromBytes(t *testing.T) {
  339. noNewLines := `
  340. # Current provisional, Remove once everything moves over to the real root.
  341. -----BEGIN NEBULA CERTIFICATE-----
  342. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  343. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  344. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  345. -----END NEBULA CERTIFICATE-----
  346. # root-ca01
  347. -----BEGIN NEBULA CERTIFICATE-----
  348. CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
  349. BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
  350. 8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
  351. -----END NEBULA CERTIFICATE-----
  352. `
  353. withNewLines := `
  354. # Current provisional, Remove once everything moves over to the real root.
  355. -----BEGIN NEBULA CERTIFICATE-----
  356. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  357. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  358. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  359. -----END NEBULA CERTIFICATE-----
  360. # root-ca01
  361. -----BEGIN NEBULA CERTIFICATE-----
  362. CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
  363. BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
  364. 8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
  365. -----END NEBULA CERTIFICATE-----
  366. `
  367. rootCA := NebulaCertificate{
  368. Details: NebulaCertificateDetails{
  369. Name: "nebula root ca",
  370. },
  371. }
  372. rootCA01 := NebulaCertificate{
  373. Details: NebulaCertificateDetails{
  374. Name: "nebula root ca 01",
  375. },
  376. }
  377. p, err := NewCAPoolFromBytes([]byte(noNewLines))
  378. assert.Nil(t, err)
  379. assert.Equal(t, p.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
  380. assert.Equal(t, p.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
  381. pp, err := NewCAPoolFromBytes([]byte(withNewLines))
  382. assert.Nil(t, err)
  383. assert.Equal(t, pp.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
  384. assert.Equal(t, pp.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
  385. }
  386. func appendByteSlices(b ...[]byte) []byte {
  387. retSlice := []byte{}
  388. for _, v := range b {
  389. retSlice = append(retSlice, v...)
  390. }
  391. return retSlice
  392. }
  393. func TestUnmrshalCertPEM(t *testing.T) {
  394. goodCert := []byte(`
  395. # A good cert
  396. -----BEGIN NEBULA CERTIFICATE-----
  397. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  398. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  399. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  400. -----END NEBULA CERTIFICATE-----
  401. `)
  402. badBanner := []byte(`# A bad banner
  403. -----BEGIN NOT A NEBULA CERTIFICATE-----
  404. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  405. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  406. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  407. -----END NOT A NEBULA CERTIFICATE-----
  408. `)
  409. invalidPem := []byte(`# Not a valid PEM format
  410. -BEGIN NEBULA CERTIFICATE-----
  411. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  412. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  413. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  414. -END NEBULA CERTIFICATE----`)
  415. certBundle := appendByteSlices(goodCert, badBanner, invalidPem)
  416. // Success test case
  417. cert, rest, err := UnmarshalNebulaCertificateFromPEM(certBundle)
  418. assert.NotNil(t, cert)
  419. assert.Equal(t, rest, append(badBanner, invalidPem...))
  420. assert.Nil(t, err)
  421. // Fail due to invalid banner.
  422. cert, rest, err = UnmarshalNebulaCertificateFromPEM(rest)
  423. assert.Nil(t, cert)
  424. assert.Equal(t, rest, invalidPem)
  425. assert.EqualError(t, err, "bytes did not contain a proper nebula certificate banner")
  426. // Fail due to ivalid PEM format, because
  427. // it's missing the requisite pre-encapsulation boundary.
  428. cert, rest, err = UnmarshalNebulaCertificateFromPEM(rest)
  429. assert.Nil(t, cert)
  430. assert.Equal(t, rest, invalidPem)
  431. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  432. }
  433. func TestUnmarshalEd25519PrivateKey(t *testing.T) {
  434. privKey := []byte(`# A good key
  435. -----BEGIN NEBULA ED25519 PRIVATE KEY-----
  436. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  437. -----END NEBULA ED25519 PRIVATE KEY-----
  438. `)
  439. shortKey := []byte(`# A short key
  440. -----BEGIN NEBULA ED25519 PRIVATE KEY-----
  441. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  442. -----END NEBULA ED25519 PRIVATE KEY-----
  443. `)
  444. invalidBanner := []byte(`# Invalid banner
  445. -----BEGIN NOT A NEBULA PRIVATE KEY-----
  446. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  447. -----END NOT A NEBULA PRIVATE KEY-----
  448. `)
  449. invalidPem := []byte(`# Not a valid PEM format
  450. -BEGIN NEBULA ED25519 PRIVATE KEY-----
  451. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  452. -END NEBULA ED25519 PRIVATE KEY-----`)
  453. keyBundle := appendByteSlices(privKey, shortKey, invalidBanner, invalidPem)
  454. // Success test case
  455. k, rest, err := UnmarshalEd25519PrivateKey(keyBundle)
  456. assert.Len(t, k, 64)
  457. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  458. assert.Nil(t, err)
  459. // Fail due to short key
  460. k, rest, err = UnmarshalEd25519PrivateKey(rest)
  461. assert.Nil(t, k)
  462. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  463. assert.EqualError(t, err, "key was not 64 bytes, is invalid ed25519 private key")
  464. // Fail due to invalid banner
  465. k, rest, err = UnmarshalEd25519PrivateKey(rest)
  466. assert.Nil(t, k)
  467. assert.Equal(t, rest, invalidPem)
  468. assert.EqualError(t, err, "bytes did not contain a proper nebula Ed25519 private key banner")
  469. // Fail due to ivalid PEM format, because
  470. // it's missing the requisite pre-encapsulation boundary.
  471. k, rest, err = UnmarshalEd25519PrivateKey(rest)
  472. assert.Nil(t, k)
  473. assert.Equal(t, rest, invalidPem)
  474. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  475. }
  476. func TestUnmarshalX25519PrivateKey(t *testing.T) {
  477. privKey := []byte(`# A good key
  478. -----BEGIN NEBULA X25519 PRIVATE KEY-----
  479. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  480. -----END NEBULA X25519 PRIVATE KEY-----
  481. `)
  482. shortKey := []byte(`# A short key
  483. -----BEGIN NEBULA X25519 PRIVATE KEY-----
  484. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  485. -----END NEBULA X25519 PRIVATE KEY-----
  486. `)
  487. invalidBanner := []byte(`# Invalid banner
  488. -----BEGIN NOT A NEBULA PRIVATE KEY-----
  489. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  490. -----END NOT A NEBULA PRIVATE KEY-----
  491. `)
  492. invalidPem := []byte(`# Not a valid PEM format
  493. -BEGIN NEBULA X25519 PRIVATE KEY-----
  494. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  495. -END NEBULA X25519 PRIVATE KEY-----`)
  496. keyBundle := appendByteSlices(privKey, shortKey, invalidBanner, invalidPem)
  497. // Success test case
  498. k, rest, err := UnmarshalX25519PrivateKey(keyBundle)
  499. assert.Len(t, k, 32)
  500. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  501. assert.Nil(t, err)
  502. // Fail due to short key
  503. k, rest, err = UnmarshalX25519PrivateKey(rest)
  504. assert.Nil(t, k)
  505. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  506. assert.EqualError(t, err, "key was not 32 bytes, is invalid X25519 private key")
  507. // Fail due to invalid banner
  508. k, rest, err = UnmarshalX25519PrivateKey(rest)
  509. assert.Nil(t, k)
  510. assert.Equal(t, rest, invalidPem)
  511. assert.EqualError(t, err, "bytes did not contain a proper nebula X25519 private key banner")
  512. // Fail due to ivalid PEM format, because
  513. // it's missing the requisite pre-encapsulation boundary.
  514. k, rest, err = UnmarshalX25519PrivateKey(rest)
  515. assert.Nil(t, k)
  516. assert.Equal(t, rest, invalidPem)
  517. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  518. }
  519. func TestUnmarshalEd25519PublicKey(t *testing.T) {
  520. pubKey := []byte(`# A good key
  521. -----BEGIN NEBULA ED25519 PUBLIC KEY-----
  522. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  523. -----END NEBULA ED25519 PUBLIC KEY-----
  524. `)
  525. shortKey := []byte(`# A short key
  526. -----BEGIN NEBULA ED25519 PUBLIC KEY-----
  527. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  528. -----END NEBULA ED25519 PUBLIC KEY-----
  529. `)
  530. invalidBanner := []byte(`# Invalid banner
  531. -----BEGIN NOT A NEBULA PUBLIC KEY-----
  532. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  533. -----END NOT A NEBULA PUBLIC KEY-----
  534. `)
  535. invalidPem := []byte(`# Not a valid PEM format
  536. -BEGIN NEBULA ED25519 PUBLIC KEY-----
  537. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  538. -END NEBULA ED25519 PUBLIC KEY-----`)
  539. keyBundle := appendByteSlices(pubKey, shortKey, invalidBanner, invalidPem)
  540. // Success test case
  541. k, rest, err := UnmarshalEd25519PublicKey(keyBundle)
  542. assert.Equal(t, len(k), 32)
  543. assert.Nil(t, err)
  544. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  545. // Fail due to short key
  546. k, rest, err = UnmarshalEd25519PublicKey(rest)
  547. assert.Nil(t, k)
  548. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  549. assert.EqualError(t, err, "key was not 32 bytes, is invalid ed25519 public key")
  550. // Fail due to invalid banner
  551. k, rest, err = UnmarshalEd25519PublicKey(rest)
  552. assert.Nil(t, k)
  553. assert.EqualError(t, err, "bytes did not contain a proper nebula Ed25519 public key banner")
  554. assert.Equal(t, rest, invalidPem)
  555. // Fail due to ivalid PEM format, because
  556. // it's missing the requisite pre-encapsulation boundary.
  557. k, rest, err = UnmarshalEd25519PublicKey(rest)
  558. assert.Nil(t, k)
  559. assert.Equal(t, rest, invalidPem)
  560. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  561. }
  562. func TestUnmarshalX25519PublicKey(t *testing.T) {
  563. pubKey := []byte(`# A good key
  564. -----BEGIN NEBULA X25519 PUBLIC KEY-----
  565. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  566. -----END NEBULA X25519 PUBLIC KEY-----
  567. `)
  568. shortKey := []byte(`# A short key
  569. -----BEGIN NEBULA X25519 PUBLIC KEY-----
  570. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  571. -----END NEBULA X25519 PUBLIC KEY-----
  572. `)
  573. invalidBanner := []byte(`# Invalid banner
  574. -----BEGIN NOT A NEBULA PUBLIC KEY-----
  575. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  576. -----END NOT A NEBULA PUBLIC KEY-----
  577. `)
  578. invalidPem := []byte(`# Not a valid PEM format
  579. -BEGIN NEBULA X25519 PUBLIC KEY-----
  580. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  581. -END NEBULA X25519 PUBLIC KEY-----`)
  582. keyBundle := appendByteSlices(pubKey, shortKey, invalidBanner, invalidPem)
  583. // Success test case
  584. k, rest, err := UnmarshalX25519PublicKey(keyBundle)
  585. assert.Equal(t, len(k), 32)
  586. assert.Nil(t, err)
  587. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  588. // Fail due to short key
  589. k, rest, err = UnmarshalX25519PublicKey(rest)
  590. assert.Nil(t, k)
  591. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  592. assert.EqualError(t, err, "key was not 32 bytes, is invalid X25519 public key")
  593. // Fail due to invalid banner
  594. k, rest, err = UnmarshalX25519PublicKey(rest)
  595. assert.Nil(t, k)
  596. assert.EqualError(t, err, "bytes did not contain a proper nebula X25519 public key banner")
  597. assert.Equal(t, rest, invalidPem)
  598. // Fail due to ivalid PEM format, because
  599. // it's missing the requisite pre-encapsulation boundary.
  600. k, rest, err = UnmarshalX25519PublicKey(rest)
  601. assert.Nil(t, k)
  602. assert.Equal(t, rest, invalidPem)
  603. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  604. }
  605. // Ensure that upgrading the protobuf library does not change how certificates
  606. // are marshalled, since this would break signature verification
  607. func TestMarshalingNebulaCertificateConsistency(t *testing.T) {
  608. before := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
  609. after := time.Date(2017, time.January, 18, 28, 40, 0, 0, time.UTC)
  610. pubKey := []byte("1234567890abcedfghij1234567890ab")
  611. nc := NebulaCertificate{
  612. Details: NebulaCertificateDetails{
  613. Name: "testing",
  614. Ips: []*net.IPNet{
  615. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  616. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  617. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  618. },
  619. Subnets: []*net.IPNet{
  620. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  621. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  622. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  623. },
  624. Groups: []string{"test-group1", "test-group2", "test-group3"},
  625. NotBefore: before,
  626. NotAfter: after,
  627. PublicKey: pubKey,
  628. IsCA: false,
  629. Issuer: "1234567890abcedfghij1234567890ab",
  630. },
  631. Signature: []byte("1234567890abcedfghij1234567890ab"),
  632. }
  633. b, err := nc.Marshal()
  634. assert.Nil(t, err)
  635. //t.Log("Cert size:", len(b))
  636. assert.Equal(t, "0aa2010a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf1220313233343536373839306162636564666768696a313233343536373839306162", fmt.Sprintf("%x", b))
  637. b, err = proto.Marshal(nc.getRawDetails())
  638. assert.Nil(t, err)
  639. //t.Log("Raw cert size:", len(b))
  640. assert.Equal(t, "0a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf", fmt.Sprintf("%x", b))
  641. }
  642. func TestNebulaCertificate_Copy(t *testing.T) {
  643. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  644. assert.Nil(t, err)
  645. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  646. assert.Nil(t, err)
  647. cc := c.Copy()
  648. test.AssertDeepCopyEqual(t, c, cc)
  649. }
  650. func TestUnmarshalNebulaCertificate(t *testing.T) {
  651. // Test that we don't panic with an invalid certificate (#332)
  652. data := []byte("\x98\x00\x00")
  653. _, err := UnmarshalNebulaCertificate(data)
  654. assert.EqualError(t, err, "encoded Details was nil")
  655. }
  656. func newTestCaCert(before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  657. pub, priv, err := ed25519.GenerateKey(rand.Reader)
  658. if before.IsZero() {
  659. before = time.Now().Add(time.Second * -60).Round(time.Second)
  660. }
  661. if after.IsZero() {
  662. after = time.Now().Add(time.Second * 60).Round(time.Second)
  663. }
  664. nc := &NebulaCertificate{
  665. Details: NebulaCertificateDetails{
  666. Name: "test ca",
  667. NotBefore: time.Unix(before.Unix(), 0),
  668. NotAfter: time.Unix(after.Unix(), 0),
  669. PublicKey: pub,
  670. IsCA: true,
  671. InvertedGroups: make(map[string]struct{}),
  672. },
  673. }
  674. if len(ips) > 0 {
  675. nc.Details.Ips = ips
  676. }
  677. if len(subnets) > 0 {
  678. nc.Details.Subnets = subnets
  679. }
  680. if len(groups) > 0 {
  681. nc.Details.Groups = groups
  682. }
  683. err = nc.Sign(priv)
  684. if err != nil {
  685. return nil, nil, nil, err
  686. }
  687. return nc, pub, priv, nil
  688. }
  689. func newTestCert(ca *NebulaCertificate, key []byte, before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  690. issuer, err := ca.Sha256Sum()
  691. if err != nil {
  692. return nil, nil, nil, err
  693. }
  694. if before.IsZero() {
  695. before = time.Now().Add(time.Second * -60).Round(time.Second)
  696. }
  697. if after.IsZero() {
  698. after = time.Now().Add(time.Second * 60).Round(time.Second)
  699. }
  700. if len(groups) == 0 {
  701. groups = []string{"test-group1", "test-group2", "test-group3"}
  702. }
  703. if len(ips) == 0 {
  704. ips = []*net.IPNet{
  705. {IP: net.ParseIP("10.1.1.1").To4(), Mask: net.IPMask(net.ParseIP("255.255.255.0").To4())},
  706. {IP: net.ParseIP("10.1.1.2").To4(), Mask: net.IPMask(net.ParseIP("255.255.0.0").To4())},
  707. {IP: net.ParseIP("10.1.1.3").To4(), Mask: net.IPMask(net.ParseIP("255.0.255.0").To4())},
  708. }
  709. }
  710. if len(subnets) == 0 {
  711. subnets = []*net.IPNet{
  712. {IP: net.ParseIP("9.1.1.1").To4(), Mask: net.IPMask(net.ParseIP("255.0.255.0").To4())},
  713. {IP: net.ParseIP("9.1.1.2").To4(), Mask: net.IPMask(net.ParseIP("255.255.255.0").To4())},
  714. {IP: net.ParseIP("9.1.1.3").To4(), Mask: net.IPMask(net.ParseIP("255.255.0.0").To4())},
  715. }
  716. }
  717. pub, rawPriv := x25519Keypair()
  718. nc := &NebulaCertificate{
  719. Details: NebulaCertificateDetails{
  720. Name: "testing",
  721. Ips: ips,
  722. Subnets: subnets,
  723. Groups: groups,
  724. NotBefore: time.Unix(before.Unix(), 0),
  725. NotAfter: time.Unix(after.Unix(), 0),
  726. PublicKey: pub,
  727. IsCA: false,
  728. Issuer: issuer,
  729. InvertedGroups: make(map[string]struct{}),
  730. },
  731. }
  732. err = nc.Sign(key)
  733. if err != nil {
  734. return nil, nil, nil, err
  735. }
  736. return nc, pub, rawPriv, nil
  737. }
  738. func x25519Keypair() ([]byte, []byte) {
  739. privkey := make([]byte, 32)
  740. if _, err := io.ReadFull(rand.Reader, privkey); err != nil {
  741. panic(err)
  742. }
  743. pubkey, err := curve25519.X25519(privkey, curve25519.Basepoint)
  744. if err != nil {
  745. panic(err)
  746. }
  747. return pubkey, privkey
  748. }