sign_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. //go:build !windows
  2. // +build !windows
  3. package main
  4. import (
  5. "bytes"
  6. "crypto/rand"
  7. "errors"
  8. "os"
  9. "testing"
  10. "time"
  11. "github.com/slackhq/nebula/cert"
  12. "github.com/stretchr/testify/assert"
  13. "golang.org/x/crypto/ed25519"
  14. )
  15. func Test_signSummary(t *testing.T) {
  16. assert.Equal(t, "sign <flags>: create and sign a certificate", signSummary())
  17. }
  18. func Test_signHelp(t *testing.T) {
  19. ob := &bytes.Buffer{}
  20. signHelp(ob)
  21. assert.Equal(
  22. t,
  23. "Usage of "+os.Args[0]+" sign <flags>: create and sign a certificate\n"+
  24. " -ca-crt string\n"+
  25. " \tOptional: path to the signing CA cert (default \"ca.crt\")\n"+
  26. " -ca-key string\n"+
  27. " \tOptional: path to the signing CA key (default \"ca.key\")\n"+
  28. " -duration duration\n"+
  29. " \tOptional: how long the cert should be valid for. The default is 1 second before the signing cert expires. Valid time units are seconds: \"s\", minutes: \"m\", hours: \"h\"\n"+
  30. " -groups string\n"+
  31. " \tOptional: comma separated list of groups\n"+
  32. " -in-pub string\n"+
  33. " \tOptional (if out-key not set): path to read a previously generated public key\n"+
  34. " -ip string\n"+
  35. " \tDeprecated, see -networks\n"+
  36. " -name string\n"+
  37. " \tRequired: name of the cert, usually a hostname\n"+
  38. " -networks string\n"+
  39. " \tRequired: comma separated list of ip address and network in CIDR notation to assign to this cert\n"+
  40. " -out-crt string\n"+
  41. " \tOptional: path to write the certificate to\n"+
  42. " -out-key string\n"+
  43. " \tOptional (if in-pub not set): path to write the private key to\n"+
  44. " -out-qr string\n"+
  45. " \tOptional: output a qr code image (png) of the certificate\n"+
  46. optionalPkcs11String(" -pkcs11 string\n \tOptional: PKCS#11 URI to an existing private key\n")+
  47. " -subnets string\n"+
  48. " \tDeprecated, see -unsafe-networks\n"+
  49. " -unsafe-networks string\n"+
  50. " \tOptional: comma separated list of ip address and network in CIDR notation. Unsafe networks this cert can route for\n"+
  51. " -version uint\n"+
  52. " \tOptional: version of the certificate format to use, the default is to create both v1 and v2 certificates.\n",
  53. ob.String(),
  54. )
  55. }
  56. func Test_signCert(t *testing.T) {
  57. ob := &bytes.Buffer{}
  58. eb := &bytes.Buffer{}
  59. nopw := &StubPasswordReader{
  60. password: []byte(""),
  61. err: nil,
  62. }
  63. errpw := &StubPasswordReader{
  64. password: []byte(""),
  65. err: errors.New("stub error"),
  66. }
  67. passphrase := []byte("DO NOT USE THIS KEY")
  68. testpw := &StubPasswordReader{
  69. password: passphrase,
  70. err: nil,
  71. }
  72. // required args
  73. assertHelpError(t, signCert(
  74. []string{"-version", "1", "-ca-crt", "./nope", "-ca-key", "./nope", "-ip", "1.1.1.1/24", "-out-key", "nope", "-out-crt", "nope"}, ob, eb, nopw,
  75. ), "-name is required")
  76. assert.Empty(t, ob.String())
  77. assert.Empty(t, eb.String())
  78. assertHelpError(t, signCert(
  79. []string{"-version", "1", "-ca-crt", "./nope", "-ca-key", "./nope", "-name", "test", "-out-key", "nope", "-out-crt", "nope"}, ob, eb, nopw,
  80. ), "-networks is required")
  81. assert.Empty(t, ob.String())
  82. assert.Empty(t, eb.String())
  83. // cannot set -in-pub and -out-key
  84. assertHelpError(t, signCert(
  85. []string{"-version", "1", "-ca-crt", "./nope", "-ca-key", "./nope", "-name", "test", "-in-pub", "nope", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope"}, ob, eb, nopw,
  86. ), "cannot set both -in-pub and -out-key")
  87. assert.Empty(t, ob.String())
  88. assert.Empty(t, eb.String())
  89. // failed to read key
  90. ob.Reset()
  91. eb.Reset()
  92. args := []string{"-version", "1", "-ca-crt", "./nope", "-ca-key", "./nope", "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m"}
  93. assert.EqualError(t, signCert(args, ob, eb, nopw), "error while reading ca-key: open ./nope: "+NoSuchFileError)
  94. // failed to unmarshal key
  95. ob.Reset()
  96. eb.Reset()
  97. caKeyF, err := os.CreateTemp("", "sign-cert.key")
  98. assert.Nil(t, err)
  99. defer os.Remove(caKeyF.Name())
  100. args = []string{"-version", "1", "-ca-crt", "./nope", "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m"}
  101. assert.EqualError(t, signCert(args, ob, eb, nopw), "error while parsing ca-key: input did not contain a valid PEM encoded block")
  102. assert.Empty(t, ob.String())
  103. assert.Empty(t, eb.String())
  104. // Write a proper ca key for later
  105. ob.Reset()
  106. eb.Reset()
  107. caPub, caPriv, _ := ed25519.GenerateKey(rand.Reader)
  108. caKeyF.Write(cert.MarshalSigningPrivateKeyToPEM(cert.Curve_CURVE25519, caPriv))
  109. // failed to read cert
  110. args = []string{"-version", "1", "-ca-crt", "./nope", "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m"}
  111. assert.EqualError(t, signCert(args, ob, eb, nopw), "error while reading ca-crt: open ./nope: "+NoSuchFileError)
  112. assert.Empty(t, ob.String())
  113. assert.Empty(t, eb.String())
  114. // failed to unmarshal cert
  115. ob.Reset()
  116. eb.Reset()
  117. caCrtF, err := os.CreateTemp("", "sign-cert.crt")
  118. assert.Nil(t, err)
  119. defer os.Remove(caCrtF.Name())
  120. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m"}
  121. assert.EqualError(t, signCert(args, ob, eb, nopw), "error while parsing ca-crt: input did not contain a valid PEM encoded block")
  122. assert.Empty(t, ob.String())
  123. assert.Empty(t, eb.String())
  124. // write a proper ca cert for later
  125. ca, _ := NewTestCaCert("ca", caPub, caPriv, time.Now(), time.Now().Add(time.Minute*200), nil, nil, nil)
  126. b, _ := ca.MarshalPEM()
  127. caCrtF.Write(b)
  128. // failed to read pub
  129. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-in-pub", "./nope", "-duration", "100m"}
  130. assert.EqualError(t, signCert(args, ob, eb, nopw), "error while reading in-pub: open ./nope: "+NoSuchFileError)
  131. assert.Empty(t, ob.String())
  132. assert.Empty(t, eb.String())
  133. // failed to unmarshal pub
  134. ob.Reset()
  135. eb.Reset()
  136. inPubF, err := os.CreateTemp("", "in.pub")
  137. assert.Nil(t, err)
  138. defer os.Remove(inPubF.Name())
  139. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-in-pub", inPubF.Name(), "-duration", "100m"}
  140. assert.EqualError(t, signCert(args, ob, eb, nopw), "error while parsing in-pub: input did not contain a valid PEM encoded block")
  141. assert.Empty(t, ob.String())
  142. assert.Empty(t, eb.String())
  143. // write a proper pub for later
  144. ob.Reset()
  145. eb.Reset()
  146. inPub, _ := x25519Keypair()
  147. inPubF.Write(cert.MarshalPublicKeyToPEM(cert.Curve_CURVE25519, inPub))
  148. // bad ip cidr
  149. ob.Reset()
  150. eb.Reset()
  151. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "a1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m"}
  152. assertHelpError(t, signCert(args, ob, eb, nopw), "invalid -networks definition: a1.1.1.1/24")
  153. assert.Empty(t, ob.String())
  154. assert.Empty(t, eb.String())
  155. ob.Reset()
  156. eb.Reset()
  157. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "100::100/100", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m"}
  158. assertHelpError(t, signCert(args, ob, eb, nopw), "invalid -networks definition: v1 certificates can only have a single ipv4 address")
  159. assert.Empty(t, ob.String())
  160. assert.Empty(t, eb.String())
  161. ob.Reset()
  162. eb.Reset()
  163. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24,1.1.1.2/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m"}
  164. assertHelpError(t, signCert(args, ob, eb, nopw), "invalid -networks definition: v1 certificates can only have a single ipv4 address")
  165. assert.Empty(t, ob.String())
  166. assert.Empty(t, eb.String())
  167. // bad subnet cidr
  168. ob.Reset()
  169. eb.Reset()
  170. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m", "-subnets", "a"}
  171. assertHelpError(t, signCert(args, ob, eb, nopw), "invalid -unsafe-networks definition: a")
  172. assert.Empty(t, ob.String())
  173. assert.Empty(t, eb.String())
  174. ob.Reset()
  175. eb.Reset()
  176. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m", "-subnets", "100::100/100"}
  177. assertHelpError(t, signCert(args, ob, eb, nopw), "invalid -unsafe-networks definition: v1 certificates can only be ipv4")
  178. assert.Empty(t, ob.String())
  179. assert.Empty(t, eb.String())
  180. // mismatched ca key
  181. _, caPriv2, _ := ed25519.GenerateKey(rand.Reader)
  182. caKeyF2, err := os.CreateTemp("", "sign-cert-2.key")
  183. assert.Nil(t, err)
  184. defer os.Remove(caKeyF2.Name())
  185. caKeyF2.Write(cert.MarshalSigningPrivateKeyToPEM(cert.Curve_CURVE25519, caPriv2))
  186. ob.Reset()
  187. eb.Reset()
  188. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF2.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "nope", "-out-key", "nope", "-duration", "100m", "-subnets", "a"}
  189. assert.EqualError(t, signCert(args, ob, eb, nopw), "refusing to sign, root certificate does not match private key")
  190. assert.Empty(t, ob.String())
  191. assert.Empty(t, eb.String())
  192. // failed key write
  193. ob.Reset()
  194. eb.Reset()
  195. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "/do/not/write/pleasecrt", "-out-key", "/do/not/write/pleasekey", "-duration", "100m", "-subnets", "10.1.1.1/32"}
  196. assert.EqualError(t, signCert(args, ob, eb, nopw), "error while writing out-key: open /do/not/write/pleasekey: "+NoSuchDirError)
  197. assert.Empty(t, ob.String())
  198. assert.Empty(t, eb.String())
  199. // create temp key file
  200. keyF, err := os.CreateTemp("", "test.key")
  201. assert.Nil(t, err)
  202. os.Remove(keyF.Name())
  203. // failed cert write
  204. ob.Reset()
  205. eb.Reset()
  206. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", "/do/not/write/pleasecrt", "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32"}
  207. assert.EqualError(t, signCert(args, ob, eb, nopw), "error while writing out-crt: open /do/not/write/pleasecrt: "+NoSuchDirError)
  208. assert.Empty(t, ob.String())
  209. assert.Empty(t, eb.String())
  210. os.Remove(keyF.Name())
  211. // create temp cert file
  212. crtF, err := os.CreateTemp("", "test.crt")
  213. assert.Nil(t, err)
  214. os.Remove(crtF.Name())
  215. // test proper cert with removed empty groups and subnets
  216. ob.Reset()
  217. eb.Reset()
  218. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  219. assert.Nil(t, signCert(args, ob, eb, nopw))
  220. assert.Empty(t, ob.String())
  221. assert.Empty(t, eb.String())
  222. // read cert and key files
  223. rb, _ := os.ReadFile(keyF.Name())
  224. lKey, b, curve, err := cert.UnmarshalPrivateKeyFromPEM(rb)
  225. assert.Equal(t, cert.Curve_CURVE25519, curve)
  226. assert.Len(t, b, 0)
  227. assert.Nil(t, err)
  228. assert.Len(t, lKey, 32)
  229. rb, _ = os.ReadFile(crtF.Name())
  230. lCrt, b, err := cert.UnmarshalCertificateFromPEM(rb)
  231. assert.Len(t, b, 0)
  232. assert.Nil(t, err)
  233. assert.Equal(t, "test", lCrt.Name())
  234. assert.Equal(t, "1.1.1.1/24", lCrt.Networks()[0].String())
  235. assert.Len(t, lCrt.Networks(), 1)
  236. assert.False(t, lCrt.IsCA())
  237. assert.Equal(t, []string{"1", "2", "3", "4", "5"}, lCrt.Groups())
  238. assert.Len(t, lCrt.UnsafeNetworks(), 3)
  239. assert.Len(t, lCrt.PublicKey(), 32)
  240. assert.Equal(t, time.Duration(time.Minute*100), lCrt.NotAfter().Sub(lCrt.NotBefore()))
  241. sns := []string{}
  242. for _, sn := range lCrt.UnsafeNetworks() {
  243. sns = append(sns, sn.String())
  244. }
  245. assert.Equal(t, []string{"10.1.1.1/32", "10.2.2.2/32", "10.5.5.5/32"}, sns)
  246. issuer, _ := ca.Fingerprint()
  247. assert.Equal(t, issuer, lCrt.Issuer())
  248. assert.True(t, lCrt.CheckSignature(caPub))
  249. // test proper cert with in-pub
  250. os.Remove(keyF.Name())
  251. os.Remove(crtF.Name())
  252. ob.Reset()
  253. eb.Reset()
  254. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-in-pub", inPubF.Name(), "-duration", "100m", "-groups", "1"}
  255. assert.Nil(t, signCert(args, ob, eb, nopw))
  256. assert.Empty(t, ob.String())
  257. assert.Empty(t, eb.String())
  258. // read cert file and check pub key matches in-pub
  259. rb, _ = os.ReadFile(crtF.Name())
  260. lCrt, b, err = cert.UnmarshalCertificateFromPEM(rb)
  261. assert.Len(t, b, 0)
  262. assert.Nil(t, err)
  263. assert.Equal(t, lCrt.PublicKey(), inPub)
  264. // test refuse to sign cert with duration beyond root
  265. ob.Reset()
  266. eb.Reset()
  267. os.Remove(keyF.Name())
  268. os.Remove(crtF.Name())
  269. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "1000m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  270. assert.EqualError(t, signCert(args, ob, eb, nopw), "error while signing: certificate expires after signing certificate")
  271. assert.Empty(t, ob.String())
  272. assert.Empty(t, eb.String())
  273. // create valid cert/key for overwrite tests
  274. os.Remove(keyF.Name())
  275. os.Remove(crtF.Name())
  276. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  277. assert.Nil(t, signCert(args, ob, eb, nopw))
  278. // test that we won't overwrite existing key file
  279. os.Remove(crtF.Name())
  280. ob.Reset()
  281. eb.Reset()
  282. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  283. assert.EqualError(t, signCert(args, ob, eb, nopw), "refusing to overwrite existing key: "+keyF.Name())
  284. assert.Empty(t, ob.String())
  285. assert.Empty(t, eb.String())
  286. // create valid cert/key for overwrite tests
  287. os.Remove(keyF.Name())
  288. os.Remove(crtF.Name())
  289. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  290. assert.Nil(t, signCert(args, ob, eb, nopw))
  291. // test that we won't overwrite existing certificate file
  292. os.Remove(keyF.Name())
  293. ob.Reset()
  294. eb.Reset()
  295. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  296. assert.EqualError(t, signCert(args, ob, eb, nopw), "refusing to overwrite existing cert: "+crtF.Name())
  297. assert.Empty(t, ob.String())
  298. assert.Empty(t, eb.String())
  299. // create valid cert/key using encrypted CA key
  300. os.Remove(caKeyF.Name())
  301. os.Remove(caCrtF.Name())
  302. os.Remove(keyF.Name())
  303. os.Remove(crtF.Name())
  304. ob.Reset()
  305. eb.Reset()
  306. caKeyF, err = os.CreateTemp("", "sign-cert.key")
  307. assert.Nil(t, err)
  308. defer os.Remove(caKeyF.Name())
  309. caCrtF, err = os.CreateTemp("", "sign-cert.crt")
  310. assert.Nil(t, err)
  311. defer os.Remove(caCrtF.Name())
  312. // generate the encrypted key
  313. caPub, caPriv, _ = ed25519.GenerateKey(rand.Reader)
  314. kdfParams := cert.NewArgon2Parameters(64*1024, 4, 3)
  315. b, _ = cert.EncryptAndMarshalSigningPrivateKey(cert.Curve_CURVE25519, caPriv, passphrase, kdfParams)
  316. caKeyF.Write(b)
  317. ca, _ = NewTestCaCert("ca", caPub, caPriv, time.Now(), time.Now().Add(time.Minute*200), nil, nil, nil)
  318. b, _ = ca.MarshalPEM()
  319. caCrtF.Write(b)
  320. // test with the proper password
  321. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  322. assert.Nil(t, signCert(args, ob, eb, testpw))
  323. assert.Equal(t, "Enter passphrase: ", ob.String())
  324. assert.Empty(t, eb.String())
  325. // test with the wrong password
  326. ob.Reset()
  327. eb.Reset()
  328. testpw.password = []byte("invalid password")
  329. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  330. assert.Error(t, signCert(args, ob, eb, testpw))
  331. assert.Equal(t, "Enter passphrase: ", ob.String())
  332. assert.Empty(t, eb.String())
  333. // test with the user not entering a password
  334. ob.Reset()
  335. eb.Reset()
  336. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  337. assert.Error(t, signCert(args, ob, eb, nopw))
  338. // normally the user hitting enter on the prompt would add newlines between these
  339. assert.Equal(t, "Enter passphrase: Enter passphrase: Enter passphrase: Enter passphrase: Enter passphrase: ", ob.String())
  340. assert.Empty(t, eb.String())
  341. // test an error condition
  342. ob.Reset()
  343. eb.Reset()
  344. args = []string{"-version", "1", "-ca-crt", caCrtF.Name(), "-ca-key", caKeyF.Name(), "-name", "test", "-ip", "1.1.1.1/24", "-out-crt", crtF.Name(), "-out-key", keyF.Name(), "-duration", "100m", "-subnets", "10.1.1.1/32, , 10.2.2.2/32 , , ,, 10.5.5.5/32", "-groups", "1,, 2 , ,,,3,4,5"}
  345. assert.Error(t, signCert(args, ob, eb, errpw))
  346. assert.Equal(t, "Enter passphrase: ", ob.String())
  347. assert.Empty(t, eb.String())
  348. }