mirror of
https://github.com/gogrlx/nats-server.git
synced 2026-04-14 10:10:42 -07:00
Merge pull request #1042 from nats-io/leafnode-tls-timeout
Allow updating TLS timeout for leafnode remotes
This commit is contained in:
@@ -1083,9 +1083,9 @@ func TestConfigCheck(t *testing.T) {
|
||||
}
|
||||
}
|
||||
`,
|
||||
err: errors.New(`error parsing X509 certificate/key pair: open : no such file or directory`),
|
||||
errorLine: 3,
|
||||
errorPos: 5,
|
||||
err: nil,
|
||||
errorLine: 0,
|
||||
errorPos: 0,
|
||||
},
|
||||
{
|
||||
name: "invalid lame_duck_duration type",
|
||||
@@ -1096,6 +1096,23 @@ func TestConfigCheck(t *testing.T) {
|
||||
errorLine: 2,
|
||||
errorPos: 3,
|
||||
},
|
||||
{
|
||||
name: "when only setting TLS timeout for a leafnode remote",
|
||||
config: `
|
||||
leafnodes {
|
||||
remotes = [
|
||||
{
|
||||
url: "tls://connect.ngs.global:7422"
|
||||
tls {
|
||||
timeout: 0.01
|
||||
}
|
||||
}
|
||||
]
|
||||
}`,
|
||||
err: nil,
|
||||
errorLine: 0,
|
||||
errorPos: 0,
|
||||
},
|
||||
}
|
||||
|
||||
checkConfig := func(config string) error {
|
||||
|
||||
@@ -115,6 +115,9 @@ const (
|
||||
// DEFAULT_LEAF_NODE_RECONNECT LeafNode reconnect interval.
|
||||
DEFAULT_LEAF_NODE_RECONNECT = time.Second
|
||||
|
||||
// DEFAULT_LEAF_TLS_TIMEOUT TLS timeout for LeafNodes
|
||||
DEFAULT_LEAF_TLS_TIMEOUT = 2 * time.Second
|
||||
|
||||
// PROTO_SNIPPET_SIZE is the default size of proto to print on parse errors.
|
||||
PROTO_SNIPPET_SIZE = 32
|
||||
|
||||
|
||||
@@ -136,3 +136,128 @@ func TestLeafNodeTLSWithCerts(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func TestLeafNodeTLSRemoteWithNoCerts(t *testing.T) {
|
||||
conf1 := createConfFile(t, []byte(`
|
||||
port: -1
|
||||
leaf {
|
||||
listen: "127.0.0.1:-1"
|
||||
tls {
|
||||
ca_file: "../test/configs/certs/tlsauth/ca.pem"
|
||||
cert_file: "../test/configs/certs/tlsauth/server.pem"
|
||||
key_file: "../test/configs/certs/tlsauth/server-key.pem"
|
||||
timeout: 2
|
||||
}
|
||||
}
|
||||
`))
|
||||
defer os.Remove(conf1)
|
||||
s1, o1 := RunServerWithConfig(conf1)
|
||||
defer s1.Shutdown()
|
||||
|
||||
u, err := url.Parse(fmt.Sprintf("nats://localhost:%d", o1.LeafNode.Port))
|
||||
if err != nil {
|
||||
t.Fatalf("Error parsing url: %v", err)
|
||||
}
|
||||
conf2 := createConfFile(t, []byte(fmt.Sprintf(`
|
||||
port: -1
|
||||
leaf {
|
||||
remotes [
|
||||
{
|
||||
url: "%s"
|
||||
tls {
|
||||
ca_file: "../test/configs/certs/tlsauth/ca.pem"
|
||||
timeout: 5
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`, u.String())))
|
||||
defer os.Remove(conf2)
|
||||
o2, err := ProcessConfigFile(conf2)
|
||||
if err != nil {
|
||||
t.Fatalf("Error processing config file: %v", err)
|
||||
}
|
||||
|
||||
if len(o2.LeafNode.Remotes) == 0 {
|
||||
t.Fatal("Expected at least a single leaf remote")
|
||||
}
|
||||
|
||||
var (
|
||||
got float64 = o2.LeafNode.Remotes[0].TLSTimeout
|
||||
expected float64 = 5
|
||||
)
|
||||
if got != expected {
|
||||
t.Fatalf("Expected %v, got: %v", expected, got)
|
||||
}
|
||||
o2.NoLog, o2.NoSigs = true, true
|
||||
o2.LeafNode.resolver = &testLoopbackResolver{}
|
||||
s2 := RunServer(o2)
|
||||
defer s2.Shutdown()
|
||||
|
||||
checkFor(t, 3*time.Second, 10*time.Millisecond, func() error {
|
||||
if nln := s1.NumLeafNodes(); nln != 1 {
|
||||
return fmt.Errorf("Number of leaf nodes is %d", nln)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
// Here we only process options without starting the server
|
||||
// and without a root CA for the remote.
|
||||
conf3 := createConfFile(t, []byte(fmt.Sprintf(`
|
||||
port: -1
|
||||
leaf {
|
||||
remotes [
|
||||
{
|
||||
url: "%s"
|
||||
tls {
|
||||
timeout: 10
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`, u.String())))
|
||||
defer os.Remove(conf3)
|
||||
o3, err := ProcessConfigFile(conf3)
|
||||
if err != nil {
|
||||
t.Fatalf("Error processing config file: %v", err)
|
||||
}
|
||||
|
||||
if len(o3.LeafNode.Remotes) == 0 {
|
||||
t.Fatal("Expected at least a single leaf remote")
|
||||
}
|
||||
got = o3.LeafNode.Remotes[0].TLSTimeout
|
||||
expected = 10
|
||||
if got != expected {
|
||||
t.Fatalf("Expected %v, got: %v", expected, got)
|
||||
}
|
||||
|
||||
// Here we only process options without starting the server
|
||||
// and check the default for leafnode remotes.
|
||||
conf4 := createConfFile(t, []byte(fmt.Sprintf(`
|
||||
port: -1
|
||||
leaf {
|
||||
remotes [
|
||||
{
|
||||
url: "%s"
|
||||
tls {
|
||||
ca_file: "../test/configs/certs/tlsauth/ca.pem"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
`, u.String())))
|
||||
defer os.Remove(conf4)
|
||||
o4, err := ProcessConfigFile(conf4)
|
||||
if err != nil {
|
||||
t.Fatalf("Error processing config file: %v", err)
|
||||
}
|
||||
|
||||
if len(o4.LeafNode.Remotes) == 0 {
|
||||
t.Fatal("Expected at least a single leaf remote")
|
||||
}
|
||||
got = o4.LeafNode.Remotes[0].TLSTimeout
|
||||
expected = float64(DEFAULT_LEAF_TLS_TIMEOUT)
|
||||
if int(got) != int(expected) {
|
||||
t.Fatalf("Expected %v, got: %v", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1096,7 +1096,11 @@ func parseRemoteLeafNodes(v interface{}, errors *[]error, warnings *[]error) ([]
|
||||
// Set RootCAs since this tls.Config is used when soliciting
|
||||
// a connection (therefore behaves as a client).
|
||||
remote.TLSConfig.RootCAs = remote.TLSConfig.ClientCAs
|
||||
remote.TLSTimeout = tc.Timeout
|
||||
if tc.Timeout > 0 {
|
||||
remote.TLSTimeout = tc.Timeout
|
||||
} else {
|
||||
remote.TLSTimeout = float64(DEFAULT_LEAF_TLS_TIMEOUT)
|
||||
}
|
||||
default:
|
||||
if !tk.IsUsedVariable() {
|
||||
err := &unknownConfigFieldErr{
|
||||
@@ -2144,29 +2148,35 @@ func parseTLS(v interface{}) (*TLSConfigOpts, error) {
|
||||
|
||||
// GenTLSConfig loads TLS related configuration parameters.
|
||||
func GenTLSConfig(tc *TLSConfigOpts) (*tls.Config, error) {
|
||||
|
||||
// Now load in cert and private key
|
||||
cert, err := tls.LoadX509KeyPair(tc.CertFile, tc.KeyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing X509 certificate/key pair: %v", err)
|
||||
}
|
||||
cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing certificate: %v", err)
|
||||
}
|
||||
|
||||
// Create the tls.Config from our options.
|
||||
// We will determine the cipher suites that we prefer.
|
||||
// Create the tls.Config from our options before including the certs.
|
||||
// It will determine the cipher suites that we prefer.
|
||||
// FIXME(dlc) change if ARM based.
|
||||
config := tls.Config{
|
||||
MinVersion: tls.VersionTLS12,
|
||||
CipherSuites: tc.Ciphers,
|
||||
PreferServerCipherSuites: true,
|
||||
CurvePreferences: tc.CurvePreferences,
|
||||
Certificates: []tls.Certificate{cert},
|
||||
InsecureSkipVerify: tc.Insecure,
|
||||
}
|
||||
|
||||
switch {
|
||||
case tc.CertFile != "" && tc.KeyFile == "":
|
||||
return nil, fmt.Errorf("missing 'key_file' in TLS configuration")
|
||||
case tc.CertFile == "" && tc.KeyFile != "":
|
||||
return nil, fmt.Errorf("missing 'cert_file' in TLS configuration")
|
||||
case tc.CertFile != "" && tc.KeyFile != "":
|
||||
// Now load in cert and private key
|
||||
cert, err := tls.LoadX509KeyPair(tc.CertFile, tc.KeyFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing X509 certificate/key pair: %v", err)
|
||||
}
|
||||
cert.Leaf, err = x509.ParseCertificate(cert.Certificate[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing certificate: %v", err)
|
||||
}
|
||||
config.Certificates = []tls.Certificate{cert}
|
||||
}
|
||||
|
||||
// Require client certificates as needed
|
||||
if tc.Verify {
|
||||
config.ClientAuth = tls.RequireAndVerifyClientCert
|
||||
|
||||
@@ -1614,12 +1614,59 @@ func TestParsingGatewaysErrors(t *testing.T) {
|
||||
"to be filename",
|
||||
},
|
||||
{
|
||||
"tls_gen_error",
|
||||
"tls_gen_error_cert_file_not_found",
|
||||
`gateway {
|
||||
name: "A"
|
||||
port: -1
|
||||
tls {
|
||||
cert_file: "./configs/certs/missing.pem"
|
||||
key_file: "./configs/certs/server-key.pem"
|
||||
}
|
||||
}`,
|
||||
"certificate/key pair",
|
||||
},
|
||||
{
|
||||
"tls_gen_error_key_file_not_found",
|
||||
`gateway {
|
||||
name: "A"
|
||||
port: -1
|
||||
tls {
|
||||
cert_file: "./configs/certs/server.pem"
|
||||
key_file: "./configs/certs/missing.pem"
|
||||
}
|
||||
}`,
|
||||
"certificate/key pair",
|
||||
},
|
||||
{
|
||||
"tls_gen_error_key_file_missing",
|
||||
`gateway {
|
||||
name: "A"
|
||||
port: -1
|
||||
tls {
|
||||
cert_file: "./configs/certs/server.pem"
|
||||
}
|
||||
}`,
|
||||
`missing 'key_file' in TLS configuration`,
|
||||
},
|
||||
{
|
||||
"tls_gen_error_cert_file_missing",
|
||||
`gateway {
|
||||
name: "A"
|
||||
port: -1
|
||||
tls {
|
||||
key_file: "./configs/certs/server-key.pem"
|
||||
}
|
||||
}`,
|
||||
`missing 'cert_file' in TLS configuration`,
|
||||
},
|
||||
{
|
||||
"tls_gen_error_key_file_not_found",
|
||||
`gateway {
|
||||
name: "A"
|
||||
port: -1
|
||||
tls {
|
||||
cert_file: "./configs/certs/server.pem"
|
||||
key_file: "./configs/certs/missing.pem"
|
||||
}
|
||||
}`,
|
||||
"certificate/key pair",
|
||||
@@ -1687,7 +1734,7 @@ func TestParsingGatewaysErrors(t *testing.T) {
|
||||
"to be filename",
|
||||
},
|
||||
{
|
||||
"gateway_unknon_field",
|
||||
"gateway_unknown_field",
|
||||
`gateway {
|
||||
name: "A"
|
||||
port: -1
|
||||
|
||||
Reference in New Issue
Block a user