cli: tls certs not created with correct SANs (#16959)

The `nomad tls cert` command did not create certificates with the correct SANs for
them to work with non default domain and region names. This changset updates the
code to support non default domains and regions in the certificates.
This commit is contained in:
Lance Haig
2023-05-22 15:31:56 +02:00
committed by GitHub
parent a6f15ba0ac
commit 7e93f150b5
61 changed files with 776 additions and 634 deletions

View File

@@ -920,11 +920,12 @@ func TestServer_Reload_TLS_Shared_Keyloader(t *testing.T) {
// We will start out with a bad cert and then reload with a good one.
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-bad.pem"
fookey = "../../helper/tlsutil/testdata/nomad-bad-key.pem"
foocert2 = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey2 = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
badca = "../../helper/tlsutil/testdata/bad-agent-ca.pem"
badcert = "../../helper/tlsutil/testdata/badRegion-client-bad.pem"
badkey = "../../helper/tlsutil/testdata/badRegion-client-bad-key.pem"
foocafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
fooclientcert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fooclientkey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
)
agent := NewTestAgent(t, t.Name(), func(c *Config) {
@@ -932,9 +933,9 @@ func TestServer_Reload_TLS_Shared_Keyloader(t *testing.T) {
EnableHTTP: true,
EnableRPC: true,
VerifyServerHostname: true,
CAFile: cafile,
CertFile: foocert,
KeyFile: fookey,
CAFile: badca,
CertFile: badcert,
KeyFile: badkey,
}
})
defer agent.Shutdown()
@@ -952,9 +953,9 @@ func TestServer_Reload_TLS_Shared_Keyloader(t *testing.T) {
EnableHTTP: true,
EnableRPC: true,
VerifyServerHostname: true,
CAFile: cafile,
CertFile: foocert2,
KeyFile: fookey2,
CAFile: foocafile,
CertFile: fooclientcert,
KeyFile: fooclientkey,
},
}
@@ -987,11 +988,12 @@ func TestServer_Reload_TLS_Certificate(t *testing.T) {
assert := assert.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-bad.pem"
fookey = "../../helper/tlsutil/testdata/nomad-bad-key.pem"
foocert2 = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey2 = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
badca = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
badcert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
badkey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
fooclientcert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fooclientkey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
)
agentConfig := &Config{
@@ -999,9 +1001,9 @@ func TestServer_Reload_TLS_Certificate(t *testing.T) {
EnableHTTP: true,
EnableRPC: true,
VerifyServerHostname: true,
CAFile: cafile,
CertFile: foocert,
KeyFile: fookey,
CAFile: badca,
CertFile: badcert,
KeyFile: badkey,
},
}
@@ -1016,8 +1018,8 @@ func TestServer_Reload_TLS_Certificate(t *testing.T) {
EnableRPC: true,
VerifyServerHostname: true,
CAFile: cafile,
CertFile: foocert2,
KeyFile: fookey2,
CertFile: fooclientcert,
KeyFile: fooclientkey,
},
}
@@ -1036,11 +1038,11 @@ func TestServer_Reload_TLS_Certificate_Invalid(t *testing.T) {
assert := assert.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-bad.pem"
fookey = "../../helper/tlsutil/testdata/nomad-bad-key.pem"
foocert2 = "invalid_cert_path"
fookey2 = "invalid_key_path"
badca = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
badcert = "../../helper/tlsutil/testdata/badRegion-client-bad.pem"
badkey = "../../helper/tlsutil/testdata/badRegion-client-bad-key.pem"
newfoocert = "invalid_cert_path"
newfookey = "invalid_key_path"
)
agentConfig := &Config{
@@ -1048,9 +1050,9 @@ func TestServer_Reload_TLS_Certificate_Invalid(t *testing.T) {
EnableHTTP: true,
EnableRPC: true,
VerifyServerHostname: true,
CAFile: cafile,
CertFile: foocert,
KeyFile: fookey,
CAFile: badca,
CertFile: badcert,
KeyFile: badkey,
},
}
@@ -1064,9 +1066,9 @@ func TestServer_Reload_TLS_Certificate_Invalid(t *testing.T) {
EnableHTTP: true,
EnableRPC: true,
VerifyServerHostname: true,
CAFile: cafile,
CertFile: foocert2,
KeyFile: fookey2,
CAFile: badca,
CertFile: newfoocert,
KeyFile: newfookey,
},
}
@@ -1123,9 +1125,9 @@ func TestServer_Reload_TLS_UpgradeToTLS(t *testing.T) {
assert := assert.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
)
logger := testlog.HCLogger(t)
@@ -1164,9 +1166,9 @@ func TestServer_Reload_TLS_DowngradeFromTLS(t *testing.T) {
assert := assert.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
)
logger := testlog.HCLogger(t)
@@ -1238,9 +1240,9 @@ func TestServer_ShouldReload_ReturnFalseForNoChanges(t *testing.T) {
assert := assert.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
)
sameAgentConfig := &Config{
@@ -1276,9 +1278,9 @@ func TestServer_ShouldReload_ReturnTrueForOnlyHTTPChanges(t *testing.T) {
require := require.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
)
sameAgentConfig := &Config{
@@ -1314,9 +1316,9 @@ func TestServer_ShouldReload_ReturnTrueForOnlyRPCChanges(t *testing.T) {
assert := assert.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
)
sameAgentConfig := &Config{
@@ -1352,11 +1354,11 @@ func TestServer_ShouldReload_ReturnTrueForConfigChanges(t *testing.T) {
assert := assert.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
foocert2 = "../../helper/tlsutil/testdata/nomad-bad.pem"
fookey2 = "../../helper/tlsutil/testdata/nomad-bad-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
badcert = "../../helper/tlsutil/testdata/badRegion-client-bad.pem"
badkey = "../../helper/tlsutil/testdata/badRegion-client-bad-key.pem"
)
agent := NewTestAgent(t, t.Name(), func(c *Config) {
@@ -1377,8 +1379,8 @@ func TestServer_ShouldReload_ReturnTrueForConfigChanges(t *testing.T) {
EnableRPC: true,
VerifyServerHostname: true,
CAFile: cafile,
CertFile: foocert2,
KeyFile: fookey2,
CertFile: badcert,
KeyFile: badkey,
},
}
@@ -1419,8 +1421,8 @@ func TestServer_ShouldReload_ReturnTrueForFileChanges(t *testing.T) {
require.Nil(err)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
key = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
key = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
)
logger := testlog.HCLogger(t)
@@ -1491,11 +1493,11 @@ func TestServer_ShouldReload_ShouldHandleMultipleChanges(t *testing.T) {
require := require.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
foocert2 = "../../helper/tlsutil/testdata/nomad-bad.pem"
fookey2 = "../../helper/tlsutil/testdata/nomad-bad-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
badcert = "../../helper/tlsutil/testdata/badRegion-client-bad.pem"
badkey = "../../helper/tlsutil/testdata/badRegion-client-bad-key.pem"
)
sameAgentConfig := &Config{
@@ -1515,8 +1517,8 @@ func TestServer_ShouldReload_ShouldHandleMultipleChanges(t *testing.T) {
EnableRPC: true,
VerifyServerHostname: true,
CAFile: cafile,
CertFile: foocert2,
KeyFile: fookey2,
CertFile: badcert,
KeyFile: badkey,
}
})
defer agent.Shutdown()

View File

@@ -732,12 +732,12 @@ func TestParsePagination(t *testing.T) {
func TestHTTP_VerifyHTTPSClient(t *testing.T) {
ci.Parallel(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-server-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-server-nomad-key.pem"
)
s := makeHTTPServer(t, func(c *Config) {
c.Region = "foo" // match the region on foocert
c.Region = "regionFoo" // match the region on foocert
c.TLSConfig = &config.TLSConfig{
EnableHTTP: true,
VerifyHTTPSClient: true,
@@ -749,10 +749,29 @@ func TestHTTP_VerifyHTTPSClient(t *testing.T) {
})
defer s.Shutdown()
tlConf := &tls.Config{
ServerName: "client.regionFoo.nomad",
}
cacert, err := os.ReadFile(cafile)
if err != nil {
t.Fatalf("error reading cacert: %v", err)
}
tlConf.RootCAs, err = x509.SystemCertPool()
if err != nil {
t.Fatalf("error reading SystemPool: %v", err)
}
tlConf.RootCAs.AppendCertsFromPEM(cacert)
tr := &http.Transport{TLSClientConfig: tlConf}
clnt := &http.Client{Transport: tr}
reqURL := fmt.Sprintf("https://%s/v1/agent/self", s.Agent.config.AdvertiseAddrs.HTTP)
request, err := http.NewRequest("GET", reqURL, nil)
must.NoError(t, err, must.Sprintf("error creating request: %v", err))
resp, err := clnt.Do(request)
// FAIL: Requests that expect 127.0.0.1 as the name should fail
resp, err := http.Get(reqURL)
if err == nil {
resp.Body.Close()
t.Fatalf("expected non-nil error but received: %v", resp.StatusCode)
@@ -767,14 +786,16 @@ func TestHTTP_VerifyHTTPSClient(t *testing.T) {
if !ok {
t.Fatalf("expected a x509.HostnameError but received: %T -> %v", urlErr.Err, urlErr.Err)
}
if expected := "127.0.0.1"; hostErr.Host != expected {
if expected := "client.regionFoo.nomad"; hostErr.Host != expected {
t.Fatalf("expected hostname on error to be %q but found %q", expected, hostErr.Host)
}
// FAIL: Requests that specify a valid hostname but not the CA should
// fail
pool := x509.NewCertPool()
tlsConf := &tls.Config{
ServerName: "client.regionFoo.nomad",
RootCAs: pool,
ServerName: "server.regionFoo.nomad",
}
transport := &http.Transport{TLSClientConfig: tlsConf}
client := &http.Client{Transport: transport}
@@ -860,11 +881,11 @@ func TestHTTP_VerifyHTTPSClient_AfterConfigReload(t *testing.T) {
assert := assert.New(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-bad.pem"
fookey = "../../helper/tlsutil/testdata/nomad-bad-key.pem"
foocert2 = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey2 = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
badcert = "../../helper/tlsutil/testdata/badRegion-client-bad.pem"
badkey = "../../helper/tlsutil/testdata/badRegion-client-bad-key.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
)
agentConfig := &Config{
@@ -872,8 +893,8 @@ func TestHTTP_VerifyHTTPSClient_AfterConfigReload(t *testing.T) {
EnableHTTP: true,
VerifyHTTPSClient: true,
CAFile: cafile,
CertFile: foocert,
KeyFile: fookey,
CertFile: badcert,
KeyFile: badkey,
},
}
@@ -882,8 +903,8 @@ func TestHTTP_VerifyHTTPSClient_AfterConfigReload(t *testing.T) {
EnableHTTP: true,
VerifyHTTPSClient: true,
CAFile: cafile,
CertFile: foocert2,
KeyFile: fookey2,
CertFile: foocert,
KeyFile: fookey,
},
}
@@ -933,7 +954,7 @@ func TestHTTP_VerifyHTTPSClient_AfterConfigReload(t *testing.T) {
ServerName: "client.regionFoo.nomad",
RootCAs: x509.NewCertPool(),
GetClientCertificate: func(*tls.CertificateRequestInfo) (*tls.Certificate, error) {
c, err := tls.LoadX509KeyPair(foocert2, fookey2)
c, err := tls.LoadX509KeyPair(foocert, fookey)
if err != nil {
return nil, err
}
@@ -1053,9 +1074,9 @@ func TestHTTPServer_Limits_OK(t *testing.T) {
ci.Parallel(t)
const (
cafile = "../../helper/tlsutil/testdata/ca.pem"
foocert = "../../helper/tlsutil/testdata/nomad-foo.pem"
fookey = "../../helper/tlsutil/testdata/nomad-foo-key.pem"
cafile = "../../helper/tlsutil/testdata/nomad-agent-ca.pem"
foocert = "../../helper/tlsutil/testdata/regionFoo-client-nomad.pem"
fookey = "../../helper/tlsutil/testdata/regionFoo-client-nomad-key.pem"
maxConns = 10 // limit must be < this for testing
bufSize = 1 // enough to know if something was written
)

View File

@@ -139,7 +139,7 @@ func (c *TLSCACreateCommand) Run(args []string) int {
constraints := []string{}
if c.constraint {
constraints = []string{c.domain, "localhost"}
constraints = []string{c.domain, "localhost", "nomad"}
constraints = append(constraints, c.additionalDomain...)
}

View File

@@ -53,8 +53,8 @@ func TestCACreateCommand(t *testing.T) {
func(t *testing.T, cert *x509.Certificate) {
require.Equal(t, 365*24*time.Hour, time.Until(cert.NotAfter).Round(24*time.Hour))
require.True(t, cert.PermittedDNSDomainsCritical)
require.Len(t, cert.PermittedDNSDomains, 3)
require.ElementsMatch(t, cert.PermittedDNSDomains, []string{"foo", "localhost", "bar"})
require.Len(t, cert.PermittedDNSDomains, 4)
require.ElementsMatch(t, cert.PermittedDNSDomains, []string{"nomad", "foo", "localhost", "bar"})
},
},
{"with common-name",

View File

@@ -33,19 +33,23 @@ type TLSCertCreateCommand struct {
cli bool
client bool
// key is used to set the custom CA certificate key when creating
// certificates.
key string
// days is the number of days the certificate will be valid for.
days int
// domain is used to provide a custom domain for the certificate.
domain string
// cluster_region is used to add the region name to the certifacte SAN
// records
cluster_region string
// domain is used to provide a custom domain for the certificate.
domain string
// key is used to set the custom CA certificate key when creating
// certificates.
key string
// cluster_region is used to add the region name to the certifacte SAN
// records
region string
server bool
}
@@ -79,8 +83,7 @@ Certificate Create Options:
Generate a client certificate.
-cluster-region
Provide the datacenter. Only used for -server certificates.
Defaults to "global".
DEPRECATED please use -region.
-days
Provide number of days the certificate is valid for from now on.
@@ -92,6 +95,10 @@ Certificate Create Options:
-key
Provide path to the certificate authority key. Defaults to
#DOMAIN#-agent-ca-key.pem.
-region
Provide the region. Only used for -server certificates.
Defaults to "global".
-server
Generate a server certificate.
@@ -134,10 +141,11 @@ func (c *TLSCertCreateCommand) Run(args []string) int {
flagSet.StringVar(&c.ca, "ca", "#DOMAIN#-agent-ca.pem", "")
flagSet.BoolVar(&c.cli, "cli", false, "")
flagSet.BoolVar(&c.client, "client", false, "")
flagSet.StringVar(&c.key, "key", "#DOMAIN#-agent-ca-key.pem", "")
// cluster region will be deprecated in the next version
flagSet.StringVar(&c.cluster_region, "cluster-region", "", "")
flagSet.IntVar(&c.days, "days", 365, "")
flagSet.StringVar(&c.cluster_region, "cluster-region", "global", "")
flagSet.StringVar(&c.domain, "domain", "nomad", "")
flagSet.StringVar(&c.key, "key", "#DOMAIN#-agent-ca-key.pem", "")
flagSet.BoolVar(&c.server, "server", false, "")
if err := flagSet.Parse(args); err != nil {
return 1
@@ -165,43 +173,42 @@ func (c *TLSCertCreateCommand) Run(args []string) int {
return 1
}
var DNSNames []string
var IPAddresses []net.IP
var dnsNames []string
var ipAddresses []net.IP
var extKeyUsage []x509.ExtKeyUsage
var name, prefix string
var name, regionName, prefix string
for _, d := range c.dnsNames {
if len(d) > 0 {
DNSNames = append(DNSNames, strings.TrimSpace(d))
dnsNames = append(dnsNames, strings.TrimSpace(d))
}
}
for _, i := range c.ipAddresses {
if len(i) > 0 {
IPAddresses = append(IPAddresses, net.ParseIP(strings.TrimSpace(i)))
ipAddresses = append(ipAddresses, net.ParseIP(strings.TrimSpace(i)))
}
}
if c.server {
name = fmt.Sprintf("server.%s.%s", c.cluster_region, c.domain)
DNSNames = append(DNSNames, name)
DNSNames = append(DNSNames, "localhost")
// set region variable to prepare for deprecating cluster_region
switch {
case c.cluster_region != "":
regionName = c.cluster_region
case c.clientConfig().Region != "" && c.clientConfig().Region != "global":
regionName = c.clientConfig().Region
default:
regionName = "global"
}
IPAddresses = append(IPAddresses, net.ParseIP("127.0.0.1"))
extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}
prefix = fmt.Sprintf("%s-server-%s", c.cluster_region, c.domain)
} else if c.client {
name = fmt.Sprintf("client.%s.%s", c.cluster_region, c.domain)
DNSNames = append(DNSNames, []string{name, "localhost"}...)
IPAddresses = append(IPAddresses, net.ParseIP("127.0.0.1"))
extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
prefix = fmt.Sprintf("%s-client-%s", c.cluster_region, c.domain)
} else if c.cli {
name = fmt.Sprintf("cli.%s.%s", c.cluster_region, c.domain)
DNSNames = []string{name, "localhost"}
prefix = fmt.Sprintf("%s-cli-%s", c.cluster_region, c.domain)
} else {
// Set dnsNames and ipAddresses based on whether this is a client, server or cli
switch {
case c.server:
ipAddresses, dnsNames, name, extKeyUsage, prefix = recordPreparation("server", regionName, c.domain, dnsNames, ipAddresses)
case c.client:
ipAddresses, dnsNames, name, extKeyUsage, prefix = recordPreparation("client", regionName, c.domain, dnsNames, ipAddresses)
case c.cli:
ipAddresses, dnsNames, name, extKeyUsage, prefix = recordPreparation("cli", regionName, c.domain, dnsNames, ipAddresses)
default:
c.Ui.Error("Neither client, cli nor server - should not happen")
return 1
}
@@ -252,10 +259,9 @@ func (c *TLSCertCreateCommand) Run(args []string) int {
c.Ui.Error(err.Error())
return 1
}
pub, priv, err := tlsutil.GenerateCert(tlsutil.CertOpts{
Signer: signer, CA: string(cert), Name: name, Days: c.days,
DNSNames: DNSNames, IPAddresses: IPAddresses, ExtKeyUsage: extKeyUsage,
DNSNames: dnsNames, IPAddresses: ipAddresses, ExtKeyUsage: extKeyUsage,
})
if err != nil {
c.Ui.Error(err.Error())
@@ -294,3 +300,37 @@ func (c *TLSCertCreateCommand) Run(args []string) int {
return 0
}
func recordPreparation(certType string, regionName string, domain string, dnsNames []string, ipAddresses []net.IP) ([]net.IP, []string, string, []x509.ExtKeyUsage, string) {
var (
extKeyUsage []x509.ExtKeyUsage
name, regionUrl, prefix string
)
if certType == "server" || certType == "client" {
extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}
ipAddresses = append(ipAddresses, net.ParseIP("127.0.0.1"))
} else if certType == "cli" {
extKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth}
}
// prefix is used to generate the filename for the certificate before writing to disk.
prefix = fmt.Sprintf("%s-%s-%s", regionName, certType, domain)
regionUrl = fmt.Sprintf("%s.%s.nomad", certType, regionName)
name = fmt.Sprintf("%s.%s.%s", certType, regionName, domain)
if regionName != "global" && domain != "nomad" {
dnsNames = append(dnsNames, name, regionUrl, fmt.Sprintf("%s.global.nomad", certType), "localhost")
}
if regionName != "global" && domain == "nomad" {
dnsNames = append(dnsNames, regionUrl, fmt.Sprintf("%s.global.nomad", certType), "localhost")
}
if regionName == "global" && domain != "nomad" {
dnsNames = append(dnsNames, regionUrl, fmt.Sprintf("%s.%s.%s", certType, regionName, domain), "localhost")
}
if regionName == "global" && domain == "nomad" {
dnsNames = append(dnsNames, name, "localhost")
}
return ipAddresses, dnsNames, name, extKeyUsage, prefix
}

View File

@@ -7,6 +7,7 @@ import (
"crypto/x509"
"net"
"os"
"strings"
"testing"
"github.com/hashicorp/nomad/testutil"
@@ -57,7 +58,7 @@ func TestTlsCertCreateCommand_InvalidArgs(t *testing.T) {
}
}
func TestTlsCertCreateCommand_fileCreate(t *testing.T) {
func TestTlsCertCreateCommandDefaults_fileCreate(t *testing.T) {
testDir := t.TempDir()
previousDirectory, err := os.Getwd()
require.NoError(t, err)
@@ -97,14 +98,15 @@ func TestTlsCertCreateCommand_fileCreate(t *testing.T) {
[]net.IP{{127, 0, 0, 1}},
"==> WARNING: Server Certificates grants authority to become a\n server and access all state in the cluster including root keys\n and all ACL tokens. Do not distribute them to production hosts\n that are not server nodes. Store them as securely as CA keys.\n",
},
{"server0-region2-altdomain",
{"server0-region1",
"server",
[]string{"-server", "-cluster-region", "region2", "-domain", "nomad"},
"region2-server-nomad.pem",
"region2-server-nomad-key.pem",
"server.region2.nomad",
[]string{"-server", "-region", "region1"},
"region1-server-nomad.pem",
"region1-server-nomad-key.pem",
"server.region1.nomad",
[]string{
"server.region2.nomad",
"server.region1.nomad",
"server.global.nomad",
"localhost",
},
[]net.IP{{127, 0, 0, 1}},
@@ -123,19 +125,6 @@ func TestTlsCertCreateCommand_fileCreate(t *testing.T) {
[]net.IP{{127, 0, 0, 1}},
"",
},
{"client0-region2-altdomain",
"client",
[]string{"-client", "-cluster-region", "region2", "-domain", "nomad"},
"region2-client-nomad.pem",
"region2-client-nomad-key.pem",
"client.region2.nomad",
[]string{
"client.region2.nomad",
"localhost",
},
[]net.IP{{127, 0, 0, 1}},
"",
},
{"cli0",
"cli",
[]string{"-cli"},
@@ -146,20 +135,7 @@ func TestTlsCertCreateCommand_fileCreate(t *testing.T) {
"cli.global.nomad",
"localhost",
},
nil,
"",
},
{"cli0-region2-altdomain",
"cli",
[]string{"-cli", "-cluster-region", "region2", "-domain", "nomad"},
"region2-cli-nomad.pem",
"region2-cli-nomad-key.pem",
"cli.region2.nomad",
[]string{
"cli.region2.nomad",
"localhost",
},
nil,
[]net.IP(nil),
"",
},
}
@@ -184,10 +160,12 @@ func TestTlsCertCreateCommand_fileCreate(t *testing.T) {
cert.ExtKeyUsage)
case "client":
require.Equal(t,
[]x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
[]x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
cert.ExtKeyUsage)
case "cli":
require.Len(t, cert.ExtKeyUsage, 0)
require.Equal(t,
[]x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
cert.ExtKeyUsage)
}
require.False(t, cert.IsCA)
require.Equal(t, tc.expectDNS, cert.DNSNames)
@@ -195,3 +173,156 @@ func TestTlsCertCreateCommand_fileCreate(t *testing.T) {
}))
}
}
func TestTlsRecordPreparation(t *testing.T) {
type testcase struct {
name string
certType string
regionName string
domain string
dnsNames []string
ipAddresses []string
expectedipAddresses []net.IP
expectedDNSNames []string
expectedName string
expectedextKeyUsage []x509.ExtKeyUsage
expectedPrefix string
}
// The default values are region = global and domain = nomad.
cases := []testcase{
{
name: "server0",
certType: "server",
regionName: "global",
domain: "nomad",
dnsNames: []string{},
ipAddresses: []string{},
expectedipAddresses: []net.IP{net.ParseIP("127.0.0.1")},
expectedDNSNames: []string{
"server.global.nomad",
"localhost",
},
expectedName: "server.global.nomad",
expectedextKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
expectedPrefix: "global-server-nomad",
},
{
name: "server0-region1",
certType: "server",
regionName: "region1",
domain: "nomad",
dnsNames: []string{},
ipAddresses: []string{},
expectedipAddresses: []net.IP{net.ParseIP("127.0.0.1")},
expectedDNSNames: []string{
"server.region1.nomad",
"server.global.nomad",
"localhost",
},
expectedName: "server.region1.nomad",
expectedextKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
expectedPrefix: "region1-server-nomad",
},
{
name: "server0-domain1",
certType: "server",
regionName: "global",
domain: "domain1",
dnsNames: []string{},
ipAddresses: []string{},
expectedipAddresses: []net.IP{net.ParseIP("127.0.0.1")},
expectedDNSNames: []string{
"server.global.nomad",
"server.global.domain1",
"localhost",
},
expectedName: "server.global.domain1",
expectedextKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
expectedPrefix: "global-server-domain1",
},
{
name: "server0-dns",
certType: "server",
regionName: "global",
domain: "nomad",
dnsNames: []string{"server.global.foo"},
ipAddresses: []string{},
expectedipAddresses: []net.IP{net.ParseIP("127.0.0.1")},
expectedDNSNames: []string{
"server.global.foo",
"server.global.nomad",
"localhost",
},
expectedName: "server.global.nomad",
expectedextKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
expectedPrefix: "global-server-nomad",
},
{
name: "server0-ips",
certType: "server",
regionName: "global",
domain: "nomad",
dnsNames: []string{},
ipAddresses: []string{"10.0.0.1"},
expectedipAddresses: []net.IP{net.ParseIP("10.0.0.1"), net.ParseIP("127.0.0.1")},
expectedDNSNames: []string{
"server.global.nomad",
"localhost",
},
expectedName: "server.global.nomad",
expectedextKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
expectedPrefix: "global-server-nomad",
},
{
name: "client0",
certType: "client",
regionName: "global",
domain: "nomad",
dnsNames: []string{},
ipAddresses: []string{},
expectedipAddresses: []net.IP{net.ParseIP("127.0.0.1")},
expectedDNSNames: []string{
"client.global.nomad",
"localhost",
},
expectedName: "client.global.nomad",
expectedextKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
expectedPrefix: "global-client-nomad",
},
{
name: "cli0",
certType: "cli",
regionName: "global",
domain: "nomad",
dnsNames: []string{},
ipAddresses: []string{},
expectedipAddresses: []net.IP(nil),
expectedDNSNames: []string{
"cli.global.nomad",
"localhost",
},
expectedName: "cli.global.nomad",
expectedextKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
expectedPrefix: "global-cli-nomad",
},
}
for _, tc := range cases {
tc := tc
require.True(t, t.Run(tc.name, func(t *testing.T) {
var ipAddresses []net.IP
for _, i := range tc.ipAddresses {
if len(i) > 0 {
ipAddresses = append(ipAddresses, net.ParseIP(strings.TrimSpace(i)))
}
}
ipAddresses, dnsNames, name, extKeyUsage, prefix := recordPreparation(tc.certType, tc.regionName, tc.domain, tc.dnsNames, ipAddresses)
require.Equal(t, tc.expectedipAddresses, ipAddresses)
require.Equal(t, tc.expectedDNSNames, dnsNames)
require.Equal(t, tc.expectedName, name)
require.Equal(t, tc.expectedextKeyUsage, extKeyUsage)
require.Equal(t, tc.expectedPrefix, prefix)
}))
}
}