ca_test.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. //go:build !windows
  2. // +build !windows
  3. package main
  4. import (
  5. "bytes"
  6. "io/ioutil"
  7. "os"
  8. "testing"
  9. "time"
  10. "github.com/slackhq/nebula/cert"
  11. "github.com/stretchr/testify/assert"
  12. )
  13. //TODO: test file permissions
  14. func Test_caSummary(t *testing.T) {
  15. assert.Equal(t, "ca <flags>: create a self signed certificate authority", caSummary())
  16. }
  17. func Test_caHelp(t *testing.T) {
  18. ob := &bytes.Buffer{}
  19. caHelp(ob)
  20. assert.Equal(
  21. t,
  22. "Usage of "+os.Args[0]+" ca <flags>: create a self signed certificate authority\n"+
  23. " -duration duration\n"+
  24. " \tOptional: amount of time the certificate should be valid for. Valid time units are seconds: \"s\", minutes: \"m\", hours: \"h\" (default 8760h0m0s)\n"+
  25. " -groups string\n"+
  26. " \tOptional: comma separated list of groups. This will limit which groups subordinate certs can use\n"+
  27. " -ips string\n"+
  28. " \tOptional: comma separated list of ip and network in CIDR notation. This will limit which ip addresses and networks subordinate certs can use\n"+
  29. " -name string\n"+
  30. " \tRequired: name of the certificate authority\n"+
  31. " -out-crt string\n"+
  32. " \tOptional: path to write the certificate to (default \"ca.crt\")\n"+
  33. " -out-key string\n"+
  34. " \tOptional: path to write the private key to (default \"ca.key\")\n"+
  35. " -out-qr string\n"+
  36. " \tOptional: output a qr code image (png) of the certificate\n"+
  37. " -subnets string\n"+
  38. " \tOptional: comma separated list of ip and network in CIDR notation. This will limit which subnet addresses and networks subordinate certs can use\n",
  39. ob.String(),
  40. )
  41. }
  42. func Test_ca(t *testing.T) {
  43. ob := &bytes.Buffer{}
  44. eb := &bytes.Buffer{}
  45. // required args
  46. assertHelpError(t, ca([]string{"-out-key", "nope", "-out-crt", "nope", "duration", "100m"}, ob, eb), "-name is required")
  47. assert.Equal(t, "", ob.String())
  48. assert.Equal(t, "", eb.String())
  49. // failed key write
  50. ob.Reset()
  51. eb.Reset()
  52. args := []string{"-name", "test", "-duration", "100m", "-out-crt", "/do/not/write/pleasecrt", "-out-key", "/do/not/write/pleasekey"}
  53. assert.EqualError(t, ca(args, ob, eb), "error while writing out-key: open /do/not/write/pleasekey: "+NoSuchDirError)
  54. assert.Equal(t, "", ob.String())
  55. assert.Equal(t, "", eb.String())
  56. // create temp key file
  57. keyF, err := ioutil.TempFile("", "test.key")
  58. assert.Nil(t, err)
  59. os.Remove(keyF.Name())
  60. // failed cert write
  61. ob.Reset()
  62. eb.Reset()
  63. args = []string{"-name", "test", "-duration", "100m", "-out-crt", "/do/not/write/pleasecrt", "-out-key", keyF.Name()}
  64. assert.EqualError(t, ca(args, ob, eb), "error while writing out-crt: open /do/not/write/pleasecrt: "+NoSuchDirError)
  65. assert.Equal(t, "", ob.String())
  66. assert.Equal(t, "", eb.String())
  67. // create temp cert file
  68. crtF, err := ioutil.TempFile("", "test.crt")
  69. assert.Nil(t, err)
  70. os.Remove(crtF.Name())
  71. os.Remove(keyF.Name())
  72. // test proper cert with removed empty groups and subnets
  73. ob.Reset()
  74. eb.Reset()
  75. args = []string{"-name", "test", "-duration", "100m", "-groups", "1,, 2 , ,,,3,4,5", "-out-crt", crtF.Name(), "-out-key", keyF.Name()}
  76. assert.Nil(t, ca(args, ob, eb))
  77. assert.Equal(t, "", ob.String())
  78. assert.Equal(t, "", eb.String())
  79. // read cert and key files
  80. rb, _ := ioutil.ReadFile(keyF.Name())
  81. lKey, b, err := cert.UnmarshalEd25519PrivateKey(rb)
  82. assert.Len(t, b, 0)
  83. assert.Nil(t, err)
  84. assert.Len(t, lKey, 64)
  85. rb, _ = ioutil.ReadFile(crtF.Name())
  86. lCrt, b, err := cert.UnmarshalNebulaCertificateFromPEM(rb)
  87. assert.Len(t, b, 0)
  88. assert.Nil(t, err)
  89. assert.Equal(t, "test", lCrt.Details.Name)
  90. assert.Len(t, lCrt.Details.Ips, 0)
  91. assert.True(t, lCrt.Details.IsCA)
  92. assert.Equal(t, []string{"1", "2", "3", "4", "5"}, lCrt.Details.Groups)
  93. assert.Len(t, lCrt.Details.Subnets, 0)
  94. assert.Len(t, lCrt.Details.PublicKey, 32)
  95. assert.Equal(t, time.Duration(time.Minute*100), lCrt.Details.NotAfter.Sub(lCrt.Details.NotBefore))
  96. assert.Equal(t, "", lCrt.Details.Issuer)
  97. assert.True(t, lCrt.CheckSignature(lCrt.Details.PublicKey))
  98. // create valid cert/key for overwrite tests
  99. os.Remove(keyF.Name())
  100. os.Remove(crtF.Name())
  101. ob.Reset()
  102. eb.Reset()
  103. args = []string{"-name", "test", "-duration", "100m", "-groups", "1,, 2 , ,,,3,4,5", "-out-crt", crtF.Name(), "-out-key", keyF.Name()}
  104. assert.Nil(t, ca(args, ob, eb))
  105. // test that we won't overwrite existing certificate file
  106. ob.Reset()
  107. eb.Reset()
  108. args = []string{"-name", "test", "-duration", "100m", "-groups", "1,, 2 , ,,,3,4,5", "-out-crt", crtF.Name(), "-out-key", keyF.Name()}
  109. assert.EqualError(t, ca(args, ob, eb), "refusing to overwrite existing CA key: "+keyF.Name())
  110. assert.Equal(t, "", ob.String())
  111. assert.Equal(t, "", eb.String())
  112. // test that we won't overwrite existing key file
  113. os.Remove(keyF.Name())
  114. ob.Reset()
  115. eb.Reset()
  116. args = []string{"-name", "test", "-duration", "100m", "-groups", "1,, 2 , ,,,3,4,5", "-out-crt", crtF.Name(), "-out-key", keyF.Name()}
  117. assert.EqualError(t, ca(args, ob, eb), "refusing to overwrite existing CA cert: "+crtF.Name())
  118. assert.Equal(t, "", ob.String())
  119. assert.Equal(t, "", eb.String())
  120. os.Remove(keyF.Name())
  121. }