Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ADDED] TLSServerName and TLSSkipVerify options #981

Merged
merged 1 commit into from
Dec 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions server/conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,16 @@ func parseTLS(itf interface{}, opts *Options) error {
return err
}
opts.ClientCA = v.(string)
case "server_name", "server_hostname":
if err := checkType(k, reflect.String, v); err != nil {
return err
}
opts.TLSServerName = v.(string)
case "skip_verify", "insecure":
if err := checkType(k, reflect.Bool, v); err != nil {
return err
}
opts.TLSSkipVerify = v.(bool)
}
}
return nil
Expand Down
8 changes: 8 additions & 0 deletions server/conf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@ func TestParseConfig(t *testing.T) {
if opts.ClientCA != "/path/to/client/ca_file" {
t.Fatalf("Expected ClientCA to be %q, got %q", "/path/to/client/ca_file", opts.ClientCA)
}
if opts.TLSServerName != "localhost" {
t.Fatalf("Expected TLSServerName to be %q, got %q", "localhost", opts.TLSServerName)
}
if !opts.TLSSkipVerify {
t.Fatalf("Expected TLSSkipVerify to be true, got %v", opts.TLSSkipVerify)
}
if opts.NATSCredentials != "credentials.creds" {
t.Fatalf("Expected Credentials to be %q, got %q", "credentials.creds", opts.NATSCredentials)
}
Expand Down Expand Up @@ -438,6 +444,8 @@ func TestParseWrongTypes(t *testing.T) {
expectFailureFor(t, "tls:{client_cert:123}", wrongTypeErr)
expectFailureFor(t, "tls:{client_key:123}", wrongTypeErr)
expectFailureFor(t, "tls:{client_ca:123}", wrongTypeErr)
expectFailureFor(t, "tls:{server_name:123}", wrongTypeErr)
expectFailureFor(t, "tls:{insecure:123}", wrongTypeErr)
expectFailureFor(t, "file:{compact:123}", wrongTypeErr)
expectFailureFor(t, "file:{compact_frag:false}", wrongTypeErr)
expectFailureFor(t, "file:{compact_interval:false}", wrongTypeErr)
Expand Down
34 changes: 33 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package server

import (
"crypto/tls"
"errors"
"fmt"
"net"
Expand Down Expand Up @@ -1273,10 +1274,12 @@ type Options struct {
Trace bool // Verbose trace
Debug bool // Debug trace
HandleSignals bool // Should the server setup a signal handler (for Ctrl+C, etc...)
Secure bool // Create a TLS enabled connection w/o server verification
Secure bool // Create a TLS enabled connection
ClientCert string // Client Certificate for TLS
ClientKey string // Client Key for TLS
ClientCA string // Client CAs for TLS
TLSSkipVerify bool // Skips the server's certificate chain and host name verification (Insecure!)
TLSServerName string // Used to verify the hostname returned in the server certificate
IOBatchSize int // Maximum number of messages collected from clients before starting their processing.
IOSleepTime int64 // Duration (in micro-seconds) the server waits for more message to fill up a batch.
NATSServerURL string // URL for external NATS Server to connect to. If empty, NATS Server is embedded.
Expand Down Expand Up @@ -1437,6 +1440,15 @@ func (s *StanServer) createNatsClientConn(name string) (*nats.Conn, error) {
for _, o := range s.opts.NATSClientOpts {
o(&ncOpts)
}
// If a TLSConfig is passed as an option, reject if streaming TLSServerName
// is set, but is different from the existing TLSConfig.ServerName.
if ncOpts.TLSConfig != nil &&
ncOpts.TLSConfig.ServerName != "" &&
s.opts.TLSServerName != "" &&
ncOpts.TLSConfig.ServerName != s.opts.TLSServerName {
return nil, fmt.Errorf("conflict between TLS configuration's ServerName %q and Streaming's TLSServerName %q",
ncOpts.TLSConfig.ServerName, s.opts.TLSServerName)
}

ncOpts.Servers, err = s.buildServerURLs()
if err != nil {
Expand Down Expand Up @@ -1475,6 +1487,23 @@ func (s *StanServer) createNatsClientConn(name string) (*nats.Conn, error) {
return nil, err
}
}
// Check for TLSSkipVerify and TLSServerName
if s.opts.TLSServerName != "" || s.opts.TLSSkipVerify {
// Create TLSConfig if needed
if ncOpts.TLSConfig == nil {
if err = nats.Secure(&tls.Config{})(&ncOpts); err != nil {
return nil, err
}
}
// Do not override if false or empty (since TLSConfig may have been
// passed as an option).
if s.opts.TLSSkipVerify {
ncOpts.TLSConfig.InsecureSkipVerify = s.opts.TLSSkipVerify
}
if s.opts.TLSServerName != "" {
ncOpts.TLSConfig.ServerName = s.opts.TLSServerName
}
}
// Shorten the time we wait to try to reconnect.
// Don't make it too often because it may exhaust the number of FDs.
ncOpts.ReconnectWait = 250 * time.Millisecond
Expand Down Expand Up @@ -1712,6 +1741,9 @@ func RunServerWithOpts(stanOpts *Options, natsOpts *server.Options) (newServer *
if err := s.createNatsConnections(); err != nil {
return nil, err
}
if sOpts.TLSSkipVerify {
s.log.Warnf("TLS certificate chain and hostname will not be verified. DO NOT USE IN PRODUCTION!")
}

// In FT mode, server cannot recover the store until it is elected leader.
if s.opts.FTGroupName != "" {
Expand Down
104 changes: 104 additions & 0 deletions server/server_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package server

import (
"crypto/tls"
"flag"
"fmt"
"os"
Expand Down Expand Up @@ -397,6 +398,109 @@ func TestTLSFailClientTLSServerPlain(t *testing.T) {
t.Fatal("Expected server to fail to start, it did not")
}
}

func TestTLSServerNameAndSkipVerify(t *testing.T) {
nOpts := DefaultNatsServerOptions

nOpts.Host = "0.0.0.0"
nOpts.TLSCert = "../test/certs/server-noip.pem"
nOpts.TLSKey = "../test/certs/server-key-noip.pem"
nOpts.TLSCaCert = "../test/certs/ca.pem"

sOpts := GetDefaultOptions()
sOpts.ClientCert = "../test/certs/client-cert.pem"
sOpts.ClientKey = "../test/certs/client-key.pem"
sOpts.ClientCA = "../test/certs/ca.pem"

s, err := RunServerWithOpts(sOpts, &nOpts)
if s != nil || err == nil {
s.Shutdown()
t.Fatal("Expected server to fail to start, it did not")
}

sOpts.TLSServerName = "localhost"
s, err = RunServerWithOpts(sOpts, &nOpts)
if err != nil {
t.Fatalf("Expected server to start ok, got %v", err)
}
s.Shutdown()
s = nil

sOpts.TLSServerName = ""
s, err = RunServerWithOpts(sOpts, &nOpts)
if s != nil || err == nil {
s.Shutdown()
t.Fatal("Expected server to fail to start, it did not")
}

sOpts.TLSSkipVerify = true
s, err = RunServerWithOpts(sOpts, &nOpts)
if err != nil {
t.Fatalf("Expected server to start ok, got %v", err)
}
s.Shutdown()

// With insecure, all client cert/key/ca can be removed
// and connections should still succeed
sOpts.ClientCert, sOpts.ClientKey, sOpts.ClientCA = "", "", ""
s, err = RunServerWithOpts(sOpts, &nOpts)
if err != nil {
t.Fatalf("Expected server to start ok, got %v", err)
}
s.Shutdown()

// However, it should fail if NATS Server requires client cert verification
nOpts.TLSVerify = true
s, err = RunServerWithOpts(sOpts, &nOpts)
if s != nil || err == nil {
s.Shutdown()
t.Fatal("Expected server to fail to start, it did not")
}
}

func TestTLSServerNameAndSkipVerifyConflicts(t *testing.T) {
nOpts := DefaultNatsServerOptions

nOpts.Host = "0.0.0.0"
nOpts.TLSCert = "../test/certs/server-noip.pem"
nOpts.TLSKey = "../test/certs/server-key-noip.pem"
nOpts.TLSCaCert = "../test/certs/ca.pem"

sOpts := GetDefaultOptions()
sOpts.NATSClientOpts = []nats.Option{nats.Secure(&tls.Config{ServerName: "localhost"})}
sOpts.ClientCert = "../test/certs/client-cert.pem"
sOpts.ClientKey = "../test/certs/client-key.pem"
sOpts.ClientCA = "../test/certs/ca.pem"
sOpts.TLSServerName = "confict"

s, err := RunServerWithOpts(sOpts, &nOpts)
if s != nil || err == nil {
s.Shutdown()
t.Fatal("Expected server to fail to start, it did not")
}
if !strings.Contains(err.Error(), "conflict between") {
t.Fatalf("Error should indicate conflict, got %v", err)
}
sOpts.TLSServerName = ""
s, err = RunServerWithOpts(sOpts, &nOpts)
if err != nil {
t.Fatalf("Unable to start server: %v", err)
}
s.Shutdown()

// Pass skip verify as a NATS option
sOpts.NATSClientOpts = []nats.Option{nats.Secure(&tls.Config{InsecureSkipVerify: true})}
// Use the wrong name for streaming TLSServerName
sOpts.TLSServerName = "wrong"
// And make sure that NATS Option skip veriy is not overridden with that..
sOpts.TLSSkipVerify = false
s, err = RunServerWithOpts(sOpts, &nOpts)
if err != nil {
t.Fatalf("Unable to start server: %v", err)
}
s.Shutdown()
}

func TestDontEmbedNATSNotRunning(t *testing.T) {
sOpts := GetDefaultOptions()
// Make sure that with empty string (normally the default), we
Expand Down
28 changes: 28 additions & 0 deletions test/certs/server-key-noip.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCt8Ic/MmaHejGb
ylQKrqYayiXVxfxJayEL3qcVyJw8zUEdMiV3aHuD6F0Uei4L6kGRpCDsIBcPy41M
G4ig0ndGZX7RoOZMS8aMOaGzWzRXyKEQDBNUOnSQezu62kFigfXctXNsgzj0oVKr
vcKVPnn/r6Su39YR2SkguLQV4zKTXDbOVrQBAqFFMaOhHuq4xAEEVxFE9FXq4q5o
CHCFwFv/ur/ei7yhxgOiL4rrnrd5OmdqsHDT6AinEiTVu1eIcjfI5i7bh+AqcRos
kJyIKQx1KITWf3UtUAg2K8/zujNyHnoH2yDamDs5hpZM4kpCYRqbC2dNbRPRn0Df
EseNnVBpAgMBAAECggEAcmiqXRwmqmfqZ4Ge4+Pap/ZdCo6OkjAf7XHHTyHD+o47
jRul3zPfQnU9fDGdRgMQm95sNUQqRx5pUy0tIjMtdyVdVD9UG80fzK4/uPx9olv5
7Nc0g4trjnkwYYgbx9KZyFGlmTN67BWMjiBj88zDbDW4ybm7UcQYNEipU1g8tQW1
tUwcZ1oahXfzO75vcMqDVlS2IE0s0AD9sh+AaJIwxV9kSLNjlSwkpsH6PBKKB/3r
WvG2p6Og1whdQ54PGADUVSx1yWFyXQDeygqLmryEWaHJQz1jt7bvaaAMy2PTdwVf
A5LVG3VHkoQOBv8imtpCbU2J7zAk9ypDuRUlpa8h/QKBgQDdCCCbV02BhrqDYchm
ojB95Vx8KtvQdXhvsxShxyuIktuB7W+NnheBmLY0TNcYSQyzithCUBhtmyaC5S4f
dHmT52e7HS0xaL9r9BhAQrtWReMcplKB1IIXtdYXEY3qOjZMxX3seJo0iBWS3hMH
EG6tC6tlr5ZXOKJOrBMGuMgplwKBgQDJdSYkC3AX2p+4BNf3hgQyzotuSVSbx/zu
0ZHhi8Wp7yF49c8+9+ahO9AMrVM0ZSh2buznfF46FNC/C55M7a9Rn60sFQQ16b5L
rJTzlPoUGTnPLt8C3TdMIFg/5cAW6ZgZWNlU3aVU0W34NVh/H2m/M72tGrk250zs
YhZ8/RGV/wKBgQCKlMfs3YXoyhIywaImR1Zj+ORNrYl4X86NKhirffbbgEhEZBvn
DNHsHVVP4UWTImnmQA1rNlC6l+ZDd3G9owd/Jj0xYg+txOEPzFFQKQbQBq1ojxd3
80dFmmqKuCTkUG8vHzvegZcdjJ0KIlaHvVPHB2QFM1vtf8Kz1MtxEXXeLQKBgDn0
Bm3WEH/8N3gzhIFDP0/yVO/8DmfmByAYj5PHpqw1C3cFl4HwxJrbXwVWkxn+g75W
OLZ684xX0pky2W4d7hJYEfQdc6GixUh1tD/COpKvkw7D2Am146N1po1zJWgx+LxJ
7/NW86nLuYvupK+lNMF5O/ZhOqjNrzZNHVUFZBq3AoGAPwixh7/ZMX6mmm8foImh
qibytx72gl1jhHWSaX3rwrSOO9dxO2rlI7LOZQrarU632Y9KMkP3HNbBHPRkA4MI
6I9wqawRzGjcpeXIMlPzOHDHYLyrTpEzo8nrSNk/cM8P4RxE12FqySzQIkiN06J7
AxJ7hVqtX6wZIoqoOa9aK1E=
-----END PRIVATE KEY-----
20 changes: 20 additions & 0 deletions test/certs/server-noip.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDNzCCAh+gAwIBAgIJAJT2U0V//QjNMA0GCSqGSIb3DQEBBQUAMHAxCzAJBgNV
BAYTAlVTMQswCQYDVQQIDAJDQTEQMA4GA1UECgwHU3luYWRpYTEQMA4GA1UECwwH
bmF0cy5pbzESMBAGA1UEAwwJbG9jYWxob3N0MRwwGgYJKoZIhvcNAQkBFg1kZXJl
a0BuYXRzLmlvMB4XDTE5MTAxNzE0MzA0MVoXDTI5MTAxNDE0MzA0MVowDTELMAkG
A1UEBhMCVVMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCt8Ic/MmaH
ejGbylQKrqYayiXVxfxJayEL3qcVyJw8zUEdMiV3aHuD6F0Uei4L6kGRpCDsIBcP
y41MG4ig0ndGZX7RoOZMS8aMOaGzWzRXyKEQDBNUOnSQezu62kFigfXctXNsgzj0
oVKrvcKVPnn/r6Su39YR2SkguLQV4zKTXDbOVrQBAqFFMaOhHuq4xAEEVxFE9FXq
4q5oCHCFwFv/ur/ei7yhxgOiL4rrnrd5OmdqsHDT6AinEiTVu1eIcjfI5i7bh+Aq
cRoskJyIKQx1KITWf3UtUAg2K8/zujNyHnoH2yDamDs5hpZM4kpCYRqbC2dNbRPR
n0DfEseNnVBpAgMBAAGjNzA1MBQGA1UdEQQNMAuCCWxvY2FsaG9zdDAdBgNVHSUE
FjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwDQYJKoZIhvcNAQEFBQADggEBAFwXf+6R
E9Xk6O878v6Vvub2SEnS9ObrLLQZWIxLPuz97+Up9BAafGQvbmwotoGzJnSpQK3g
NPagrIRtXhymH/kbvIuFCy17vbXy7OeYUoV+bsYJ/+PUcsqUkpo8xn5EUMAyMUZY
w6V8aftU96gSAO5dftg5ZJiU4BD63w1yvG0C5Xiy6ZpqEdJ0Jss2P33bbXyAdZgG
PVKqpAN0Wq1mZeBQz54bw2UEZHu34wpZGXaMsT4nzwQyzqVcyQfoe5bzWMFyDyGk
h2+ZXM1N4/Hxhu3DhjV5HiRQL+6dc/AwCZ7jzRr2ZqMCGuuxEsS8v24bKDV+I98n
Mv6MzHe/NqU6Bqc=
-----END CERTIFICATE-----
2 changes: 2 additions & 0 deletions test/configs/test_parse.conf
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ streaming: {
client_cert: "/path/to/client/cert_file"
client_key: "/path/to/client/key_file"
client_ca: "/path/to/client/ca_file"
server_name: "localhost"
insecure: true
}

file: {
Expand Down