// Copyright (c) HashiCorp, Inc. // SPDX-License-Identifier: BUSL-1.1 package command import ( "crypto/x509" "os" "testing" "time" "github.com/hashicorp/cli" "github.com/hashicorp/nomad/testutil" "github.com/shoenig/test/must" ) func TestCACreateCommand(t *testing.T) { testDir := t.TempDir() previousDirectory, err := os.Getwd() must.NoError(t, err) must.NoError(t, os.Chdir(testDir)) defer os.Chdir(previousDirectory) type testcase struct { name string args []string caPath string keyPath string extraCheck func(t *testing.T, cert *x509.Certificate) } // The following subtests must run serially. cases := []testcase{ {"ca defaults", nil, "nomad-agent-ca.pem", "nomad-agent-ca-key.pem", func(t *testing.T, cert *x509.Certificate) { must.Eq(t, 1825*24*time.Hour, time.Until(cert.NotAfter).Round(24*time.Hour)) must.False(t, cert.PermittedDNSDomainsCritical) must.SliceEmpty(t, cert.PermittedDNSDomains) }, }, {"ca custom domain", []string{ "-name-constraint=true", "-domain=foo.com", }, "foo.com-agent-ca.pem", "foo.com-agent-ca-key.pem", func(t *testing.T, cert *x509.Certificate) { must.SliceContainsAll(t, cert.PermittedDNSDomains, []string{"nomad", "foo.com", "localhost"}) }, }, {"ca options", []string{ "-days=365", "-name-constraint=true", "-domain=foo", "-additional-domain=bar", "-common-name=CustomCA", "-country=ZZ", "-organization=CustOrg", "-organizational-unit=CustOrgUnit", }, "foo-agent-ca.pem", "foo-agent-ca-key.pem", func(t *testing.T, cert *x509.Certificate) { must.Eq(t, 365*24*time.Hour, time.Until(cert.NotAfter).Round(24*time.Hour)) must.True(t, cert.PermittedDNSDomainsCritical) must.Len(t, 4, cert.PermittedDNSDomains) must.SliceContainsAll(t, cert.PermittedDNSDomains, []string{"nomad", "foo", "localhost", "bar"}) must.Eq(t, cert.Issuer.Organization, []string{"CustOrg"}) must.Eq(t, cert.Issuer.OrganizationalUnit, []string{"CustOrgUnit"}) must.Eq(t, cert.Issuer.Country, []string{"ZZ"}) must.StrHasPrefix(t, "CustomCA", cert.Issuer.CommonName) }, }, {"ca custom date", []string{ "-days=365", }, "nomad-agent-ca.pem", "nomad-agent-ca-key.pem", func(t *testing.T, cert *x509.Certificate) { must.Eq(t, 365*24*time.Hour, time.Until(cert.NotAfter).Round(24*time.Hour)) }, }, } for _, tc := range cases { tc := tc t.Run(tc.name, func(t *testing.T) { ui := cli.NewMockUi() cmd := &TLSCACreateCommand{Meta: Meta{Ui: ui}} must.Zero(t, cmd.Run(tc.args)) must.Eq(t, "", ui.ErrorWriter.String()) // is a valid key key := testutil.IsValidSigner(t, tc.keyPath) must.True(t, key) // is a valid ca expects the ca ca := testutil.IsValidCertificate(t, tc.caPath) must.True(t, ca.BasicConstraintsValid) must.Eq(t, x509.KeyUsageCertSign|x509.KeyUsageCRLSign|x509.KeyUsageDigitalSignature, ca.KeyUsage) must.True(t, ca.IsCA) must.Eq(t, ca.AuthorityKeyId, ca.SubjectKeyId) tc.extraCheck(t, ca) must.NoError(t, os.Remove(tc.caPath)) must.NoError(t, os.Remove(tc.keyPath)) }) } }