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  }