cert_test.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  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/util"
  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 TestNebulaVerifyPrivateKey(t *testing.T) {
  323. ca, _, caKey, err := newTestCaCert(time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  324. assert.Nil(t, err)
  325. c, _, priv, err := newTestCert(ca, caKey, time.Time{}, time.Time{}, []*net.IPNet{}, []*net.IPNet{}, []string{})
  326. err = c.VerifyPrivateKey(priv)
  327. assert.Nil(t, err)
  328. _, priv2 := x25519Keypair()
  329. err = c.VerifyPrivateKey(priv2)
  330. assert.NotNil(t, err)
  331. }
  332. func TestNewCAPoolFromBytes(t *testing.T) {
  333. noNewLines := `
  334. # Current provisional, Remove once everything moves over to the real root.
  335. -----BEGIN NEBULA CERTIFICATE-----
  336. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  337. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  338. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  339. -----END NEBULA CERTIFICATE-----
  340. # root-ca01
  341. -----BEGIN NEBULA CERTIFICATE-----
  342. CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
  343. BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
  344. 8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
  345. -----END NEBULA CERTIFICATE-----
  346. `
  347. withNewLines := `
  348. # Current provisional, Remove once everything moves over to the real root.
  349. -----BEGIN NEBULA CERTIFICATE-----
  350. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  351. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  352. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  353. -----END NEBULA CERTIFICATE-----
  354. # root-ca01
  355. -----BEGIN NEBULA CERTIFICATE-----
  356. CkMKEW5lYnVsYSByb290IGNhIDAxKJL2u9EFMJL86+cGOiDPXMH4oU6HZTk/CqTG
  357. BVG+oJpAoqokUBbI4U0N8CSfpUABEkB/Pm5A2xyH/nc8mg/wvGUWG3pZ7nHzaDMf
  358. 8/phAUt+FLzqTECzQKisYswKvE3pl9mbEYKbOdIHrxdIp95mo4sF
  359. -----END NEBULA CERTIFICATE-----
  360. `
  361. rootCA := NebulaCertificate{
  362. Details: NebulaCertificateDetails{
  363. Name: "nebula root ca",
  364. },
  365. }
  366. rootCA01 := NebulaCertificate{
  367. Details: NebulaCertificateDetails{
  368. Name: "nebula root ca 01",
  369. },
  370. }
  371. p, err := NewCAPoolFromBytes([]byte(noNewLines))
  372. assert.Nil(t, err)
  373. assert.Equal(t, p.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
  374. assert.Equal(t, p.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
  375. pp, err := NewCAPoolFromBytes([]byte(withNewLines))
  376. assert.Nil(t, err)
  377. assert.Equal(t, pp.CAs[string("c9bfaf7ce8e84b2eeda2e27b469f4b9617bde192efd214b68891ecda6ed49522")].Details.Name, rootCA.Details.Name)
  378. assert.Equal(t, pp.CAs[string("5c9c3f23e7ee7fe97637cbd3a0a5b854154d1d9aaaf7b566a51f4a88f76b64cd")].Details.Name, rootCA01.Details.Name)
  379. }
  380. func appendByteSlices(b ...[]byte) []byte {
  381. retSlice := []byte{}
  382. for _, v := range b {
  383. retSlice = append(retSlice, v...)
  384. }
  385. return retSlice
  386. }
  387. func TestUnmrshalCertPEM(t *testing.T) {
  388. goodCert := []byte(`
  389. # A good cert
  390. -----BEGIN NEBULA CERTIFICATE-----
  391. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  392. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  393. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  394. -----END NEBULA CERTIFICATE-----
  395. `)
  396. badBanner := []byte(`# A bad banner
  397. -----BEGIN NOT A NEBULA CERTIFICATE-----
  398. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  399. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  400. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  401. -----END NOT A NEBULA CERTIFICATE-----
  402. `)
  403. invalidPem := []byte(`# Not a valid PEM format
  404. -BEGIN NEBULA CERTIFICATE-----
  405. CkAKDm5lYnVsYSByb290IGNhKJfap9AFMJfg1+YGOiCUQGByMuNRhIlQBOyzXWbL
  406. vcKBwDhov900phEfJ5DN3kABEkDCq5R8qBiu8sl54yVfgRcQXEDt3cHr8UTSLszv
  407. bzBEr00kERQxxTzTsH8cpYEgRoipvmExvg8WP8NdAJEYJosB
  408. -END NEBULA CERTIFICATE----`)
  409. certBundle := appendByteSlices(goodCert, badBanner, invalidPem)
  410. // Success test case
  411. cert, rest, err := UnmarshalNebulaCertificateFromPEM(certBundle)
  412. assert.NotNil(t, cert)
  413. assert.Equal(t, rest, append(badBanner, invalidPem...))
  414. assert.Nil(t, err)
  415. // Fail due to invalid banner.
  416. cert, rest, err = UnmarshalNebulaCertificateFromPEM(rest)
  417. assert.Nil(t, cert)
  418. assert.Equal(t, rest, invalidPem)
  419. assert.EqualError(t, err, "bytes did not contain a proper nebula certificate banner")
  420. // Fail due to ivalid PEM format, because
  421. // it's missing the requisite pre-encapsulation boundary.
  422. cert, rest, err = UnmarshalNebulaCertificateFromPEM(rest)
  423. assert.Nil(t, cert)
  424. assert.Equal(t, rest, invalidPem)
  425. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  426. }
  427. func TestUnmarshalEd25519PrivateKey(t *testing.T) {
  428. privKey := []byte(`# A good key
  429. -----BEGIN NEBULA ED25519 PRIVATE KEY-----
  430. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  431. -----END NEBULA ED25519 PRIVATE KEY-----
  432. `)
  433. shortKey := []byte(`# A short key
  434. -----BEGIN NEBULA ED25519 PRIVATE KEY-----
  435. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
  436. -----END NEBULA ED25519 PRIVATE KEY-----
  437. `)
  438. invalidBanner := []byte(`# Invalid banner
  439. -----BEGIN NOT A NEBULA PRIVATE KEY-----
  440. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  441. -----END NOT A NEBULA PRIVATE KEY-----
  442. `)
  443. invalidPem := []byte(`# Not a valid PEM format
  444. -BEGIN NEBULA ED25519 PRIVATE KEY-----
  445. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  446. -END NEBULA ED25519 PRIVATE KEY-----`)
  447. keyBundle := appendByteSlices(privKey, shortKey, invalidBanner, invalidPem)
  448. // Success test case
  449. k, rest, err := UnmarshalEd25519PrivateKey(keyBundle)
  450. assert.Len(t, k, 64)
  451. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  452. assert.Nil(t, err)
  453. // Fail due to short key
  454. k, rest, err = UnmarshalEd25519PrivateKey(rest)
  455. assert.Nil(t, k)
  456. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  457. assert.EqualError(t, err, "key was not 64 bytes, is invalid ed25519 private key")
  458. // Fail due to invalid banner
  459. k, rest, err = UnmarshalEd25519PrivateKey(rest)
  460. assert.Nil(t, k)
  461. assert.Equal(t, rest, invalidPem)
  462. assert.EqualError(t, err, "bytes did not contain a proper nebula Ed25519 private key banner")
  463. // Fail due to ivalid PEM format, because
  464. // it's missing the requisite pre-encapsulation boundary.
  465. k, rest, err = UnmarshalEd25519PrivateKey(rest)
  466. assert.Nil(t, k)
  467. assert.Equal(t, rest, invalidPem)
  468. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  469. }
  470. func TestUnmarshalX25519PrivateKey(t *testing.T) {
  471. privKey := []byte(`# A good key
  472. -----BEGIN NEBULA X25519 PRIVATE KEY-----
  473. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  474. -----END NEBULA X25519 PRIVATE KEY-----
  475. `)
  476. shortKey := []byte(`# A short key
  477. -----BEGIN NEBULA X25519 PRIVATE KEY-----
  478. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  479. -----END NEBULA X25519 PRIVATE KEY-----
  480. `)
  481. invalidBanner := []byte(`# Invalid banner
  482. -----BEGIN NOT A NEBULA PRIVATE KEY-----
  483. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  484. -----END NOT A NEBULA PRIVATE KEY-----
  485. `)
  486. invalidPem := []byte(`# Not a valid PEM format
  487. -BEGIN NEBULA X25519 PRIVATE KEY-----
  488. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  489. -END NEBULA X25519 PRIVATE KEY-----`)
  490. keyBundle := appendByteSlices(privKey, shortKey, invalidBanner, invalidPem)
  491. // Success test case
  492. k, rest, err := UnmarshalX25519PrivateKey(keyBundle)
  493. assert.Len(t, k, 32)
  494. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  495. assert.Nil(t, err)
  496. // Fail due to short key
  497. k, rest, err = UnmarshalX25519PrivateKey(rest)
  498. assert.Nil(t, k)
  499. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  500. assert.EqualError(t, err, "key was not 32 bytes, is invalid X25519 private key")
  501. // Fail due to invalid banner
  502. k, rest, err = UnmarshalX25519PrivateKey(rest)
  503. assert.Nil(t, k)
  504. assert.Equal(t, rest, invalidPem)
  505. assert.EqualError(t, err, "bytes did not contain a proper nebula X25519 private key banner")
  506. // Fail due to ivalid PEM format, because
  507. // it's missing the requisite pre-encapsulation boundary.
  508. k, rest, err = UnmarshalX25519PrivateKey(rest)
  509. assert.Nil(t, k)
  510. assert.Equal(t, rest, invalidPem)
  511. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  512. }
  513. func TestUnmarshalEd25519PublicKey(t *testing.T) {
  514. pubKey := []byte(`# A good key
  515. -----BEGIN NEBULA ED25519 PUBLIC KEY-----
  516. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  517. -----END NEBULA ED25519 PUBLIC KEY-----
  518. `)
  519. shortKey := []byte(`# A short key
  520. -----BEGIN NEBULA ED25519 PUBLIC KEY-----
  521. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  522. -----END NEBULA ED25519 PUBLIC KEY-----
  523. `)
  524. invalidBanner := []byte(`# Invalid banner
  525. -----BEGIN NOT A NEBULA PUBLIC KEY-----
  526. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  527. -----END NOT A NEBULA PUBLIC KEY-----
  528. `)
  529. invalidPem := []byte(`# Not a valid PEM format
  530. -BEGIN NEBULA ED25519 PUBLIC KEY-----
  531. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  532. -END NEBULA ED25519 PUBLIC KEY-----`)
  533. keyBundle := appendByteSlices(pubKey, shortKey, invalidBanner, invalidPem)
  534. // Success test case
  535. k, rest, err := UnmarshalEd25519PublicKey(keyBundle)
  536. assert.Equal(t, len(k), 32)
  537. assert.Nil(t, err)
  538. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  539. // Fail due to short key
  540. k, rest, err = UnmarshalEd25519PublicKey(rest)
  541. assert.Nil(t, k)
  542. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  543. assert.EqualError(t, err, "key was not 32 bytes, is invalid ed25519 public key")
  544. // Fail due to invalid banner
  545. k, rest, err = UnmarshalEd25519PublicKey(rest)
  546. assert.Nil(t, k)
  547. assert.EqualError(t, err, "bytes did not contain a proper nebula Ed25519 public key banner")
  548. assert.Equal(t, rest, invalidPem)
  549. // Fail due to ivalid PEM format, because
  550. // it's missing the requisite pre-encapsulation boundary.
  551. k, rest, err = UnmarshalEd25519PublicKey(rest)
  552. assert.Nil(t, k)
  553. assert.Equal(t, rest, invalidPem)
  554. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  555. }
  556. func TestUnmarshalX25519PublicKey(t *testing.T) {
  557. pubKey := []byte(`# A good key
  558. -----BEGIN NEBULA X25519 PUBLIC KEY-----
  559. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  560. -----END NEBULA X25519 PUBLIC KEY-----
  561. `)
  562. shortKey := []byte(`# A short key
  563. -----BEGIN NEBULA X25519 PUBLIC KEY-----
  564. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
  565. -----END NEBULA X25519 PUBLIC KEY-----
  566. `)
  567. invalidBanner := []byte(`# Invalid banner
  568. -----BEGIN NOT A NEBULA PUBLIC KEY-----
  569. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  570. -----END NOT A NEBULA PUBLIC KEY-----
  571. `)
  572. invalidPem := []byte(`# Not a valid PEM format
  573. -BEGIN NEBULA X25519 PUBLIC KEY-----
  574. AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
  575. -END NEBULA X25519 PUBLIC KEY-----`)
  576. keyBundle := appendByteSlices(pubKey, shortKey, invalidBanner, invalidPem)
  577. // Success test case
  578. k, rest, err := UnmarshalX25519PublicKey(keyBundle)
  579. assert.Equal(t, len(k), 32)
  580. assert.Nil(t, err)
  581. assert.Equal(t, rest, appendByteSlices(shortKey, invalidBanner, invalidPem))
  582. // Fail due to short key
  583. k, rest, err = UnmarshalX25519PublicKey(rest)
  584. assert.Nil(t, k)
  585. assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
  586. assert.EqualError(t, err, "key was not 32 bytes, is invalid X25519 public key")
  587. // Fail due to invalid banner
  588. k, rest, err = UnmarshalX25519PublicKey(rest)
  589. assert.Nil(t, k)
  590. assert.EqualError(t, err, "bytes did not contain a proper nebula X25519 public key banner")
  591. assert.Equal(t, rest, invalidPem)
  592. // Fail due to ivalid PEM format, because
  593. // it's missing the requisite pre-encapsulation boundary.
  594. k, rest, err = UnmarshalX25519PublicKey(rest)
  595. assert.Nil(t, k)
  596. assert.Equal(t, rest, invalidPem)
  597. assert.EqualError(t, err, "input did not contain a valid PEM encoded block")
  598. }
  599. // Ensure that upgrading the protobuf library does not change how certificates
  600. // are marshalled, since this would break signature verification
  601. func TestMarshalingNebulaCertificateConsistency(t *testing.T) {
  602. before := time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
  603. after := time.Date(2017, time.January, 18, 28, 40, 0, 0, time.UTC)
  604. pubKey := []byte("1234567890abcedfghij1234567890ab")
  605. nc := NebulaCertificate{
  606. Details: NebulaCertificateDetails{
  607. Name: "testing",
  608. Ips: []*net.IPNet{
  609. {IP: net.ParseIP("10.1.1.1"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  610. {IP: net.ParseIP("10.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  611. {IP: net.ParseIP("10.1.1.3"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  612. },
  613. Subnets: []*net.IPNet{
  614. {IP: net.ParseIP("9.1.1.1"), Mask: net.IPMask(net.ParseIP("255.0.255.0"))},
  615. {IP: net.ParseIP("9.1.1.2"), Mask: net.IPMask(net.ParseIP("255.255.255.0"))},
  616. {IP: net.ParseIP("9.1.1.3"), Mask: net.IPMask(net.ParseIP("255.255.0.0"))},
  617. },
  618. Groups: []string{"test-group1", "test-group2", "test-group3"},
  619. NotBefore: before,
  620. NotAfter: after,
  621. PublicKey: pubKey,
  622. IsCA: false,
  623. Issuer: "1234567890abcedfghij1234567890ab",
  624. },
  625. Signature: []byte("1234567890abcedfghij1234567890ab"),
  626. }
  627. b, err := nc.Marshal()
  628. assert.Nil(t, err)
  629. //t.Log("Cert size:", len(b))
  630. assert.Equal(t, "0aa2010a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf1220313233343536373839306162636564666768696a313233343536373839306162", fmt.Sprintf("%x", b))
  631. b, err = proto.Marshal(nc.getRawDetails())
  632. assert.Nil(t, err)
  633. //t.Log("Raw cert size:", len(b))
  634. assert.Equal(t, "0a0774657374696e67121b8182845080feffff0f828284508080fcff0f8382845080fe83f80f1a1b8182844880fe83f80f8282844880feffff0f838284488080fcff0f220b746573742d67726f757031220b746573742d67726f757032220b746573742d67726f75703328f0e0e7d70430a08681c4053a20313233343536373839306162636564666768696a3132333435363738393061624a081234567890abcedf", fmt.Sprintf("%x", b))
  635. }
  636. func TestNebulaCertificate_Copy(t *testing.T) {
  637. ca, _, caKey, err := newTestCaCert(time.Now(), time.Now().Add(10*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  638. assert.Nil(t, err)
  639. c, _, _, err := newTestCert(ca, caKey, time.Now(), time.Now().Add(5*time.Minute), []*net.IPNet{}, []*net.IPNet{}, []string{})
  640. assert.Nil(t, err)
  641. cc := c.Copy()
  642. util.AssertDeepCopyEqual(t, c, cc)
  643. }
  644. func TestUnmarshalNebulaCertificate(t *testing.T) {
  645. // Test that we don't panic with an invalid certificate (#332)
  646. data := []byte("\x98\x00\x00")
  647. _, err := UnmarshalNebulaCertificate(data)
  648. assert.EqualError(t, err, "encoded Details was nil")
  649. }
  650. func newTestCaCert(before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  651. pub, priv, err := ed25519.GenerateKey(rand.Reader)
  652. if before.IsZero() {
  653. before = time.Now().Add(time.Second * -60).Round(time.Second)
  654. }
  655. if after.IsZero() {
  656. after = time.Now().Add(time.Second * 60).Round(time.Second)
  657. }
  658. nc := &NebulaCertificate{
  659. Details: NebulaCertificateDetails{
  660. Name: "test ca",
  661. NotBefore: time.Unix(before.Unix(), 0),
  662. NotAfter: time.Unix(after.Unix(), 0),
  663. PublicKey: pub,
  664. IsCA: true,
  665. InvertedGroups: make(map[string]struct{}),
  666. },
  667. }
  668. if len(ips) > 0 {
  669. nc.Details.Ips = ips
  670. }
  671. if len(subnets) > 0 {
  672. nc.Details.Subnets = subnets
  673. }
  674. if len(groups) > 0 {
  675. nc.Details.Groups = groups
  676. }
  677. err = nc.Sign(priv)
  678. if err != nil {
  679. return nil, nil, nil, err
  680. }
  681. return nc, pub, priv, nil
  682. }
  683. func newTestCert(ca *NebulaCertificate, key []byte, before, after time.Time, ips, subnets []*net.IPNet, groups []string) (*NebulaCertificate, []byte, []byte, error) {
  684. issuer, err := ca.Sha256Sum()
  685. if err != nil {
  686. return nil, nil, nil, err
  687. }
  688. if before.IsZero() {
  689. before = time.Now().Add(time.Second * -60).Round(time.Second)
  690. }
  691. if after.IsZero() {
  692. after = time.Now().Add(time.Second * 60).Round(time.Second)
  693. }
  694. if len(groups) == 0 {
  695. groups = []string{"test-group1", "test-group2", "test-group3"}
  696. }
  697. if len(ips) == 0 {
  698. ips = []*net.IPNet{
  699. {IP: net.ParseIP("10.1.1.1").To4(), Mask: net.IPMask(net.ParseIP("255.255.255.0").To4())},
  700. {IP: net.ParseIP("10.1.1.2").To4(), Mask: net.IPMask(net.ParseIP("255.255.0.0").To4())},
  701. {IP: net.ParseIP("10.1.1.3").To4(), Mask: net.IPMask(net.ParseIP("255.0.255.0").To4())},
  702. }
  703. }
  704. if len(subnets) == 0 {
  705. subnets = []*net.IPNet{
  706. {IP: net.ParseIP("9.1.1.1").To4(), Mask: net.IPMask(net.ParseIP("255.0.255.0").To4())},
  707. {IP: net.ParseIP("9.1.1.2").To4(), Mask: net.IPMask(net.ParseIP("255.255.255.0").To4())},
  708. {IP: net.ParseIP("9.1.1.3").To4(), Mask: net.IPMask(net.ParseIP("255.255.0.0").To4())},
  709. }
  710. }
  711. pub, rawPriv := x25519Keypair()
  712. nc := &NebulaCertificate{
  713. Details: NebulaCertificateDetails{
  714. Name: "testing",
  715. Ips: ips,
  716. Subnets: subnets,
  717. Groups: groups,
  718. NotBefore: time.Unix(before.Unix(), 0),
  719. NotAfter: time.Unix(after.Unix(), 0),
  720. PublicKey: pub,
  721. IsCA: false,
  722. Issuer: issuer,
  723. InvertedGroups: make(map[string]struct{}),
  724. },
  725. }
  726. err = nc.Sign(key)
  727. if err != nil {
  728. return nil, nil, nil, err
  729. }
  730. return nc, pub, rawPriv, nil
  731. }
  732. func x25519Keypair() ([]byte, []byte) {
  733. var pubkey, privkey [32]byte
  734. if _, err := io.ReadFull(rand.Reader, privkey[:]); err != nil {
  735. panic(err)
  736. }
  737. curve25519.ScalarBaseMult(&pubkey, &privkey)
  738. return pubkey[:], privkey[:]
  739. }