github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/helper/tlsutil/generate_test.go (about) 1 package tlsutil 2 3 import ( 4 "crypto" 5 "crypto/ecdsa" 6 "crypto/elliptic" 7 "crypto/rand" 8 "crypto/rsa" 9 "crypto/x509" 10 "encoding/pem" 11 "io" 12 "net" 13 "strings" 14 "testing" 15 "time" 16 17 "github.com/hashicorp/nomad/ci" 18 "github.com/stretchr/testify/require" 19 ) 20 21 func TestSerialNumber(t *testing.T) { 22 n1, err := GenerateSerialNumber() 23 require.Nil(t, err) 24 25 n2, err := GenerateSerialNumber() 26 require.Nil(t, err) 27 require.NotEqual(t, n1, n2) 28 29 n3, err := GenerateSerialNumber() 30 require.Nil(t, err) 31 require.NotEqual(t, n1, n3) 32 require.NotEqual(t, n2, n3) 33 34 } 35 36 func TestGeneratePrivateKey(t *testing.T) { 37 ci.Parallel(t) 38 _, p, err := GeneratePrivateKey() 39 require.Nil(t, err) 40 require.NotEmpty(t, p) 41 require.Contains(t, p, "BEGIN EC PRIVATE KEY") 42 require.Contains(t, p, "END EC PRIVATE KEY") 43 44 block, _ := pem.Decode([]byte(p)) 45 pk, err := x509.ParseECPrivateKey(block.Bytes) 46 47 require.Nil(t, err) 48 require.NotNil(t, pk) 49 require.Equal(t, 256, pk.Params().BitSize) 50 } 51 52 type TestSigner struct { 53 public interface{} 54 } 55 56 func (s *TestSigner) Public() crypto.PublicKey { 57 return s.public 58 } 59 60 func (s *TestSigner) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) { 61 return []byte{}, nil 62 } 63 64 func TestGenerateCA(t *testing.T) { 65 ci.Parallel(t) 66 67 t.Run("no signer", func(t *testing.T) { 68 ca, pk, err := GenerateCA(CAOpts{Signer: &TestSigner{}}) 69 require.Error(t, err) 70 require.Empty(t, ca) 71 require.Empty(t, pk) 72 }) 73 74 t.Run("wrong key", func(t *testing.T) { 75 ca, pk, err := GenerateCA(CAOpts{Signer: &TestSigner{public: &rsa.PublicKey{}}}) 76 require.Error(t, err) 77 require.Empty(t, ca) 78 require.Empty(t, pk) 79 }) 80 81 t.Run("valid key", func(t *testing.T) { 82 ca, pk, err := GenerateCA(CAOpts{}) 83 require.Nil(t, err) 84 require.NotEmpty(t, ca) 85 require.NotEmpty(t, pk) 86 87 cert, err := parseCert(ca) 88 require.Nil(t, err) 89 require.True(t, strings.HasPrefix(cert.Subject.CommonName, "Nomad Agent CA")) 90 require.Equal(t, true, cert.IsCA) 91 require.Equal(t, true, cert.BasicConstraintsValid) 92 93 require.WithinDuration(t, cert.NotBefore, time.Now(), time.Minute) 94 require.WithinDuration(t, cert.NotAfter, time.Now().AddDate(0, 0, 365), time.Minute) 95 96 require.Equal(t, x509.KeyUsageCertSign|x509.KeyUsageCRLSign|x509.KeyUsageDigitalSignature, cert.KeyUsage) 97 }) 98 99 t.Run("RSA key", func(t *testing.T) { 100 ca, pk, err := GenerateCA(CAOpts{}) 101 require.NoError(t, err) 102 require.NotEmpty(t, ca) 103 require.NotEmpty(t, pk) 104 105 cert, err := parseCert(ca) 106 require.NoError(t, err) 107 require.True(t, strings.HasPrefix(cert.Subject.CommonName, "Nomad Agent CA")) 108 require.Equal(t, true, cert.IsCA) 109 require.Equal(t, true, cert.BasicConstraintsValid) 110 111 require.WithinDuration(t, cert.NotBefore, time.Now(), time.Minute) 112 require.WithinDuration(t, cert.NotAfter, time.Now().AddDate(0, 0, 365), time.Minute) 113 114 require.Equal(t, x509.KeyUsageCertSign|x509.KeyUsageCRLSign|x509.KeyUsageDigitalSignature, cert.KeyUsage) 115 }) 116 } 117 118 func TestGenerateCert(t *testing.T) { 119 ci.Parallel(t) 120 121 signer, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) 122 require.Nil(t, err) 123 ca, _, err := GenerateCA(CAOpts{Signer: signer}) 124 require.Nil(t, err) 125 126 DNSNames := []string{"server.dc1.consul"} 127 IPAddresses := []net.IP{net.ParseIP("123.234.243.213")} 128 extKeyUsage := []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth} 129 name := "Cert Name" 130 certificate, pk, err := GenerateCert(CertOpts{ 131 Signer: signer, CA: ca, Name: name, Days: 365, 132 DNSNames: DNSNames, IPAddresses: IPAddresses, ExtKeyUsage: extKeyUsage, 133 }) 134 require.Nil(t, err) 135 require.NotEmpty(t, certificate) 136 require.NotEmpty(t, pk) 137 138 cert, err := parseCert(certificate) 139 require.Nil(t, err) 140 require.Equal(t, name, cert.Subject.CommonName) 141 require.Equal(t, true, cert.BasicConstraintsValid) 142 signee, err := ParseSigner(pk) 143 require.Nil(t, err) 144 certID, err := keyID(signee.Public()) 145 require.Nil(t, err) 146 require.Equal(t, certID, cert.SubjectKeyId) 147 caID, err := keyID(signer.Public()) 148 require.Nil(t, err) 149 require.Equal(t, caID, cert.AuthorityKeyId) 150 require.Contains(t, cert.Issuer.CommonName, "Nomad Agent CA") 151 require.Equal(t, false, cert.IsCA) 152 153 require.WithinDuration(t, cert.NotBefore, time.Now(), time.Minute) 154 require.WithinDuration(t, cert.NotAfter, time.Now().AddDate(0, 0, 365), time.Minute) 155 156 require.Equal(t, x509.KeyUsageDigitalSignature|x509.KeyUsageKeyEncipherment, cert.KeyUsage) 157 require.Equal(t, extKeyUsage, cert.ExtKeyUsage) 158 159 // https://github.com/golang/go/blob/10538a8f9e2e718a47633ac5a6e90415a2c3f5f1/src/crypto/x509/verify.go#L414 160 require.Equal(t, DNSNames, cert.DNSNames) 161 require.True(t, IPAddresses[0].Equal(cert.IPAddresses[0])) 162 }