[ADDED] Cluster tls insecure configuration

Based on @softkbot PR #913.
Removed the command line parameter, which then removes the need for Options.Cluster.TLSInsecure.
Added a test with config reload.

Signed-off-by: Ivan Kozlovic <ivan@synadia.com>
This commit is contained in:
Alexei Volkov
2019-02-23 18:21:33 +03:00
committed by Ivan Kozlovic
parent c625970909
commit 83aefdc714
7 changed files with 206 additions and 0 deletions

View File

@@ -201,6 +201,9 @@ func validateGatewayOptions(o *Options) error {
if o.Gateway.Port == 0 {
return fmt.Errorf("gateway %q has no port specified (select -1 for random port)", o.Gateway.Name)
}
if o.Gateway.TLSConfig != nil && o.Gateway.TLSConfig.InsecureSkipVerify {
return fmt.Errorf("tls InsecureSkipVerify not supported for gateway")
}
for i, g := range o.Gateway.Gateways {
if g.Name == "" {
return fmt.Errorf("gateway in the list %d has no name", i)
@@ -208,6 +211,9 @@ func validateGatewayOptions(o *Options) error {
if len(g.URLs) == 0 {
return fmt.Errorf("gateway %q has no URL", g.Name)
}
if g.TLSConfig != nil && g.TLSConfig.InsecureSkipVerify {
return fmt.Errorf("tls InsecureSkipVerify not supported for remote gateway %q", g.Name)
}
}
return nil
}

View File

@@ -233,6 +233,7 @@ type TLSConfigOpts struct {
KeyFile string
CaFile string
Verify bool
Insecure bool
Map bool
Timeout float64
Ciphers []uint16
@@ -1846,6 +1847,12 @@ func parseTLS(v interface{}) (*TLSConfigOpts, error) {
return nil, &configErr{tk, fmt.Sprintf("error parsing tls config, expected 'ca_file' to be filename")}
}
tc.CaFile = caFile
case "insecure":
insecure, ok := mv.(bool)
if !ok {
return nil, &configErr{tk, fmt.Sprintf("error parsing tls config, expected 'insecure' to be a boolean")}
}
tc.Insecure = insecure
case "verify":
verify, ok := mv.(bool)
if !ok {
@@ -1936,6 +1943,7 @@ func GenTLSConfig(tc *TLSConfigOpts) (*tls.Config, error) {
PreferServerCipherSuites: true,
CurvePreferences: tc.CurvePreferences,
Certificates: []tls.Certificate{cert},
InsecureSkipVerify: tc.Insecure,
}
// Require client certificates as needed

View File

@@ -292,6 +292,11 @@ func NewServer(opts *Options) (*Server, error) {
}
func validateOptions(o *Options) error {
// For now, InsecureSkipVerify is supported only for Cluster.
// So fail if it was set to client and or gateways.
if o.TLSConfig != nil && o.TLSConfig.InsecureSkipVerify {
return fmt.Errorf("tls InsecureSkipVerify not supported for client connections")
}
// Check that the trust configuration is correct.
if err := validateTrustedOperators(o); err != nil {
return err

View File

@@ -1085,3 +1085,57 @@ func TestClientWriteLoopStall(t *testing.T) {
case <-time.After(250 * time.Millisecond):
}
}
func TestInsecureSkipVerifyNotSupportedForClientAndGateways(t *testing.T) {
checkServerFails := func(t *testing.T, o *Options) {
t.Helper()
s, err := NewServer(o)
if s != nil {
s.Shutdown()
}
if err == nil || !strings.Contains(err.Error(), "not supported") {
t.Fatalf("Expected error about not supported feature, got %v", err)
}
}
tc := &TLSConfigOpts{}
tc.CertFile = "../test/configs/certs/server-cert.pem"
tc.KeyFile = "../test/configs/certs/server-key.pem"
tc.CaFile = "../test/configs/certs/ca.pem"
tc.Insecure = true
o := DefaultOptions()
config, err := GenTLSConfig(tc)
if err != nil {
t.Fatalf("Error generating tls config: %v", err)
}
o.TLSConfig = config
checkServerFails(t, o)
// Get a clone that we will use for the Gateway TLS setting
gwConfig := config.Clone()
// Remove the setting
o.TLSConfig.InsecureSkipVerify = false
// Configure GW
o.Gateway.Name = "A"
o.Gateway.Host = "127.0.0.1"
o.Gateway.Port = -1
o.Gateway.TLSConfig = gwConfig
checkServerFails(t, o)
// Get a config for the remote gateway
rgwConfig := gwConfig.Clone()
gurl, _ := url.Parse("nats://127.0.0.1:1234")
// Remove the insecure for the main gateway config
o.Gateway.TLSConfig.InsecureSkipVerify = false
o.Gateway.Gateways = []*RemoteGatewayOpts{
&RemoteGatewayOpts{
Name: "B",
URLs: []*url.URL{gurl},
TLSConfig: rgwConfig,
},
}
checkServerFails(t, o)
}

View File

@@ -14,7 +14,11 @@
package test
import (
"fmt"
"io/ioutil"
"strings"
"testing"
"time"
"github.com/nats-io/gnatsd/server"
)
@@ -62,3 +66,78 @@ func TestBasicTLSClusterPubSub(t *testing.T) {
matches := expectMsgs(1)
checkMsg(t, matches[0], "foo", "22", "", "2", "ok")
}
type captureTLSError struct {
dummyLogger
ch chan struct{}
}
func (c *captureTLSError) Errorf(format string, v ...interface{}) {
msg := fmt.Sprintf(format, v...)
if strings.Contains(msg, "handshake error") {
select {
case c.ch <- struct{}{}:
default:
}
}
}
func TestClusterTLSInsecure(t *testing.T) {
confA := createConfFile(t, []byte(`
port: -1
cluster {
listen: "127.0.0.1:-1"
tls {
cert_file: "./configs/certs/server-noip.pem"
key_file: "./configs/certs/server-key-noip.pem"
ca_file: "./configs/certs/ca.pem"
timeout: 2
}
}
`))
srvA, optsA := RunServerWithConfig(confA)
defer srvA.Shutdown()
l := &captureTLSError{ch: make(chan struct{}, 1)}
srvA.SetLogger(l, false, false)
bConfigTemplate := `
port: -1
cluster {
listen: "127.0.0.1:-1"
tls {
cert_file: "./configs/certs/server-noip.pem"
key_file: "./configs/certs/server-key-noip.pem"
ca_file: "./configs/certs/ca.pem"
timeout: 2
%s
}
routes [
"nats://%s:%d"
]
}
`
confB := createConfFile(t, []byte(fmt.Sprintf(bConfigTemplate,
"", optsA.Cluster.Host, optsA.Cluster.Port)))
srvB, _ := RunServerWithConfig(confB)
defer srvB.Shutdown()
// We should get errors
select {
case <-l.ch:
case <-time.After(2 * time.Second):
t.Fatalf("Did not get handshake error")
}
// Need to add "insecure: true" and reload
if err := ioutil.WriteFile(confB,
[]byte(fmt.Sprintf(bConfigTemplate, "insecure: true", optsA.Cluster.Host, optsA.Cluster.Port)),
0666); err != nil {
t.Fatalf("Error rewriting file: %v", err)
}
if err := srvB.Reload(); err != nil {
t.Fatalf("Error on reload: %v", err)
}
checkClusterFormed(t, srvA, srvB)
}

View File

@@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEArFsnvZER/Hy0ZVfBInmgn8A6CFM+TRx3dcaqw5qB7qo6yGQI
fCtGSkF5bxlevf820QHA3rRO8jboSOi4CdQ0Bis9c8XleBQFuy/EMJMcZwWpW5jO
XuMOyKbJZPtucceJdl5jbYJum3whPklFa4iIifQWth9BIPQRqw06BXU7aVgKEfJi
3BFIihamQFj1YUcDAvg5zPn2rXo3m3RRVtMmqWDldxPnRFQcvmoon723J5yn5wcR
JO21sH4vgHm8tKuxFpVH5go0tmrJUPRkG6E6zURY8+qBhwXeQPzH1kUzP2w6z21k
NFYrfxhdviSJyVzqMPkqAKcTRNb3o1Po9o/r4wIDAQABAoIBABmg4FLmzGbf4C8l
klle/oxil/5+6kerEPRZWzEEu4dSlrUPcteL08Lc44KqohTcazk+6n/zDb4kffvB
ZwRHIok8SsH5TjrBt2xzGNgkN9f11o4BNcaUOrGJY275mB2hDwaj2GMDPxEtrv/F
A2aPAcaJngrssNGGmU33BIalPPVX3HHXy/DgyJGJtMOqjba3AclOjL3dNETExIG1
LEZVu29xzUo1+g4iyM4Rtwred/rvprw7l+k7tC0EqJqu8PEMJanBwEt1Vc66Its3
02b3l+X8E2tU43arSP2mOMmsgnyCVchIiU/UXbRyto9ngXl2tUyapLvzwPGGfuX6
GXuA/9kCgYEA3T6OiMioN34jGkBjIH56D1p7iLfoxaNsb2CjHyFrgOcbGgDRJL6Z
fB7JNK3bZDMzOSBO6Fz9GogsXh0bX+6SDb+xTjqdDxv4Icz12e2lFUUKLzaLZtgX
+2yay89geKmj78gqsF+WBy8lB36D5zBXXD57udVRmKCH4oQlAHC9TCUCgYEAx26I
m+4JHgP7/3I51ZaSnpaJMeYf0gWWRfHmgF/bWJl+3CSbYy+e3Jn+SXAfqw2j/zYK
4R8PmAMtp3qM8uFW9aU+IdSuBsl/qzyTKJDxlvNHE8R0zvwyELmOPN0d1dpMhyuO
ohAhAtlvpVFboJoex6Cv5Mq6CvzM9OcLZ9ZGVWcCgYEAgIveSP89LbDuOEx8y95w
kQcji5Y/esWvNS9S172VNroQdxVObykHCKTihucU96z/8AsjjcKplIbWMIB87Uoy
NibQoAFSS/sWOp1Zoxt+tVL9zdzFNiYMGRtK/WwqQzFdfO4yT3PaOaZcv3P0s5jU
yVXMkXauCB4NlcDttsnKUrkCgYBGpbFfC4PPTjoG08AJGb32z/zp4EuFatVBEeBF
ua9KQ5XdBlrFWCk+nI6oFUAiqEJgNhTEiuxLPVT+7zrfD1Ru0IqiEWVUoizHzD2V
MUNj5epX5lA6wrw5kIICrZHUH/DcMWHlpzEKgVw7hAahbfdZYGLu+aHOIp+4YeB4
eD+SIQKBgBc7SodbrugKLrLCaH3pzl4jahbbVvQ6G6T2RwDTeFG8UGI2yLvyfZ3Y
NTYq/UaNOrKpNL4ThB2FZmfpRiWuJ9FvWXmuMWmHzKIcT142tN+EBye7y8V6mURE
SU49GLqU+6fNvu2KdFZAUQnJIzc+WXrT8Qsr5ka/ENHLp8I3o03e
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEjzCCAncCCQDvpOBu2zU8sDANBgkqhkiG9w0BAQsFADCBizELMAkGA1UEBhMC
VVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQK
EwpBcGNlcmEgSW5jMRAwDgYDVQQLEwduYXRzLmlvMRIwEAYDVQQDEwlsb2NhbGhv
c3QxHDAaBgkqhkiG9w0BCQEWDWRlcmVrQG5hdHMuaW8wHhcNMTgxMTI0MjA1MTQ1
WhcNMjgxMTIxMjA1MTQ1WjCBhjELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRQw
EgYDVQQHDAtMb3MgQW5nZWxlczEQMA4GA1UECgwHU3luYWRpYTEQMA4GA1UECwwH
TkFUUy5pbzESMBAGA1UEAwwJbG9jYWxob3N0MRwwGgYJKoZIhvcNAQkBFg1kZXJl
a0BuYXRzLmlvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArFsnvZER
/Hy0ZVfBInmgn8A6CFM+TRx3dcaqw5qB7qo6yGQIfCtGSkF5bxlevf820QHA3rRO
8jboSOi4CdQ0Bis9c8XleBQFuy/EMJMcZwWpW5jOXuMOyKbJZPtucceJdl5jbYJu
m3whPklFa4iIifQWth9BIPQRqw06BXU7aVgKEfJi3BFIihamQFj1YUcDAvg5zPn2
rXo3m3RRVtMmqWDldxPnRFQcvmoon723J5yn5wcRJO21sH4vgHm8tKuxFpVH5go0
tmrJUPRkG6E6zURY8+qBhwXeQPzH1kUzP2w6z21kNFYrfxhdviSJyVzqMPkqAKcT
RNb3o1Po9o/r4wIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQBaw+X7f5kzrvhDFAc9
ToSRfKW4P7gcnSTODMq3HqgI3mpjmgJKx7WJMYb7YTk4xrbREPQzr29rRCdCncOs
sM8hZZ/4CgVg+l7CgZFFviJ6tv0EWgmKj2H7V0nsC9qsEoCVNWQngTvs8vahLY9R
LBV1cGN33t2FA/y8Y2+ioSKxf2iyq7uGx9uVT/upaOtLm12Qex8Q1eb9xAE5Zs4m
wbZqIDocR5FCzWXSKOkpXmk1ii9oMars++dGq6XWoFhU2Yr3Yh443aLJCSVAcayW
QHlWAl73SKAorhvDl+7EWAK6dzSVMv52xCsyAzDCx1ek119e09NzxAjth9mcI7PC
a9sH2WJuUuQUu9lBAa13QvIepZLBDw6AaFnsh4ve7xFPPiRr9JRLUxRUxiUvLMDO
8UDLRcYxqbMMSECbkmiZeylROTCXj3WLXtqWMoeDmiRX5m46E9FEAkPCkz1XFeeW
5tuRhk4gdyvWWWYNIQBWwcjnK0M0BxFfFOMNc+BDiq8wydFBk79b8oyk7ayYSuzk
MEC5R/YwL+pEYdK1QqaGoNySXPnserNOw9KFxXsEINTJGSl0WJqW0qPEAEfgEBRY
E2s//VCHsqY9/yTo3DMNy00DkFTtGqOCIA21NN/xPtPcxwSAvizgRbeNMysXiW/q
b7bzpfVnBWoHkt/QMi+jI1A3iQ==
-----END CERTIFICATE-----