mirror of
https://github.com/kemko/nomad.git
synced 2026-01-04 17:35:43 +03:00
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:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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...)
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user