github.com/nats-io/nats-server/v2@v2.11.0-preview.2/server/opts_test.go (about) 1 // Copyright 2012-2020 The NATS Authors 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package server 15 16 import ( 17 "bytes" 18 "crypto/tls" 19 "encoding/json" 20 "flag" 21 "fmt" 22 "net/url" 23 "os" 24 "reflect" 25 "runtime" 26 "strings" 27 "sync" 28 "sync/atomic" 29 "testing" 30 "time" 31 32 "github.com/nats-io/jwt/v2" 33 "github.com/nats-io/nats.go" 34 "github.com/nats-io/nkeys" 35 ) 36 37 func checkOptionsEqual(t *testing.T, golden, opts *Options) { 38 t.Helper() 39 // Clone them so we can remove private fields that we don't 40 // want to be compared. 41 goldenClone := golden.Clone() 42 goldenClone.inConfig, goldenClone.inCmdLine = nil, nil 43 optsClone := opts.Clone() 44 optsClone.inConfig, optsClone.inCmdLine = nil, nil 45 if !reflect.DeepEqual(goldenClone, optsClone) { 46 t.Fatalf("Options are incorrect.\nexpected: %+v\ngot: %+v", goldenClone, optsClone) 47 } 48 } 49 50 func TestDefaultOptions(t *testing.T) { 51 golden := &Options{ 52 Host: DEFAULT_HOST, 53 Port: DEFAULT_PORT, 54 MaxConn: DEFAULT_MAX_CONNECTIONS, 55 HTTPHost: DEFAULT_HOST, 56 PingInterval: DEFAULT_PING_INTERVAL, 57 MaxPingsOut: DEFAULT_PING_MAX_OUT, 58 TLSTimeout: float64(TLS_TIMEOUT) / float64(time.Second), 59 AuthTimeout: float64(AUTH_TIMEOUT) / float64(time.Second), 60 MaxControlLine: MAX_CONTROL_LINE_SIZE, 61 MaxPayload: MAX_PAYLOAD_SIZE, 62 MaxPending: MAX_PENDING_SIZE, 63 WriteDeadline: DEFAULT_FLUSH_DEADLINE, 64 MaxClosedClients: DEFAULT_MAX_CLOSED_CLIENTS, 65 LameDuckDuration: DEFAULT_LAME_DUCK_DURATION, 66 LameDuckGracePeriod: DEFAULT_LAME_DUCK_GRACE_PERIOD, 67 LeafNode: LeafNodeOpts{ 68 ReconnectInterval: DEFAULT_LEAF_NODE_RECONNECT, 69 }, 70 ConnectErrorReports: DEFAULT_CONNECT_ERROR_REPORTS, 71 ReconnectErrorReports: DEFAULT_RECONNECT_ERROR_REPORTS, 72 MaxTracedMsgLen: 0, 73 JetStreamMaxMemory: -1, 74 JetStreamMaxStore: -1, 75 SyncInterval: 2 * time.Minute, 76 } 77 78 opts := &Options{} 79 setBaselineOptions(opts) 80 81 checkOptionsEqual(t, golden, opts) 82 } 83 84 func TestOptions_RandomPort(t *testing.T) { 85 opts := &Options{Port: RANDOM_PORT} 86 setBaselineOptions(opts) 87 88 if opts.Port != 0 { 89 t.Fatalf("Process of options should have resolved random port to "+ 90 "zero.\nexpected: %d\ngot: %d", 0, opts.Port) 91 } 92 } 93 94 func TestConfigFile(t *testing.T) { 95 golden := &Options{ 96 ConfigFile: "./configs/test.conf", 97 ServerName: "testing_server", 98 Host: "127.0.0.1", 99 Port: 4242, 100 Username: "derek", 101 Password: "porkchop", 102 AuthTimeout: 1.0, 103 Debug: false, 104 Trace: true, 105 Logtime: false, 106 HTTPPort: 8222, 107 HTTPBasePath: "/nats", 108 PidFile: "/tmp/nats-server/nats-server.pid", 109 ProfPort: 6543, 110 Syslog: true, 111 RemoteSyslog: "udp://foo.com:33", 112 MaxControlLine: 2048, 113 MaxPayload: 65536, 114 MaxConn: 100, 115 MaxSubs: 1000, 116 MaxPending: 10000000, 117 PingInterval: 60 * time.Second, 118 MaxPingsOut: 3, 119 WriteDeadline: 3 * time.Second, 120 LameDuckDuration: 4 * time.Minute, 121 ConnectErrorReports: 86400, 122 ReconnectErrorReports: 5, 123 authBlockDefined: true, 124 } 125 126 opts, err := ProcessConfigFile("./configs/test.conf") 127 if err != nil { 128 t.Fatalf("Received an error reading config file: %v", err) 129 } 130 131 checkOptionsEqual(t, golden, opts) 132 } 133 134 func TestTLSConfigFile(t *testing.T) { 135 golden := &Options{ 136 ConfigFile: "./configs/tls.conf", 137 Host: "127.0.0.1", 138 Port: 4443, 139 Username: "derek", 140 Password: "foo", 141 AuthTimeout: 1.0, 142 TLSTimeout: 2.0, 143 authBlockDefined: true, 144 } 145 opts, err := ProcessConfigFile("./configs/tls.conf") 146 if err != nil { 147 t.Fatalf("Received an error reading config file: %v", err) 148 } 149 tlsConfig := opts.TLSConfig 150 if tlsConfig == nil { 151 t.Fatal("Expected opts.TLSConfig to be non-nil") 152 } 153 opts.TLSConfig = nil 154 opts.tlsConfigOpts = nil 155 checkOptionsEqual(t, golden, opts) 156 157 // Now check TLSConfig a bit more closely 158 // CipherSuites 159 ciphers := defaultCipherSuites() 160 if !reflect.DeepEqual(tlsConfig.CipherSuites, ciphers) { 161 t.Fatalf("Got incorrect cipher suite list: [%+v]", tlsConfig.CipherSuites) 162 } 163 if tlsConfig.MinVersion != tls.VersionTLS12 { 164 t.Fatalf("Expected MinVersion of 1.2 [%v], got [%v]", tls.VersionTLS12, tlsConfig.MinVersion) 165 } 166 //lint:ignore SA1019 We want to retry on a bunch of errors here. 167 if !tlsConfig.PreferServerCipherSuites { // nolint:staticcheck 168 t.Fatal("Expected PreferServerCipherSuites to be true") 169 } 170 // Verify hostname is correct in certificate 171 if len(tlsConfig.Certificates) != 1 { 172 t.Fatal("Expected 1 certificate") 173 } 174 cert := tlsConfig.Certificates[0].Leaf 175 if err := cert.VerifyHostname("127.0.0.1"); err != nil { 176 t.Fatalf("Could not verify hostname in certificate: %v", err) 177 } 178 179 // Now test adding cipher suites. 180 opts, err = ProcessConfigFile("./configs/tls_ciphers.conf") 181 if err != nil { 182 t.Fatalf("Received an error reading config file: %v", err) 183 } 184 tlsConfig = opts.TLSConfig 185 if tlsConfig == nil { 186 t.Fatal("Expected opts.TLSConfig to be non-nil") 187 } 188 189 // CipherSuites listed in the config - test all of them. 190 ciphers = []uint16{ 191 tls.TLS_RSA_WITH_RC4_128_SHA, 192 tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA, 193 tls.TLS_RSA_WITH_AES_128_CBC_SHA, 194 tls.TLS_RSA_WITH_AES_256_CBC_SHA, 195 tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 196 tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 197 tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 198 tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA, 199 tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 200 tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 201 tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 202 tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 203 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 204 } 205 206 if !reflect.DeepEqual(tlsConfig.CipherSuites, ciphers) { 207 t.Fatalf("Got incorrect cipher suite list: [%+v]", tlsConfig.CipherSuites) 208 } 209 210 // Test an unrecognized/bad cipher 211 if _, err := ProcessConfigFile("./configs/tls_bad_cipher.conf"); err == nil { 212 t.Fatal("Did not receive an error from a unrecognized cipher") 213 } 214 215 // Test an empty cipher entry in a config file. 216 if _, err := ProcessConfigFile("./configs/tls_empty_cipher.conf"); err == nil { 217 t.Fatal("Did not receive an error from empty cipher_suites") 218 } 219 220 // Test a curve preference from the config. 221 curves := []tls.CurveID{ 222 tls.CurveP256, 223 } 224 225 // test on a file that will load the curve preference defaults 226 opts, err = ProcessConfigFile("./configs/tls_ciphers.conf") 227 if err != nil { 228 t.Fatalf("Received an error reading config file: %v", err) 229 } 230 231 if !reflect.DeepEqual(opts.TLSConfig.CurvePreferences, defaultCurvePreferences()) { 232 t.Fatalf("Got incorrect curve preference list: [%+v]", tlsConfig.CurvePreferences) 233 } 234 235 // Test specifying a single curve preference 236 opts, err = ProcessConfigFile("./configs/tls_curve_prefs.conf") 237 if err != nil { 238 t.Fatal("Did not receive an error from a unrecognized cipher.") 239 } 240 241 if !reflect.DeepEqual(opts.TLSConfig.CurvePreferences, curves) { 242 t.Fatalf("Got incorrect cipher suite list: [%+v]", tlsConfig.CurvePreferences) 243 } 244 245 // Test an unrecognized/bad curve preference 246 if _, err := ProcessConfigFile("./configs/tls_bad_curve_prefs.conf"); err == nil { 247 t.Fatal("Did not receive an error from a unrecognized curve preference") 248 } 249 // Test an empty curve preference 250 if _, err := ProcessConfigFile("./configs/tls_empty_curve_prefs.conf"); err == nil { 251 t.Fatal("Did not receive an error from empty curve preferences") 252 } 253 } 254 255 func TestMergeOverrides(t *testing.T) { 256 golden := &Options{ 257 ConfigFile: "./configs/test.conf", 258 ServerName: "testing_server", 259 Host: "127.0.0.1", 260 Port: 2222, 261 Username: "derek", 262 Password: "porkchop", 263 AuthTimeout: 1.0, 264 Debug: true, 265 Trace: true, 266 Logtime: false, 267 HTTPPort: DEFAULT_HTTP_PORT, 268 HTTPBasePath: DEFAULT_HTTP_BASE_PATH, 269 PidFile: "/tmp/nats-server/nats-server.pid", 270 ProfPort: 6789, 271 Syslog: true, 272 RemoteSyslog: "udp://foo.com:33", 273 MaxControlLine: 2048, 274 MaxPayload: 65536, 275 MaxConn: 100, 276 MaxSubs: 1000, 277 MaxPending: 10000000, 278 PingInterval: 60 * time.Second, 279 MaxPingsOut: 3, 280 Cluster: ClusterOpts{ 281 NoAdvertise: true, 282 ConnectRetries: 2, 283 }, 284 WriteDeadline: 3 * time.Second, 285 LameDuckDuration: 4 * time.Minute, 286 ConnectErrorReports: 86400, 287 ReconnectErrorReports: 5, 288 authBlockDefined: true, 289 } 290 fopts, err := ProcessConfigFile("./configs/test.conf") 291 if err != nil { 292 t.Fatalf("Received an error reading config file: %v", err) 293 } 294 295 // Overrides via flags 296 opts := &Options{ 297 Port: 2222, 298 Password: "porkchop", 299 Debug: true, 300 HTTPPort: DEFAULT_HTTP_PORT, 301 HTTPBasePath: DEFAULT_HTTP_BASE_PATH, 302 ProfPort: 6789, 303 Cluster: ClusterOpts{ 304 NoAdvertise: true, 305 ConnectRetries: 2, 306 }, 307 } 308 merged := MergeOptions(fopts, opts) 309 310 checkOptionsEqual(t, golden, merged) 311 } 312 313 func TestRemoveSelfReference(t *testing.T) { 314 url1, _ := url.Parse("nats-route://user:password@10.4.5.6:4223") 315 url2, _ := url.Parse("nats-route://user:password@127.0.0.1:4223") 316 url3, _ := url.Parse("nats-route://user:password@127.0.0.1:4223") 317 318 routes := []*url.URL{url1, url2, url3} 319 320 newroutes, err := RemoveSelfReference(4223, routes) 321 if err != nil { 322 t.Fatalf("Error during RemoveSelfReference: %v", err) 323 } 324 325 if len(newroutes) != 1 { 326 t.Fatalf("Wrong number of routes: %d", len(newroutes)) 327 } 328 329 if newroutes[0] != routes[0] { 330 t.Fatalf("Self reference IP address %s in Routes", routes[0]) 331 } 332 } 333 334 func TestAllowRouteWithDifferentPort(t *testing.T) { 335 url1, _ := url.Parse("nats-route://user:password@127.0.0.1:4224") 336 routes := []*url.URL{url1} 337 338 newroutes, err := RemoveSelfReference(4223, routes) 339 if err != nil { 340 t.Fatalf("Error during RemoveSelfReference: %v", err) 341 } 342 343 if len(newroutes) != 1 { 344 t.Fatalf("Wrong number of routes: %d", len(newroutes)) 345 } 346 } 347 348 func TestRouteFlagOverride(t *testing.T) { 349 routeFlag := "nats-route://ruser:top_secret@127.0.0.1:8246" 350 rurl, _ := url.Parse(routeFlag) 351 352 golden := &Options{ 353 ConfigFile: "./configs/srv_a.conf", 354 Host: "127.0.0.1", 355 Port: 7222, 356 Cluster: ClusterOpts{ 357 Name: "abc", 358 Host: "127.0.0.1", 359 Port: 7244, 360 Username: "ruser", 361 Password: "top_secret", 362 AuthTimeout: 0.5, 363 }, 364 Routes: []*url.URL{rurl}, 365 RoutesStr: routeFlag, 366 } 367 368 fopts, err := ProcessConfigFile("./configs/srv_a.conf") 369 if err != nil { 370 t.Fatalf("Received an error reading config file: %v", err) 371 } 372 373 // Overrides via flags 374 opts := &Options{ 375 RoutesStr: routeFlag, 376 } 377 merged := MergeOptions(fopts, opts) 378 379 checkOptionsEqual(t, golden, merged) 380 } 381 382 func TestClusterFlagsOverride(t *testing.T) { 383 routeFlag := "nats-route://ruser:top_secret@127.0.0.1:7246" 384 rurl, _ := url.Parse(routeFlag) 385 386 // In this test, we override the cluster listen string. Note that in 387 // the golden options, the cluster other infos correspond to what 388 // is recovered from the configuration file, this explains the 389 // discrepency between ClusterListenStr and the rest. 390 // The server would then process the ClusterListenStr override and 391 // correctly override ClusterHost/ClustherPort/etc.. 392 golden := &Options{ 393 ConfigFile: "./configs/srv_a.conf", 394 Host: "127.0.0.1", 395 Port: 7222, 396 Cluster: ClusterOpts{ 397 Name: "abc", 398 Host: "127.0.0.1", 399 Port: 7244, 400 ListenStr: "nats://127.0.0.1:8224", 401 Username: "ruser", 402 Password: "top_secret", 403 AuthTimeout: 0.5, 404 }, 405 Routes: []*url.URL{rurl}, 406 } 407 408 fopts, err := ProcessConfigFile("./configs/srv_a.conf") 409 if err != nil { 410 t.Fatalf("Received an error reading config file: %v", err) 411 } 412 413 // Overrides via flags 414 opts := &Options{ 415 Cluster: ClusterOpts{ 416 ListenStr: "nats://127.0.0.1:8224", 417 }, 418 } 419 merged := MergeOptions(fopts, opts) 420 421 checkOptionsEqual(t, golden, merged) 422 } 423 424 func TestRouteFlagOverrideWithMultiple(t *testing.T) { 425 routeFlag := "nats-route://ruser:top_secret@127.0.0.1:8246, nats-route://ruser:top_secret@127.0.0.1:8266" 426 rurls := RoutesFromStr(routeFlag) 427 428 golden := &Options{ 429 ConfigFile: "./configs/srv_a.conf", 430 Host: "127.0.0.1", 431 Port: 7222, 432 Cluster: ClusterOpts{ 433 Host: "127.0.0.1", 434 Name: "abc", 435 Port: 7244, 436 Username: "ruser", 437 Password: "top_secret", 438 AuthTimeout: 0.5, 439 }, 440 Routes: rurls, 441 RoutesStr: routeFlag, 442 } 443 444 fopts, err := ProcessConfigFile("./configs/srv_a.conf") 445 if err != nil { 446 t.Fatalf("Received an error reading config file: %v", err) 447 } 448 449 // Overrides via flags 450 opts := &Options{ 451 RoutesStr: routeFlag, 452 } 453 merged := MergeOptions(fopts, opts) 454 455 checkOptionsEqual(t, golden, merged) 456 } 457 458 func TestDynamicPortOnListen(t *testing.T) { 459 opts, err := ProcessConfigFile("./configs/listen-1.conf") 460 if err != nil { 461 t.Fatalf("Received an error reading config file: %v", err) 462 } 463 if opts.Port != -1 { 464 t.Fatalf("Received incorrect port %v, expected -1", opts.Port) 465 } 466 if opts.HTTPPort != -1 { 467 t.Fatalf("Received incorrect monitoring port %v, expected -1", opts.HTTPPort) 468 } 469 if opts.HTTPSPort != -1 { 470 t.Fatalf("Received incorrect secure monitoring port %v, expected -1", opts.HTTPSPort) 471 } 472 } 473 474 func TestListenConfig(t *testing.T) { 475 opts, err := ProcessConfigFile("./configs/listen.conf") 476 if err != nil { 477 t.Fatalf("Received an error reading config file: %v", err) 478 } 479 setBaselineOptions(opts) 480 481 // Normal clients 482 host := "10.0.1.22" 483 port := 4422 484 monHost := "127.0.0.1" 485 if opts.Host != host { 486 t.Fatalf("Received incorrect host %q, expected %q", opts.Host, host) 487 } 488 if opts.HTTPHost != monHost { 489 t.Fatalf("Received incorrect host %q, expected %q", opts.HTTPHost, monHost) 490 } 491 if opts.Port != port { 492 t.Fatalf("Received incorrect port %v, expected %v", opts.Port, port) 493 } 494 495 // Clustering 496 clusterHost := "127.0.0.1" 497 clusterPort := 4244 498 499 if opts.Cluster.Host != clusterHost { 500 t.Fatalf("Received incorrect cluster host %q, expected %q", opts.Cluster.Host, clusterHost) 501 } 502 if opts.Cluster.Port != clusterPort { 503 t.Fatalf("Received incorrect cluster port %v, expected %v", opts.Cluster.Port, clusterPort) 504 } 505 506 // HTTP 507 httpHost := "127.0.0.1" 508 httpPort := 8422 509 510 if opts.HTTPHost != httpHost { 511 t.Fatalf("Received incorrect http host %q, expected %q", opts.HTTPHost, httpHost) 512 } 513 if opts.HTTPPort != httpPort { 514 t.Fatalf("Received incorrect http port %v, expected %v", opts.HTTPPort, httpPort) 515 } 516 517 // HTTPS 518 httpsPort := 9443 519 if opts.HTTPSPort != httpsPort { 520 t.Fatalf("Received incorrect https port %v, expected %v", opts.HTTPSPort, httpsPort) 521 } 522 } 523 524 func TestListenPortOnlyConfig(t *testing.T) { 525 opts, err := ProcessConfigFile("./configs/listen_port.conf") 526 if err != nil { 527 t.Fatalf("Received an error reading config file: %v", err) 528 } 529 setBaselineOptions(opts) 530 531 port := 8922 532 533 if opts.Host != DEFAULT_HOST { 534 t.Fatalf("Received incorrect host %q, expected %q", opts.Host, DEFAULT_HOST) 535 } 536 if opts.HTTPHost != DEFAULT_HOST { 537 t.Fatalf("Received incorrect host %q, expected %q", opts.Host, DEFAULT_HOST) 538 } 539 if opts.Port != port { 540 t.Fatalf("Received incorrect port %v, expected %v", opts.Port, port) 541 } 542 } 543 544 func TestListenPortWithColonConfig(t *testing.T) { 545 opts, err := ProcessConfigFile("./configs/listen_port_with_colon.conf") 546 if err != nil { 547 t.Fatalf("Received an error reading config file: %v", err) 548 } 549 setBaselineOptions(opts) 550 551 port := 8922 552 553 if opts.Host != DEFAULT_HOST { 554 t.Fatalf("Received incorrect host %q, expected %q", opts.Host, DEFAULT_HOST) 555 } 556 if opts.HTTPHost != DEFAULT_HOST { 557 t.Fatalf("Received incorrect host %q, expected %q", opts.Host, DEFAULT_HOST) 558 } 559 if opts.Port != port { 560 t.Fatalf("Received incorrect port %v, expected %v", opts.Port, port) 561 } 562 } 563 564 func TestListenMonitoringDefault(t *testing.T) { 565 opts := &Options{ 566 Host: "10.0.1.22", 567 } 568 setBaselineOptions(opts) 569 570 host := "10.0.1.22" 571 if opts.Host != host { 572 t.Fatalf("Received incorrect host %q, expected %q", opts.Host, host) 573 } 574 if opts.HTTPHost != host { 575 t.Fatalf("Received incorrect host %q, expected %q", opts.Host, host) 576 } 577 if opts.Port != DEFAULT_PORT { 578 t.Fatalf("Received incorrect port %v, expected %v", opts.Port, DEFAULT_PORT) 579 } 580 } 581 582 func TestMultipleUsersConfig(t *testing.T) { 583 opts, err := ProcessConfigFile("./configs/multiple_users.conf") 584 if err != nil { 585 t.Fatalf("Received an error reading config file: %v", err) 586 } 587 setBaselineOptions(opts) 588 } 589 590 // Test highly depends on contents of the config file listed below. Any changes to that file 591 // may very well break this test. 592 func TestAuthorizationConfig(t *testing.T) { 593 opts, err := ProcessConfigFile("./configs/authorization.conf") 594 if err != nil { 595 t.Fatalf("Received an error reading config file: %v", err) 596 } 597 setBaselineOptions(opts) 598 lu := len(opts.Users) 599 if lu != 5 { 600 t.Fatalf("Expected 5 users, got %d", lu) 601 } 602 // Build a map 603 mu := make(map[string]*User) 604 for _, u := range opts.Users { 605 mu[u.Username] = u 606 } 607 608 // Alice 609 alice, ok := mu["alice"] 610 if !ok { 611 t.Fatalf("Expected to see user Alice") 612 } 613 // Check for permissions details 614 if alice.Permissions == nil { 615 t.Fatalf("Expected Alice's permissions to be non-nil") 616 } 617 if alice.Permissions.Publish == nil { 618 t.Fatalf("Expected Alice's publish permissions to be non-nil") 619 } 620 if len(alice.Permissions.Publish.Allow) != 1 { 621 t.Fatalf("Expected Alice's publish permissions to have 1 element, got %d", 622 len(alice.Permissions.Publish.Allow)) 623 } 624 pubPerm := alice.Permissions.Publish.Allow[0] 625 if pubPerm != "*" { 626 t.Fatalf("Expected Alice's publish permissions to be '*', got %q", pubPerm) 627 } 628 if alice.Permissions.Subscribe == nil { 629 t.Fatalf("Expected Alice's subscribe permissions to be non-nil") 630 } 631 if len(alice.Permissions.Subscribe.Allow) != 1 { 632 t.Fatalf("Expected Alice's subscribe permissions to have 1 element, got %d", 633 len(alice.Permissions.Subscribe.Allow)) 634 } 635 subPerm := alice.Permissions.Subscribe.Allow[0] 636 if subPerm != ">" { 637 t.Fatalf("Expected Alice's subscribe permissions to be '>', got %q", subPerm) 638 } 639 640 // Bob 641 bob, ok := mu["bob"] 642 if !ok { 643 t.Fatalf("Expected to see user Bob") 644 } 645 if bob.Permissions == nil { 646 t.Fatalf("Expected Bob's permissions to be non-nil") 647 } 648 649 // Susan 650 susan, ok := mu["susan"] 651 if !ok { 652 t.Fatalf("Expected to see user Susan") 653 } 654 if susan.Permissions == nil { 655 t.Fatalf("Expected Susan's permissions to be non-nil") 656 } 657 // Check susan closely since she inherited the default permissions. 658 if susan.Permissions == nil { 659 t.Fatalf("Expected Susan's permissions to be non-nil") 660 } 661 if susan.Permissions.Publish != nil { 662 t.Fatalf("Expected Susan's publish permissions to be nil") 663 } 664 if susan.Permissions.Subscribe == nil { 665 t.Fatalf("Expected Susan's subscribe permissions to be non-nil") 666 } 667 if len(susan.Permissions.Subscribe.Allow) != 1 { 668 t.Fatalf("Expected Susan's subscribe permissions to have 1 element, got %d", 669 len(susan.Permissions.Subscribe.Allow)) 670 } 671 subPerm = susan.Permissions.Subscribe.Allow[0] 672 if subPerm != "PUBLIC.>" { 673 t.Fatalf("Expected Susan's subscribe permissions to be 'PUBLIC.>', got %q", subPerm) 674 } 675 676 // Service A 677 svca, ok := mu["svca"] 678 if !ok { 679 t.Fatalf("Expected to see user Service A") 680 } 681 if svca.Permissions == nil { 682 t.Fatalf("Expected Service A's permissions to be non-nil") 683 } 684 if svca.Permissions.Subscribe == nil { 685 t.Fatalf("Expected Service A's subscribe permissions to be non-nil") 686 } 687 if len(svca.Permissions.Subscribe.Allow) != 1 { 688 t.Fatalf("Expected Service A's subscribe permissions to have 1 element, got %d", 689 len(svca.Permissions.Subscribe.Allow)) 690 } 691 subPerm = svca.Permissions.Subscribe.Allow[0] 692 if subPerm != "my.service.req" { 693 t.Fatalf("Expected Service A's subscribe permissions to be 'my.service.req', got %q", subPerm) 694 } 695 // We want allow_responses to essentially set deny all, or allow none in this case. 696 if svca.Permissions.Publish == nil { 697 t.Fatalf("Expected Service A's publish permissions to be non-nil") 698 } 699 if len(svca.Permissions.Publish.Allow) != 0 { 700 t.Fatalf("Expected Service A's publish permissions to have no elements, got %d", 701 len(svca.Permissions.Publish.Allow)) 702 } 703 // We should have a ResponsePermission present with default values. 704 if svca.Permissions.Response == nil { 705 t.Fatalf("Expected Service A's response permissions to be non-nil") 706 } 707 if svca.Permissions.Response.MaxMsgs != DEFAULT_ALLOW_RESPONSE_MAX_MSGS { 708 t.Fatalf("Expected Service A's response permissions of max msgs to be %d, got %d", 709 DEFAULT_ALLOW_RESPONSE_MAX_MSGS, svca.Permissions.Response.MaxMsgs, 710 ) 711 } 712 if svca.Permissions.Response.Expires != DEFAULT_ALLOW_RESPONSE_EXPIRATION { 713 t.Fatalf("Expected Service A's response permissions of expiration to be %v, got %v", 714 DEFAULT_ALLOW_RESPONSE_EXPIRATION, svca.Permissions.Response.Expires, 715 ) 716 } 717 718 // Service B 719 svcb, ok := mu["svcb"] 720 if !ok { 721 t.Fatalf("Expected to see user Service B") 722 } 723 if svcb.Permissions == nil { 724 t.Fatalf("Expected Service B's permissions to be non-nil") 725 } 726 if svcb.Permissions.Subscribe == nil { 727 t.Fatalf("Expected Service B's subscribe permissions to be non-nil") 728 } 729 if len(svcb.Permissions.Subscribe.Allow) != 1 { 730 t.Fatalf("Expected Service B's subscribe permissions to have 1 element, got %d", 731 len(svcb.Permissions.Subscribe.Allow)) 732 } 733 subPerm = svcb.Permissions.Subscribe.Allow[0] 734 if subPerm != "my.service.req" { 735 t.Fatalf("Expected Service B's subscribe permissions to be 'my.service.req', got %q", subPerm) 736 } 737 // We want allow_responses to essentially set deny all, or allow none in this case. 738 if svcb.Permissions.Publish == nil { 739 t.Fatalf("Expected Service B's publish permissions to be non-nil") 740 } 741 if len(svcb.Permissions.Publish.Allow) != 0 { 742 t.Fatalf("Expected Service B's publish permissions to have no elements, got %d", 743 len(svcb.Permissions.Publish.Allow)) 744 } 745 // We should have a ResponsePermission present with default values. 746 if svcb.Permissions.Response == nil { 747 t.Fatalf("Expected Service B's response permissions to be non-nil") 748 } 749 if svcb.Permissions.Response.MaxMsgs != 10 { 750 t.Fatalf("Expected Service B's response permissions of max msgs to be %d, got %d", 751 10, svcb.Permissions.Response.MaxMsgs, 752 ) 753 } 754 if svcb.Permissions.Response.Expires != time.Minute { 755 t.Fatalf("Expected Service B's response permissions of expiration to be %v, got %v", 756 time.Minute, svcb.Permissions.Response.Expires, 757 ) 758 } 759 } 760 761 // Test highly depends on contents of the config file listed below. Any changes to that file 762 // may very well break this test. 763 func TestNewStyleAuthorizationConfig(t *testing.T) { 764 opts, err := ProcessConfigFile("./configs/new_style_authorization.conf") 765 if err != nil { 766 t.Fatalf("Received an error reading config file: %v", err) 767 } 768 setBaselineOptions(opts) 769 770 lu := len(opts.Users) 771 if lu != 2 { 772 t.Fatalf("Expected 2 users, got %d", lu) 773 } 774 // Build a map 775 mu := make(map[string]*User) 776 for _, u := range opts.Users { 777 mu[u.Username] = u 778 } 779 // Alice 780 alice, ok := mu["alice"] 781 if !ok { 782 t.Fatalf("Expected to see user Alice") 783 } 784 if alice.Permissions == nil { 785 t.Fatalf("Expected Alice's permissions to be non-nil") 786 } 787 788 if alice.Permissions.Publish == nil { 789 t.Fatalf("Expected Alice's publish permissions to be non-nil") 790 } 791 if len(alice.Permissions.Publish.Allow) != 3 { 792 t.Fatalf("Expected Alice's allowed publish permissions to have 3 elements, got %d", 793 len(alice.Permissions.Publish.Allow)) 794 } 795 pubPerm := alice.Permissions.Publish.Allow[0] 796 if pubPerm != "foo" { 797 t.Fatalf("Expected Alice's first allowed publish permission to be 'foo', got %q", pubPerm) 798 } 799 pubPerm = alice.Permissions.Publish.Allow[1] 800 if pubPerm != "bar" { 801 t.Fatalf("Expected Alice's second allowed publish permission to be 'bar', got %q", pubPerm) 802 } 803 pubPerm = alice.Permissions.Publish.Allow[2] 804 if pubPerm != "baz" { 805 t.Fatalf("Expected Alice's third allowed publish permission to be 'baz', got %q", pubPerm) 806 } 807 if len(alice.Permissions.Publish.Deny) != 0 { 808 t.Fatalf("Expected Alice's denied publish permissions to have 0 elements, got %d", 809 len(alice.Permissions.Publish.Deny)) 810 } 811 812 if alice.Permissions.Subscribe == nil { 813 t.Fatalf("Expected Alice's subscribe permissions to be non-nil") 814 } 815 if len(alice.Permissions.Subscribe.Allow) != 0 { 816 t.Fatalf("Expected Alice's allowed subscribe permissions to have 0 elements, got %d", 817 len(alice.Permissions.Subscribe.Allow)) 818 } 819 if len(alice.Permissions.Subscribe.Deny) != 1 { 820 t.Fatalf("Expected Alice's denied subscribe permissions to have 1 element, got %d", 821 len(alice.Permissions.Subscribe.Deny)) 822 } 823 subPerm := alice.Permissions.Subscribe.Deny[0] 824 if subPerm != "$SYS.>" { 825 t.Fatalf("Expected Alice's only denied subscribe permission to be '$SYS.>', got %q", subPerm) 826 } 827 828 // Bob 829 bob, ok := mu["bob"] 830 if !ok { 831 t.Fatalf("Expected to see user Bob") 832 } 833 if bob.Permissions == nil { 834 t.Fatalf("Expected Bob's permissions to be non-nil") 835 } 836 837 if bob.Permissions.Publish == nil { 838 t.Fatalf("Expected Bobs's publish permissions to be non-nil") 839 } 840 if len(bob.Permissions.Publish.Allow) != 1 { 841 t.Fatalf("Expected Bob's allowed publish permissions to have 1 element, got %d", 842 len(bob.Permissions.Publish.Allow)) 843 } 844 pubPerm = bob.Permissions.Publish.Allow[0] 845 if pubPerm != "$SYS.>" { 846 t.Fatalf("Expected Bob's first allowed publish permission to be '$SYS.>', got %q", pubPerm) 847 } 848 if len(bob.Permissions.Publish.Deny) != 0 { 849 t.Fatalf("Expected Bob's denied publish permissions to have 0 elements, got %d", 850 len(bob.Permissions.Publish.Deny)) 851 } 852 853 if bob.Permissions.Subscribe == nil { 854 t.Fatalf("Expected Bob's subscribe permissions to be non-nil") 855 } 856 if len(bob.Permissions.Subscribe.Allow) != 0 { 857 t.Fatalf("Expected Bob's allowed subscribe permissions to have 0 elements, got %d", 858 len(bob.Permissions.Subscribe.Allow)) 859 } 860 if len(bob.Permissions.Subscribe.Deny) != 3 { 861 t.Fatalf("Expected Bobs's denied subscribe permissions to have 3 elements, got %d", 862 len(bob.Permissions.Subscribe.Deny)) 863 } 864 subPerm = bob.Permissions.Subscribe.Deny[0] 865 if subPerm != "foo" { 866 t.Fatalf("Expected Bobs's first denied subscribe permission to be 'foo', got %q", subPerm) 867 } 868 subPerm = bob.Permissions.Subscribe.Deny[1] 869 if subPerm != "bar" { 870 t.Fatalf("Expected Bobs's second denied subscribe permission to be 'bar', got %q", subPerm) 871 } 872 subPerm = bob.Permissions.Subscribe.Deny[2] 873 if subPerm != "baz" { 874 t.Fatalf("Expected Bobs's third denied subscribe permission to be 'baz', got %q", subPerm) 875 } 876 } 877 878 // Test new nkey users 879 func TestNkeyUsersConfig(t *testing.T) { 880 confFileName := createConfFile(t, []byte(` 881 authorization { 882 users = [ 883 {nkey: "UDKTV7HZVYJFJN64LLMYQBUR6MTNNYCDC3LAZH4VHURW3GZLL3FULBXV"} 884 {nkey: "UA3C5TBZYK5GJQJRWPMU6NFY5JNAEVQB2V2TUZFZDHFJFUYVKTTUOFKZ"} 885 ] 886 }`)) 887 opts, err := ProcessConfigFile(confFileName) 888 if err != nil { 889 t.Fatalf("Received an error reading config file: %v", err) 890 } 891 lu := len(opts.Nkeys) 892 if lu != 2 { 893 t.Fatalf("Expected 2 nkey users, got %d", lu) 894 } 895 } 896 897 // Test pinned certificates 898 func TestTlsPinnedCertificates(t *testing.T) { 899 confFileName := createConfFile(t, []byte(` 900 tls { 901 cert_file: "./configs/certs/server.pem" 902 key_file: "./configs/certs/key.pem" 903 # Require a client certificate and map user id from certificate 904 verify: true 905 pinned_certs: ["7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", 906 "a8f407340dcc719864214b85ed96f98d16cbffa8f509d9fa4ca237b7bb3f9c32"] 907 } 908 cluster { 909 port -1 910 name cluster-hub 911 tls { 912 cert_file: "./configs/certs/server.pem" 913 key_file: "./configs/certs/key.pem" 914 # Require a client certificate and map user id from certificate 915 verify: true 916 pinned_certs: ["7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", 917 "a8f407340dcc719864214b85ed96f98d16cbffa8f509d9fa4ca237b7bb3f9c32"] 918 } 919 } 920 leafnodes { 921 port -1 922 tls { 923 cert_file: "./configs/certs/server.pem" 924 key_file: "./configs/certs/key.pem" 925 # Require a client certificate and map user id from certificate 926 verify: true 927 pinned_certs: ["7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", 928 "a8f407340dcc719864214b85ed96f98d16cbffa8f509d9fa4ca237b7bb3f9c32"] 929 } 930 } 931 gateway { 932 name: "A" 933 port -1 934 tls { 935 cert_file: "./configs/certs/server.pem" 936 key_file: "./configs/certs/key.pem" 937 # Require a client certificate and map user id from certificate 938 verify: true 939 pinned_certs: ["7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", 940 "a8f407340dcc719864214b85ed96f98d16cbffa8f509d9fa4ca237b7bb3f9c32"] 941 } 942 } 943 websocket { 944 port -1 945 tls { 946 cert_file: "./configs/certs/server.pem" 947 key_file: "./configs/certs/key.pem" 948 # Require a client certificate and map user id from certificate 949 verify: true 950 pinned_certs: ["7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", 951 "a8f407340dcc719864214b85ed96f98d16cbffa8f509d9fa4ca237b7bb3f9c32"] 952 } 953 } 954 mqtt { 955 port -1 956 tls { 957 cert_file: "./configs/certs/server.pem" 958 key_file: "./configs/certs/key.pem" 959 # Require a client certificate and map user id from certificate 960 verify: true 961 pinned_certs: ["7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", 962 "a8f407340dcc719864214b85ed96f98d16cbffa8f509d9fa4ca237b7bb3f9c32"] 963 } 964 }`)) 965 opts, err := ProcessConfigFile(confFileName) 966 if err != nil { 967 t.Fatalf("Received an error reading config file: %v", err) 968 } 969 check := func(set PinnedCertSet) { 970 t.Helper() 971 if l := len(set); l != 2 { 972 t.Fatalf("Expected 2 pinned certificates, got got %d", l) 973 } 974 } 975 976 check(opts.TLSPinnedCerts) 977 check(opts.LeafNode.TLSPinnedCerts) 978 check(opts.Cluster.TLSPinnedCerts) 979 check(opts.MQTT.TLSPinnedCerts) 980 check(opts.Gateway.TLSPinnedCerts) 981 check(opts.Websocket.TLSPinnedCerts) 982 } 983 984 func TestNkeyUsersDefaultPermissionsConfig(t *testing.T) { 985 confFileName := createConfFile(t, []byte(` 986 authorization { 987 default_permissions = { 988 publish = "foo" 989 } 990 users = [ 991 { user: "user", password: "pwd"} 992 { user: "other", password: "pwd", 993 permissions = { 994 subscribe = "bar" 995 } 996 } 997 { nkey: "UDKTV7HZVYJFJN64LLMYQBUR6MTNNYCDC3LAZH4VHURW3GZLL3FULBXV" } 998 { nkey: "UA3C5TBZYK5GJQJRWPMU6NFY5JNAEVQB2V2TUZFZDHFJFUYVKTTUOFKZ", 999 permissions = { 1000 subscribe = "bar" 1001 } 1002 } 1003 ] 1004 } 1005 accounts { 1006 A { 1007 default_permissions = { 1008 publish = "foo" 1009 } 1010 users = [ 1011 { user: "accuser", password: "pwd"} 1012 { user: "accother", password: "pwd", 1013 permissions = { 1014 subscribe = "bar" 1015 } 1016 } 1017 { nkey: "UC4YEYJHYKTU4LHROX7UEKEIO5RP5OUWDYXELHWXZOQHZYXHUD44LCRS" } 1018 { nkey: "UDLSDF4UY3YW7JJQCYE6T2D4KFDCH6RGF3R65KHK247G3POJPI27VMQ3", 1019 permissions = { 1020 subscribe = "bar" 1021 } 1022 } 1023 ] 1024 } 1025 } 1026 `)) 1027 checkPerms := func(permsDef *Permissions, permsNonDef *Permissions) { 1028 if permsDef.Publish.Allow[0] != "foo" { 1029 t.Fatal("Publish allow foo missing") 1030 } else if permsDef.Subscribe != nil { 1031 t.Fatal("Has unexpected Subscribe permission") 1032 } else if permsNonDef.Subscribe.Allow[0] != "bar" { 1033 t.Fatal("Subscribe allow bar missing") 1034 } else if permsNonDef.Publish != nil { 1035 t.Fatal("Has unexpected Publish permission") 1036 } 1037 } 1038 opts, err := ProcessConfigFile(confFileName) 1039 if err != nil { 1040 t.Fatalf("Received an error reading config file: %v", err) 1041 } 1042 1043 findUsers := func(u1, u2 string) (found []*User) { 1044 find := []string{u1, u2} 1045 for _, f := range find { 1046 for _, u := range opts.Users { 1047 if u.Username == f { 1048 found = append(found, u) 1049 break 1050 } 1051 } 1052 } 1053 return 1054 } 1055 1056 findNkeyUsers := func(nk1, nk2 string) (found []*NkeyUser) { 1057 find := []string{nk1, nk2} 1058 for _, f := range find { 1059 for _, u := range opts.Nkeys { 1060 if strings.HasPrefix(u.Nkey, f) { 1061 found = append(found, u) 1062 break 1063 } 1064 } 1065 } 1066 return 1067 } 1068 1069 if lu := len(opts.Users); lu != 4 { 1070 t.Fatalf("Expected 4 nkey users, got %d", lu) 1071 } 1072 foundU := findUsers("user", "other") 1073 checkPerms(foundU[0].Permissions, foundU[1].Permissions) 1074 foundU = findUsers("accuser", "accother") 1075 checkPerms(foundU[0].Permissions, foundU[1].Permissions) 1076 1077 if lu := len(opts.Nkeys); lu != 4 { 1078 t.Fatalf("Expected 4 nkey users, got %d", lu) 1079 } 1080 foundNk := findNkeyUsers("UDK", "UA3") 1081 checkPerms(foundNk[0].Permissions, foundNk[1].Permissions) 1082 foundNk = findNkeyUsers("UC4", "UDL") 1083 checkPerms(foundNk[0].Permissions, foundNk[1].Permissions) 1084 } 1085 1086 func TestNkeyUsersWithPermsConfig(t *testing.T) { 1087 confFileName := createConfFile(t, []byte(` 1088 authorization { 1089 users = [ 1090 {nkey: "UDKTV7HZVYJFJN64LLMYQBUR6MTNNYCDC3LAZH4VHURW3GZLL3FULBXV", 1091 permissions = { 1092 publish = "$SYS.>" 1093 subscribe = { deny = ["foo", "bar", "baz"] } 1094 } 1095 } 1096 ] 1097 }`)) 1098 opts, err := ProcessConfigFile(confFileName) 1099 if err != nil { 1100 t.Fatalf("Received an error reading config file: %v", err) 1101 } 1102 lu := len(opts.Nkeys) 1103 if lu != 1 { 1104 t.Fatalf("Expected 1 nkey user, got %d", lu) 1105 } 1106 nk := opts.Nkeys[0] 1107 if nk.Permissions == nil { 1108 t.Fatal("Expected to have permissions") 1109 } 1110 if nk.Permissions.Publish == nil { 1111 t.Fatal("Expected to have publish permissions") 1112 } 1113 if nk.Permissions.Publish.Allow[0] != "$SYS.>" { 1114 t.Fatalf("Expected publish to allow \"$SYS.>\", but got %v", nk.Permissions.Publish.Allow[0]) 1115 } 1116 if nk.Permissions.Subscribe == nil { 1117 t.Fatal("Expected to have subscribe permissions") 1118 } 1119 if nk.Permissions.Subscribe.Allow != nil { 1120 t.Fatal("Expected to have no subscribe allow permissions") 1121 } 1122 deny := nk.Permissions.Subscribe.Deny 1123 if deny == nil || len(deny) != 3 || 1124 deny[0] != "foo" || deny[1] != "bar" || deny[2] != "baz" { 1125 t.Fatalf("Expected to have subscribe deny permissions, got %v", deny) 1126 } 1127 } 1128 1129 func TestBadNkeyConfig(t *testing.T) { 1130 confFileName := "nkeys_bad.conf" 1131 content := ` 1132 authorization { 1133 users = [ {nkey: "Ufoo"}] 1134 }` 1135 if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil { 1136 t.Fatalf("Error writing config file: %v", err) 1137 } 1138 defer removeFile(t, confFileName) 1139 if _, err := ProcessConfigFile(confFileName); err == nil { 1140 t.Fatalf("Expected an error from nkey entry with password") 1141 } 1142 } 1143 1144 func TestNkeyWithPassConfig(t *testing.T) { 1145 confFileName := "nkeys_pass.conf" 1146 content := ` 1147 authorization { 1148 users = [ 1149 {nkey: "UDKTV7HZVYJFJN64LLMYQBUR6MTNNYCDC3LAZH4VHURW3GZLL3FULBXV", pass: "foo"} 1150 ] 1151 }` 1152 if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil { 1153 t.Fatalf("Error writing config file: %v", err) 1154 } 1155 defer removeFile(t, confFileName) 1156 if _, err := ProcessConfigFile(confFileName); err == nil { 1157 t.Fatalf("Expected an error from bad nkey entry") 1158 } 1159 } 1160 1161 func TestTokenWithUserPass(t *testing.T) { 1162 confFileName := "test.conf" 1163 content := ` 1164 authorization={ 1165 user: user 1166 pass: password 1167 token: $2a$11$whatever 1168 }` 1169 if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil { 1170 t.Fatalf("Error writing config file: %v", err) 1171 } 1172 defer removeFile(t, confFileName) 1173 _, err := ProcessConfigFile(confFileName) 1174 if err == nil { 1175 t.Fatal("Expected error, got none") 1176 } 1177 if !strings.Contains(err.Error(), "token") { 1178 t.Fatalf("Expected error related to token, got %v", err) 1179 } 1180 } 1181 1182 func TestTokenWithUsers(t *testing.T) { 1183 confFileName := "test.conf" 1184 content := ` 1185 authorization={ 1186 token: $2a$11$whatever 1187 users: [ 1188 {user: test, password: test} 1189 ] 1190 }` 1191 if err := os.WriteFile(confFileName, []byte(content), 0666); err != nil { 1192 t.Fatalf("Error writing config file: %v", err) 1193 } 1194 defer removeFile(t, confFileName) 1195 _, err := ProcessConfigFile(confFileName) 1196 if err == nil { 1197 t.Fatal("Expected error, got none") 1198 } 1199 if !strings.Contains(err.Error(), "token") { 1200 t.Fatalf("Expected error related to token, got %v", err) 1201 } 1202 } 1203 1204 func TestParseWriteDeadline(t *testing.T) { 1205 confFile := createConfFile(t, []byte("write_deadline: \"1x\"")) 1206 _, err := ProcessConfigFile(confFile) 1207 if err == nil { 1208 t.Fatal("Expected error, got none") 1209 } 1210 if !strings.Contains(err.Error(), "parsing") { 1211 t.Fatalf("Expected error related to parsing, got %v", err) 1212 } 1213 confFile = createConfFile(t, []byte("write_deadline: \"1s\"")) 1214 opts, err := ProcessConfigFile(confFile) 1215 if err != nil { 1216 t.Fatalf("Unexpected error: %v", err) 1217 } 1218 if opts.WriteDeadline != time.Second { 1219 t.Fatalf("Expected write_deadline to be 1s, got %v", opts.WriteDeadline) 1220 } 1221 oldStdout := os.Stdout 1222 _, w, _ := os.Pipe() 1223 defer func() { 1224 w.Close() 1225 os.Stdout = oldStdout 1226 }() 1227 os.Stdout = w 1228 confFile = createConfFile(t, []byte("write_deadline: 2")) 1229 opts, err = ProcessConfigFile(confFile) 1230 if err != nil { 1231 t.Fatalf("Unexpected error: %v", err) 1232 } 1233 if opts.WriteDeadline != 2*time.Second { 1234 t.Fatalf("Expected write_deadline to be 2s, got %v", opts.WriteDeadline) 1235 } 1236 } 1237 1238 func TestOptionsClone(t *testing.T) { 1239 opts := &Options{ 1240 ConfigFile: "./configs/test.conf", 1241 Host: "127.0.0.1", 1242 Port: 2222, 1243 Username: "derek", 1244 Password: "porkchop", 1245 AuthTimeout: 1.0, 1246 Debug: true, 1247 Trace: true, 1248 Logtime: false, 1249 HTTPPort: DEFAULT_HTTP_PORT, 1250 HTTPBasePath: DEFAULT_HTTP_BASE_PATH, 1251 PidFile: "/tmp/nats-server/nats-server.pid", 1252 ProfPort: 6789, 1253 Syslog: true, 1254 RemoteSyslog: "udp://foo.com:33", 1255 MaxControlLine: 2048, 1256 MaxPayload: 65536, 1257 MaxConn: 100, 1258 PingInterval: 60 * time.Second, 1259 MaxPingsOut: 3, 1260 Cluster: ClusterOpts{ 1261 NoAdvertise: true, 1262 ConnectRetries: 2, 1263 }, 1264 Gateway: GatewayOpts{ 1265 Name: "A", 1266 Gateways: []*RemoteGatewayOpts{ 1267 {Name: "B", URLs: []*url.URL{{Scheme: "nats", Host: "host:5222"}}}, 1268 {Name: "C"}, 1269 }, 1270 }, 1271 WriteDeadline: 3 * time.Second, 1272 Routes: []*url.URL{{}}, 1273 Users: []*User{{Username: "foo", Password: "bar"}}, 1274 } 1275 1276 clone := opts.Clone() 1277 1278 if !reflect.DeepEqual(opts, clone) { 1279 t.Fatalf("Cloned Options are incorrect.\nexpected: %+v\ngot: %+v", 1280 clone, opts) 1281 } 1282 1283 clone.Users[0].Password = "baz" 1284 if reflect.DeepEqual(opts, clone) { 1285 t.Fatal("Expected Options to be different") 1286 } 1287 1288 opts.Gateway.Gateways[0].URLs[0] = nil 1289 if reflect.DeepEqual(opts.Gateway.Gateways[0], clone.Gateway.Gateways[0]) { 1290 t.Fatal("Expected Options to be different") 1291 } 1292 if clone.Gateway.Gateways[0].URLs[0].Host != "host:5222" { 1293 t.Fatalf("Unexpected URL: %v", clone.Gateway.Gateways[0].URLs[0]) 1294 } 1295 } 1296 1297 func TestOptionsCloneNilLists(t *testing.T) { 1298 opts := &Options{} 1299 1300 clone := opts.Clone() 1301 1302 if clone.Routes != nil { 1303 t.Fatalf("Expected Routes to be nil, got: %v", clone.Routes) 1304 } 1305 if clone.Users != nil { 1306 t.Fatalf("Expected Users to be nil, got: %v", clone.Users) 1307 } 1308 } 1309 1310 func TestOptionsCloneNil(t *testing.T) { 1311 opts := (*Options)(nil) 1312 clone := opts.Clone() 1313 if clone != nil { 1314 t.Fatalf("Expected nil, got: %+v", clone) 1315 } 1316 } 1317 1318 func TestEmptyConfig(t *testing.T) { 1319 opts, err := ProcessConfigFile("") 1320 1321 if err != nil { 1322 t.Fatalf("Expected no error from empty config, got: %+v", err) 1323 } 1324 1325 if opts.ConfigFile != "" { 1326 t.Fatalf("Expected empty config, got: %+v", opts) 1327 } 1328 } 1329 1330 func TestMalformedListenAddress(t *testing.T) { 1331 opts, err := ProcessConfigFile("./configs/malformed_listen_address.conf") 1332 if err == nil { 1333 t.Fatalf("Expected an error reading config file: got %+v", opts) 1334 } 1335 } 1336 1337 func TestMalformedClusterAddress(t *testing.T) { 1338 opts, err := ProcessConfigFile("./configs/malformed_cluster_address.conf") 1339 if err == nil { 1340 t.Fatalf("Expected an error reading config file: got %+v", opts) 1341 } 1342 } 1343 1344 func TestPanic(t *testing.T) { 1345 conf := createConfFile(t, []byte(`port: "this_string_trips_a_panic"`)) 1346 opts, err := ProcessConfigFile(conf) 1347 if err == nil { 1348 t.Fatalf("Expected an error reading config file: got %+v", opts) 1349 } else { 1350 if !strings.Contains(err.Error(), ":1:0: interface conversion:") { 1351 t.Fatalf("This was supposed to trip a panic on interface conversion right at the beginning") 1352 } 1353 } 1354 } 1355 1356 func TestPingIntervalOld(t *testing.T) { 1357 conf := createConfFile(t, []byte(`ping_interval: 5`)) 1358 opts := &Options{} 1359 err := opts.ProcessConfigFile(conf) 1360 if err == nil { 1361 t.Fatalf("expected an error") 1362 } 1363 errTyped, ok := err.(*processConfigErr) 1364 if !ok { 1365 t.Fatalf("expected an error of type processConfigErr") 1366 } 1367 if len(errTyped.warnings) != 1 { 1368 t.Fatalf("expected processConfigErr to have one warning") 1369 } 1370 if len(errTyped.errors) != 0 { 1371 t.Fatalf("expected processConfigErr to have no error") 1372 } 1373 if opts.PingInterval != 5*time.Second { 1374 t.Fatalf("expected ping interval to be 5 seconds") 1375 } 1376 } 1377 1378 func TestPingIntervalNew(t *testing.T) { 1379 conf := createConfFile(t, []byte(`ping_interval: "5m"`)) 1380 opts := &Options{} 1381 if err := opts.ProcessConfigFile(conf); err != nil { 1382 t.Fatalf("expected no error") 1383 } 1384 if opts.PingInterval != 5*time.Minute { 1385 t.Fatalf("expected ping interval to be 5 minutes") 1386 } 1387 } 1388 1389 func TestOptionsProcessConfigFile(t *testing.T) { 1390 // Create options with default values of Debug and Trace 1391 // that are the opposite of what is in the config file. 1392 // Set another option that is not present in the config file. 1393 logFileName := "test.log" 1394 opts := &Options{ 1395 Debug: true, 1396 Trace: false, 1397 LogFile: logFileName, 1398 } 1399 configFileName := "./configs/test.conf" 1400 if err := opts.ProcessConfigFile(configFileName); err != nil { 1401 t.Fatalf("Error processing config file: %v", err) 1402 } 1403 // Verify that values are as expected 1404 if opts.ConfigFile != configFileName { 1405 t.Fatalf("Expected ConfigFile to be set to %q, got %v", configFileName, opts.ConfigFile) 1406 } 1407 if opts.Debug { 1408 t.Fatal("Debug option should have been set to false from config file") 1409 } 1410 if !opts.Trace { 1411 t.Fatal("Trace option should have been set to true from config file") 1412 } 1413 if opts.LogFile != logFileName { 1414 t.Fatalf("Expected LogFile to be %q, got %q", logFileName, opts.LogFile) 1415 } 1416 } 1417 1418 func TestConfigureOptions(t *testing.T) { 1419 // Options.Configure() will snapshot the flags. This is used by the reload code. 1420 // We need to set it back to nil otherwise it will impact reload tests. 1421 defer func() { FlagSnapshot = nil }() 1422 1423 ch := make(chan bool, 1) 1424 checkPrintInvoked := func() { 1425 ch <- true 1426 } 1427 usage := func() { panic("should not get there") } 1428 var fs *flag.FlagSet 1429 type testPrint struct { 1430 args []string 1431 version, help, tlsHelp func() 1432 } 1433 testFuncs := []testPrint{ 1434 {[]string{"-v"}, checkPrintInvoked, usage, PrintTLSHelpAndDie}, 1435 {[]string{"version"}, checkPrintInvoked, usage, PrintTLSHelpAndDie}, 1436 {[]string{"-h"}, PrintServerAndExit, checkPrintInvoked, PrintTLSHelpAndDie}, 1437 {[]string{"help"}, PrintServerAndExit, checkPrintInvoked, PrintTLSHelpAndDie}, 1438 {[]string{"-help_tls"}, PrintServerAndExit, usage, checkPrintInvoked}, 1439 } 1440 for _, tf := range testFuncs { 1441 fs = flag.NewFlagSet("test", flag.ContinueOnError) 1442 opts, err := ConfigureOptions(fs, tf.args, tf.version, tf.help, tf.tlsHelp) 1443 if err != nil { 1444 t.Fatalf("Error on configure: %v", err) 1445 } 1446 if opts != nil { 1447 t.Fatalf("Expected options to be nil, got %v", opts) 1448 } 1449 select { 1450 case <-ch: 1451 case <-time.After(time.Second): 1452 t.Fatalf("Should have invoked print function for args=%v", tf.args) 1453 } 1454 } 1455 1456 // Helper function that expect parsing with given args to not produce an error. 1457 mustNotFail := func(args []string) *Options { 1458 fs := flag.NewFlagSet("test", flag.ContinueOnError) 1459 opts, err := ConfigureOptions(fs, args, PrintServerAndExit, fs.Usage, PrintTLSHelpAndDie) 1460 if err != nil { 1461 stackFatalf(t, "Error on configure: %v", err) 1462 } 1463 return opts 1464 } 1465 1466 // Helper function that expect configuration to fail. 1467 expectToFail := func(args []string, errContent ...string) { 1468 fs := flag.NewFlagSet("test", flag.ContinueOnError) 1469 // Silence the flagSet so that on failure nothing is printed. 1470 // (flagSet would print error message about unknown flags, etc..) 1471 silenceOuput := &bytes.Buffer{} 1472 fs.SetOutput(silenceOuput) 1473 opts, err := ConfigureOptions(fs, args, PrintServerAndExit, fs.Usage, PrintTLSHelpAndDie) 1474 if opts != nil || err == nil { 1475 stackFatalf(t, "Expected no option and an error, got opts=%v and err=%v", opts, err) 1476 } 1477 for _, testErr := range errContent { 1478 if strings.Contains(err.Error(), testErr) { 1479 // We got the error we wanted. 1480 return 1481 } 1482 } 1483 stackFatalf(t, "Expected errors containing any of those %v, got %v", errContent, err) 1484 } 1485 1486 // Basic test with port number 1487 opts := mustNotFail([]string{"-p", "1234"}) 1488 if opts.Port != 1234 { 1489 t.Fatalf("Expected port to be 1234, got %v", opts.Port) 1490 } 1491 1492 // Should fail because of unknown parameter 1493 expectToFail([]string{"foo"}, "command") 1494 1495 // Should fail because unknown flag 1496 expectToFail([]string{"-xxx", "foo"}, "flag") 1497 1498 // Should fail because of config file missing 1499 expectToFail([]string{"-c", "xxx.cfg"}, "file") 1500 1501 // Should fail because of too many args for signal command 1502 expectToFail([]string{"-sl", "quit=pid=foo"}, "signal") 1503 1504 // Should fail because of invalid pid 1505 // On windows, if not running with admin privileges, you would get access denied. 1506 expectToFail([]string{"-sl", "quit=pid"}, "pid", "denied") 1507 1508 // The config file set Trace to true. 1509 opts = mustNotFail([]string{"-c", "./configs/test.conf"}) 1510 if !opts.Trace { 1511 t.Fatal("Trace should have been set to true") 1512 } 1513 1514 // The config file set Trace to true, but was overridden by param -V=false 1515 opts = mustNotFail([]string{"-c", "./configs/test.conf", "-V=false"}) 1516 if opts.Trace { 1517 t.Fatal("Trace should have been set to false") 1518 } 1519 1520 // The config file set Trace to true, but was overridden by param -DV=false 1521 opts = mustNotFail([]string{"-c", "./configs/test.conf", "-DV=false"}) 1522 if opts.Debug || opts.Trace { 1523 t.Fatal("Debug and Trace should have been set to false") 1524 } 1525 1526 // The config file set Trace to true, but was overridden by param -DV 1527 opts = mustNotFail([]string{"-c", "./configs/test.conf", "-DV"}) 1528 if !opts.Debug || !opts.Trace { 1529 t.Fatal("Debug and Trace should have been set to true") 1530 } 1531 1532 // This should fail since -cluster is missing 1533 expectedURL, _ := url.Parse("nats://127.0.0.1:6223") 1534 expectToFail([]string{"-routes", expectedURL.String()}, "solicited routes") 1535 1536 // Ensure that we can set cluster and routes from command line 1537 opts = mustNotFail([]string{"-cluster", "nats://127.0.0.1:6222", "-routes", expectedURL.String()}) 1538 if opts.Cluster.ListenStr != "nats://127.0.0.1:6222" { 1539 t.Fatalf("Unexpected Cluster.ListenStr=%q", opts.Cluster.ListenStr) 1540 } 1541 if opts.RoutesStr != "nats://127.0.0.1:6223" || len(opts.Routes) != 1 || opts.Routes[0].String() != expectedURL.String() { 1542 t.Fatalf("Unexpected RoutesStr: %q and Routes: %v", opts.RoutesStr, opts.Routes) 1543 } 1544 1545 // Use a config with cluster configuration and explicit route defined. 1546 // Override with empty routes string. 1547 opts = mustNotFail([]string{"-c", "./configs/srv_a.conf", "-routes", ""}) 1548 if opts.RoutesStr != "" || len(opts.Routes) != 0 { 1549 t.Fatalf("Unexpected RoutesStr: %q and Routes: %v", opts.RoutesStr, opts.Routes) 1550 } 1551 1552 // Use a config with cluster configuration and override cluster listen string 1553 expectedURL, _ = url.Parse("nats-route://ruser:top_secret@127.0.0.1:7246") 1554 opts = mustNotFail([]string{"-c", "./configs/srv_a.conf", "-cluster", "nats://ivan:pwd@127.0.0.1:6222"}) 1555 if opts.Cluster.Username != "ivan" || opts.Cluster.Password != "pwd" || opts.Cluster.Port != 6222 || 1556 len(opts.Routes) != 1 || opts.Routes[0].String() != expectedURL.String() { 1557 t.Fatalf("Unexpected Cluster and/or Routes: %#v - %v", opts.Cluster, opts.Routes) 1558 } 1559 1560 // Disable clustering from command line 1561 opts = mustNotFail([]string{"-c", "./configs/srv_a.conf", "-cluster", ""}) 1562 if opts.Cluster.Port != 0 { 1563 t.Fatalf("Unexpected Cluster: %v", opts.Cluster) 1564 } 1565 1566 // Various erros due to malformed cluster listen string. 1567 // (adding -routes to have more than 1 set flag to check 1568 // that Visit() stops when an error is found). 1569 expectToFail([]string{"-cluster", ":", "-routes", ""}, "protocol") 1570 expectToFail([]string{"-cluster", "nats://127.0.0.1", "-routes", ""}, "port") 1571 expectToFail([]string{"-cluster", "nats://127.0.0.1:xxx", "-routes", ""}, "invalid port") 1572 expectToFail([]string{"-cluster", "nats://ivan:127.0.0.1:6222", "-routes", ""}, "colons") 1573 expectToFail([]string{"-cluster", "nats://ivan@127.0.0.1:6222", "-routes", ""}, "password") 1574 1575 // Override config file's TLS configuration from command line, and completely disable TLS 1576 opts = mustNotFail([]string{"-c", "./configs/tls.conf", "-tls=false"}) 1577 if opts.TLSConfig != nil || opts.TLS { 1578 t.Fatal("Expected TLS to be disabled") 1579 } 1580 // Override config file's TLS configuration from command line, and force TLS verification. 1581 // However, since TLS config has to be regenerated, user need to provide -tlscert and -tlskey too. 1582 // So this should fail. 1583 expectToFail([]string{"-c", "./configs/tls.conf", "-tlsverify"}, "valid") 1584 1585 // Now same than above, but with all valid params. 1586 opts = mustNotFail([]string{"-c", "./configs/tls.conf", "-tlsverify", "-tlscert", "./configs/certs/server.pem", "-tlskey", "./configs/certs/key.pem"}) 1587 if opts.TLSConfig == nil || !opts.TLSVerify { 1588 t.Fatal("Expected TLS to be configured and force verification") 1589 } 1590 1591 // Configure TLS, but some TLS params missing 1592 expectToFail([]string{"-tls"}, "valid") 1593 expectToFail([]string{"-tls", "-tlscert", "./configs/certs/server.pem"}, "valid") 1594 // One of the file does not exist 1595 expectToFail([]string{"-tls", "-tlscert", "./configs/certs/server.pem", "-tlskey", "./configs/certs/notfound.pem"}, "file") 1596 1597 // Configure TLS and check that this results in a TLSConfig option. 1598 opts = mustNotFail([]string{"-tls", "-tlscert", "./configs/certs/server.pem", "-tlskey", "./configs/certs/key.pem"}) 1599 if opts.TLSConfig == nil || !opts.TLS { 1600 t.Fatal("Expected TLSConfig to be set") 1601 } 1602 // Check that we use default TLS ciphers 1603 if !reflect.DeepEqual(opts.TLSConfig.CipherSuites, defaultCipherSuites()) { 1604 t.Fatalf("Default ciphers not set, expected %v, got %v", defaultCipherSuites(), opts.TLSConfig.CipherSuites) 1605 } 1606 } 1607 1608 func TestClusterPermissionsConfig(t *testing.T) { 1609 template := ` 1610 cluster { 1611 port: 1234 1612 %s 1613 authorization { 1614 user: ivan 1615 password: pwd 1616 permissions { 1617 import { 1618 allow: "foo" 1619 } 1620 export { 1621 allow: "bar" 1622 } 1623 } 1624 } 1625 } 1626 ` 1627 conf := createConfFile(t, []byte(fmt.Sprintf(template, ""))) 1628 opts, err := ProcessConfigFile(conf) 1629 if err != nil { 1630 if cerr, ok := err.(*processConfigErr); ok && len(cerr.Errors()) > 0 { 1631 t.Fatalf("Error processing config file: %v", err) 1632 } 1633 } 1634 if opts.Cluster.Permissions == nil { 1635 t.Fatal("Expected cluster permissions to be set") 1636 } 1637 if opts.Cluster.Permissions.Import == nil { 1638 t.Fatal("Expected cluster import permissions to be set") 1639 } 1640 if len(opts.Cluster.Permissions.Import.Allow) != 1 || opts.Cluster.Permissions.Import.Allow[0] != "foo" { 1641 t.Fatalf("Expected cluster import permissions to have %q, got %v", "foo", opts.Cluster.Permissions.Import.Allow) 1642 } 1643 if opts.Cluster.Permissions.Export == nil { 1644 t.Fatal("Expected cluster export permissions to be set") 1645 } 1646 if len(opts.Cluster.Permissions.Export.Allow) != 1 || opts.Cluster.Permissions.Export.Allow[0] != "bar" { 1647 t.Fatalf("Expected cluster export permissions to have %q, got %v", "bar", opts.Cluster.Permissions.Export.Allow) 1648 } 1649 1650 // Now add permissions in top level cluster and check 1651 // that this is the one that is being used. 1652 conf = createConfFile(t, []byte(fmt.Sprintf(template, ` 1653 permissions { 1654 import { 1655 allow: "baz" 1656 } 1657 export { 1658 allow: "bat" 1659 } 1660 } 1661 `))) 1662 opts, err = ProcessConfigFile(conf) 1663 if err != nil { 1664 t.Fatalf("Error processing config file: %v", err) 1665 } 1666 if opts.Cluster.Permissions == nil { 1667 t.Fatal("Expected cluster permissions to be set") 1668 } 1669 if opts.Cluster.Permissions.Import == nil { 1670 t.Fatal("Expected cluster import permissions to be set") 1671 } 1672 if len(opts.Cluster.Permissions.Import.Allow) != 1 || opts.Cluster.Permissions.Import.Allow[0] != "baz" { 1673 t.Fatalf("Expected cluster import permissions to have %q, got %v", "baz", opts.Cluster.Permissions.Import.Allow) 1674 } 1675 if opts.Cluster.Permissions.Export == nil { 1676 t.Fatal("Expected cluster export permissions to be set") 1677 } 1678 if len(opts.Cluster.Permissions.Export.Allow) != 1 || opts.Cluster.Permissions.Export.Allow[0] != "bat" { 1679 t.Fatalf("Expected cluster export permissions to have %q, got %v", "bat", opts.Cluster.Permissions.Export.Allow) 1680 } 1681 1682 // Tests with invalid permissions 1683 invalidPerms := []string{ 1684 `permissions: foo`, 1685 `permissions { 1686 unknown_field: "foo" 1687 }`, 1688 `permissions { 1689 import: [1, 2, 3] 1690 }`, 1691 `permissions { 1692 import { 1693 unknown_field: "foo" 1694 } 1695 }`, 1696 `permissions { 1697 import { 1698 allow { 1699 x: y 1700 } 1701 } 1702 }`, 1703 `permissions { 1704 import { 1705 deny { 1706 x: y 1707 } 1708 } 1709 }`, 1710 `permissions { 1711 export: [1, 2, 3] 1712 }`, 1713 `permissions { 1714 export { 1715 unknown_field: "foo" 1716 } 1717 }`, 1718 `permissions { 1719 export { 1720 allow { 1721 x: y 1722 } 1723 } 1724 }`, 1725 `permissions { 1726 export { 1727 deny { 1728 x: y 1729 } 1730 } 1731 }`, 1732 } 1733 for _, perms := range invalidPerms { 1734 conf = createConfFile(t, []byte(fmt.Sprintf(` 1735 cluster { 1736 port: 1234 1737 %s 1738 } 1739 `, perms))) 1740 _, err := ProcessConfigFile(conf) 1741 if err == nil { 1742 t.Fatalf("Expected failure for permissions %s", perms) 1743 } 1744 } 1745 1746 for _, perms := range invalidPerms { 1747 conf = createConfFile(t, []byte(fmt.Sprintf(` 1748 cluster { 1749 port: 1234 1750 authorization { 1751 user: ivan 1752 password: pwd 1753 %s 1754 } 1755 } 1756 `, perms))) 1757 _, err := ProcessConfigFile(conf) 1758 if err == nil { 1759 t.Fatalf("Expected failure for permissions %s", perms) 1760 } 1761 } 1762 } 1763 1764 func TestParseServiceLatency(t *testing.T) { 1765 cases := []struct { 1766 name string 1767 conf string 1768 want *serviceLatency 1769 wantErr bool 1770 }{ 1771 { 1772 name: "block with percent sample default value", 1773 conf: `system_account = nats.io 1774 accounts { 1775 nats.io { 1776 exports [{ 1777 service: nats.add 1778 latency: { 1779 sampling: 100% 1780 subject: latency.tracking.add 1781 } 1782 }] 1783 } 1784 }`, 1785 want: &serviceLatency{ 1786 subject: "latency.tracking.add", 1787 sampling: 100, 1788 }, 1789 }, 1790 { 1791 name: "block with percent sample nondefault value", 1792 conf: `system_account = nats.io 1793 accounts { 1794 nats.io { 1795 exports [{ 1796 service: nats.add 1797 latency: { 1798 sampling: 33% 1799 subject: latency.tracking.add 1800 } 1801 }] 1802 } 1803 }`, 1804 want: &serviceLatency{ 1805 subject: "latency.tracking.add", 1806 sampling: 33, 1807 }, 1808 }, 1809 { 1810 name: "block with number sample nondefault value", 1811 conf: `system_account = nats.io 1812 accounts { 1813 nats.io { 1814 exports [{ 1815 service: nats.add 1816 latency: { 1817 sampling: 87 1818 subject: latency.tracking.add 1819 } 1820 }] 1821 } 1822 }`, 1823 want: &serviceLatency{ 1824 subject: "latency.tracking.add", 1825 sampling: 87, 1826 }, 1827 }, 1828 { 1829 name: "field with subject", 1830 conf: `system_account = nats.io 1831 accounts { 1832 nats.io { 1833 exports [{ 1834 service: nats.add 1835 latency: latency.tracking.add 1836 }] 1837 } 1838 }`, 1839 want: &serviceLatency{ 1840 subject: "latency.tracking.add", 1841 sampling: 100, 1842 }, 1843 }, 1844 { 1845 name: "block with missing subject", 1846 conf: `system_account = nats.io 1847 accounts { 1848 nats.io { 1849 exports [{ 1850 service: nats.add 1851 latency: { 1852 sampling: 87 1853 } 1854 }] 1855 } 1856 }`, 1857 wantErr: true, 1858 }, 1859 } 1860 1861 for _, c := range cases { 1862 t.Run(c.name, func(t *testing.T) { 1863 f := createConfFile(t, []byte(c.conf)) 1864 opts, err := ProcessConfigFile(f) 1865 switch { 1866 case c.wantErr && err == nil: 1867 t.Fatalf("Expected ProcessConfigFile to fail, but didn't") 1868 case c.wantErr && err != nil: 1869 // We wanted an error and got one, test passed. 1870 return 1871 case !c.wantErr && err == nil: 1872 // We didn't want an error and didn't get one, keep going. 1873 break 1874 case !c.wantErr && err != nil: 1875 t.Fatalf("Failed to process config: %v", err) 1876 } 1877 1878 if len(opts.Accounts) != 1 { 1879 t.Fatalf("Expected accounts to have len %d, got %d", 1, len(opts.Accounts)) 1880 } 1881 if len(opts.Accounts[0].exports.services) != 1 { 1882 t.Fatalf("Expected export services to have len %d, got %d", 1, len(opts.Accounts[0].exports.services)) 1883 } 1884 s, ok := opts.Accounts[0].exports.services["nats.add"] 1885 if !ok { 1886 t.Fatalf("Expected export service nats.add, missing") 1887 } 1888 1889 if !reflect.DeepEqual(s.latency, c.want) { 1890 t.Fatalf("Expected latency to be %#v, got %#v", c.want, s.latency) 1891 } 1892 }) 1893 } 1894 } 1895 1896 func TestParseExport(t *testing.T) { 1897 conf := ` 1898 port: -1 1899 system_account: sys 1900 accounts { 1901 sys { 1902 exports [{ 1903 stream "$SYS.SERVER.ACCOUNT.*.CONNS" 1904 account_token_position 4 1905 }] 1906 } 1907 accE { 1908 exports [{ 1909 service foo.* 1910 account_token_position 2 1911 }] 1912 users [{ 1913 user ue 1914 password pwd 1915 }], 1916 } 1917 accI1 { 1918 imports [{ 1919 service { 1920 account accE 1921 subject foo.accI1 1922 } 1923 to foo 1924 },{ 1925 stream { 1926 account sys 1927 subject "$SYS.SERVER.ACCOUNT.accI1.CONNS" 1928 } 1929 }], 1930 users [{ 1931 user u1 1932 password pwd 1933 }], 1934 } 1935 accI2 { 1936 imports [{ 1937 service { 1938 account accE 1939 subject foo.accI2 1940 } 1941 to foo 1942 },{ 1943 stream { 1944 account sys 1945 subject "$SYS.SERVER.ACCOUNT.accI2.CONNS" 1946 } 1947 }], 1948 users [{ 1949 user u2 1950 password pwd 1951 }], 1952 } 1953 }` 1954 f := createConfFile(t, []byte(conf)) 1955 s, o := RunServerWithConfig(f) 1956 if s == nil { 1957 t.Fatal("Failed startup") 1958 } 1959 defer s.Shutdown() 1960 connect := func(user string) *nats.Conn { 1961 nc, err := nats.Connect(fmt.Sprintf("nats://%s:pwd@%s:%d", user, o.Host, o.Port)) 1962 require_NoError(t, err) 1963 return nc 1964 } 1965 nc1 := connect("u1") 1966 defer nc1.Close() 1967 nc2 := connect("u2") 1968 defer nc2.Close() 1969 1970 // Due to the fact that above CONNECT events are generated and sent from 1971 // a system go routine, it is possible that by the time we create the 1972 // subscriptions below, the interest would exist and messages be sent, 1973 // which was causing issues since wg.Done() was called too many times. 1974 // Add a little delay to minimize risk, but also use counter to decide 1975 // when to call wg.Done() to avoid panic due to negative number. 1976 time.Sleep(100 * time.Millisecond) 1977 1978 wg := sync.WaitGroup{} 1979 wg.Add(1) 1980 count := int32(0) 1981 // We expect a total of 6 messages 1982 expected := int32(6) 1983 subscribe := func(nc *nats.Conn, subj string) { 1984 t.Helper() 1985 _, err := nc.Subscribe(subj, func(msg *nats.Msg) { 1986 if msg.Reply != _EMPTY_ { 1987 msg.Respond(msg.Data) 1988 } 1989 if atomic.AddInt32(&count, 1) == expected { 1990 wg.Done() 1991 } 1992 }) 1993 require_NoError(t, err) 1994 nc.Flush() 1995 } 1996 //Subscribe to CONNS events 1997 subscribe(nc1, "$SYS.SERVER.ACCOUNT.accI1.CONNS") 1998 subscribe(nc2, "$SYS.SERVER.ACCOUNT.accI2.CONNS") 1999 // Trigger 2 CONNS event 2000 nc3 := connect("u1") 2001 nc3.Close() 2002 nc4 := connect("u2") 2003 nc4.Close() 2004 // test service 2005 ncE := connect("ue") 2006 defer ncE.Close() 2007 subscribe(ncE, "foo.*") 2008 request := func(nc *nats.Conn, msg string) { 2009 if m, err := nc.Request("foo", []byte(msg), time.Second); err != nil { 2010 t.Fatal("Failed request ", msg, err) 2011 } else if m == nil { 2012 t.Fatal("No response msg") 2013 } else if string(m.Data) != msg { 2014 t.Fatal("Wrong response msg", string(m.Data)) 2015 } 2016 } 2017 request(nc1, "1") 2018 request(nc2, "1") 2019 wg.Wait() 2020 } 2021 2022 func TestAccountUsersLoadedProperly(t *testing.T) { 2023 conf := createConfFile(t, []byte(` 2024 listen: "127.0.0.1:-1" 2025 authorization { 2026 users [ 2027 {user: ivan, password: bar} 2028 {nkey : UC6NLCN7AS34YOJVCYD4PJ3QB7QGLYG5B5IMBT25VW5K4TNUJODM7BOX} 2029 ] 2030 } 2031 accounts { 2032 synadia { 2033 users [ 2034 {user: derek, password: foo} 2035 {nkey : UBAAQWTW6CG2G6ANGNKB5U2B7HRWHSGMZEZX3AQSAJOQDAUGJD46LD2E} 2036 ] 2037 } 2038 } 2039 `)) 2040 check := func(t *testing.T) { 2041 t.Helper() 2042 s, _ := RunServerWithConfig(conf) 2043 defer s.Shutdown() 2044 opts := s.getOpts() 2045 if n := len(opts.Users); n != 2 { 2046 t.Fatalf("Should have 2 users, got %v", n) 2047 } 2048 if n := len(opts.Nkeys); n != 2 { 2049 t.Fatalf("Should have 2 nkeys, got %v", n) 2050 } 2051 } 2052 // Repeat test since issue was with ordering of processing 2053 // of authorization vs accounts that depends on range of a map (after actual parsing) 2054 for i := 0; i < 20; i++ { 2055 check(t) 2056 } 2057 } 2058 2059 func TestParsingGateways(t *testing.T) { 2060 content := ` 2061 gateway { 2062 name: "A" 2063 listen: "127.0.0.1:4444" 2064 host: "127.0.0.1" 2065 port: 4444 2066 reject_unknown_cluster: true 2067 authorization { 2068 user: "ivan" 2069 password: "pwd" 2070 timeout: 2.0 2071 } 2072 tls { 2073 cert_file: "./configs/certs/server.pem" 2074 key_file: "./configs/certs/key.pem" 2075 timeout: 3.0 2076 } 2077 advertise: "me:1" 2078 connect_retries: 10 2079 gateways: [ 2080 { 2081 name: "B" 2082 urls: ["nats://user1:pwd1@host2:5222", "nats://user1:pwd1@host3:6222"] 2083 } 2084 { 2085 name: "C" 2086 url: "nats://host4:7222" 2087 } 2088 ] 2089 } 2090 ` 2091 file := "server_config_gateways.conf" 2092 if err := os.WriteFile(file, []byte(content), 0600); err != nil { 2093 t.Fatalf("Error writing config file: %v", err) 2094 } 2095 defer removeFile(t, file) 2096 opts, err := ProcessConfigFile(file) 2097 if err != nil { 2098 t.Fatalf("Error processing file: %v", err) 2099 } 2100 2101 expected := &GatewayOpts{ 2102 Name: "A", 2103 Host: "127.0.0.1", 2104 Port: 4444, 2105 Username: "ivan", 2106 Password: "pwd", 2107 AuthTimeout: 2.0, 2108 Advertise: "me:1", 2109 ConnectRetries: 10, 2110 TLSTimeout: 3.0, 2111 RejectUnknown: true, 2112 } 2113 u1, _ := url.Parse("nats://user1:pwd1@host2:5222") 2114 u2, _ := url.Parse("nats://user1:pwd1@host3:6222") 2115 urls := []*url.URL{u1, u2} 2116 gw := &RemoteGatewayOpts{ 2117 Name: "B", 2118 URLs: urls, 2119 } 2120 expected.Gateways = append(expected.Gateways, gw) 2121 2122 u1, _ = url.Parse("nats://host4:7222") 2123 urls = []*url.URL{u1} 2124 gw = &RemoteGatewayOpts{ 2125 Name: "C", 2126 URLs: urls, 2127 } 2128 expected.Gateways = append(expected.Gateways, gw) 2129 2130 // Just make sure that TLSConfig is set.. we have aother test 2131 // to check proper generating TLSConfig from config file... 2132 if opts.Gateway.TLSConfig == nil { 2133 t.Fatalf("Expected TLSConfig, got none") 2134 } 2135 opts.Gateway.TLSConfig = nil 2136 opts.Gateway.tlsConfigOpts = nil 2137 if !reflect.DeepEqual(&opts.Gateway, expected) { 2138 t.Fatalf("Expected %v, got %v", expected, opts.Gateway) 2139 } 2140 } 2141 2142 func TestParsingGatewaysErrors(t *testing.T) { 2143 for _, test := range []struct { 2144 name string 2145 content string 2146 expectedErr string 2147 }{ 2148 { 2149 "bad_type", 2150 `gateway: "bad_type"`, 2151 "Expected gateway to be a map", 2152 }, 2153 { 2154 "bad_listen", 2155 `gateway { 2156 name: "A" 2157 port: -1 2158 listen: "bad::address" 2159 }`, 2160 "parse address", 2161 }, 2162 { 2163 "bad_auth", 2164 `gateway { 2165 name: "A" 2166 port: -1 2167 authorization { 2168 users { 2169 } 2170 } 2171 }`, 2172 "be an array", 2173 }, 2174 { 2175 "unknown_field", 2176 `gateway { 2177 name: "A" 2178 port: -1 2179 reject_unknown_cluster: true 2180 unknown_field: 1 2181 }`, 2182 "unknown field", 2183 }, 2184 { 2185 "users_not_supported", 2186 `gateway { 2187 name: "A" 2188 port: -1 2189 authorization { 2190 users [ 2191 {user: alice, password: foo} 2192 {user: bob, password: bar} 2193 ] 2194 } 2195 }`, 2196 "does not allow multiple users", 2197 }, 2198 { 2199 "tls_error", 2200 `gateway { 2201 name: "A" 2202 port: -1 2203 tls { 2204 cert_file: 123 2205 } 2206 }`, 2207 "to be filename", 2208 }, 2209 { 2210 "tls_gen_error_cert_file_not_found", 2211 `gateway { 2212 name: "A" 2213 port: -1 2214 tls { 2215 cert_file: "./configs/certs/missing.pem" 2216 key_file: "./configs/certs/server-key.pem" 2217 } 2218 }`, 2219 "certificate/key pair", 2220 }, 2221 { 2222 "tls_gen_error_key_file_not_found", 2223 `gateway { 2224 name: "A" 2225 port: -1 2226 tls { 2227 cert_file: "./configs/certs/server.pem" 2228 key_file: "./configs/certs/missing.pem" 2229 } 2230 }`, 2231 "certificate/key pair", 2232 }, 2233 { 2234 "tls_gen_error_key_file_missing", 2235 `gateway { 2236 name: "A" 2237 port: -1 2238 tls { 2239 cert_file: "./configs/certs/server.pem" 2240 } 2241 }`, 2242 `missing 'key_file' in TLS configuration`, 2243 }, 2244 { 2245 "tls_gen_error_cert_file_missing", 2246 `gateway { 2247 name: "A" 2248 port: -1 2249 tls { 2250 key_file: "./configs/certs/server-key.pem" 2251 } 2252 }`, 2253 `missing 'cert_file' in TLS configuration`, 2254 }, 2255 { 2256 "tls_gen_error_key_file_not_found", 2257 `gateway { 2258 name: "A" 2259 port: -1 2260 tls { 2261 cert_file: "./configs/certs/server.pem" 2262 key_file: "./configs/certs/missing.pem" 2263 } 2264 }`, 2265 "certificate/key pair", 2266 }, 2267 { 2268 "gateways_needs_to_be_an_array", 2269 `gateway { 2270 name: "A" 2271 gateways { 2272 name: "B" 2273 } 2274 }`, 2275 "Expected gateways field to be an array", 2276 }, 2277 { 2278 "gateways_entry_needs_to_be_a_map", 2279 `gateway { 2280 name: "A" 2281 gateways [ 2282 "g1", "g2" 2283 ] 2284 }`, 2285 "Expected gateway entry to be a map", 2286 }, 2287 { 2288 "bad_url", 2289 `gateway { 2290 name: "A" 2291 gateways [ 2292 { 2293 name: "B" 2294 url: "nats://wrong url" 2295 } 2296 ] 2297 }`, 2298 "error parsing gateway url", 2299 }, 2300 { 2301 "bad_urls", 2302 `gateway { 2303 name: "A" 2304 gateways [ 2305 { 2306 name: "B" 2307 urls: ["nats://wrong url", "nats://host:5222"] 2308 } 2309 ] 2310 }`, 2311 "error parsing gateway url", 2312 }, 2313 { 2314 "gateway_tls_error", 2315 `gateway { 2316 name: "A" 2317 port: -1 2318 gateways [ 2319 { 2320 name: "B" 2321 tls { 2322 cert_file: 123 2323 } 2324 } 2325 ] 2326 }`, 2327 "to be filename", 2328 }, 2329 { 2330 "gateway_unknown_field", 2331 `gateway { 2332 name: "A" 2333 port: -1 2334 gateways [ 2335 { 2336 name: "B" 2337 unknown_field: 1 2338 } 2339 ] 2340 }`, 2341 "unknown field", 2342 }, 2343 } { 2344 t.Run(test.name, func(t *testing.T) { 2345 file := fmt.Sprintf("server_config_gateways_%s.conf", test.name) 2346 if err := os.WriteFile(file, []byte(test.content), 0600); err != nil { 2347 t.Fatalf("Error writing config file: %v", err) 2348 } 2349 defer removeFile(t, file) 2350 _, err := ProcessConfigFile(file) 2351 if err == nil { 2352 t.Fatalf("Expected to fail, did not. Content:\n%s", test.content) 2353 } else if !strings.Contains(err.Error(), test.expectedErr) { 2354 t.Fatalf("Expected error containing %q, got %q, for content:\n%s", test.expectedErr, err, test.content) 2355 } 2356 }) 2357 } 2358 } 2359 2360 func TestParsingLeafNodesListener(t *testing.T) { 2361 content := ` 2362 leafnodes { 2363 listen: "127.0.0.1:3333" 2364 host: "127.0.0.1" 2365 port: 3333 2366 advertise: "me:22" 2367 authorization { 2368 user: "derek" 2369 password: "s3cr3t!" 2370 timeout: 2.2 2371 } 2372 tls { 2373 cert_file: "./configs/certs/server.pem" 2374 key_file: "./configs/certs/key.pem" 2375 timeout: 3.3 2376 } 2377 } 2378 ` 2379 conf := createConfFile(t, []byte(content)) 2380 opts, err := ProcessConfigFile(conf) 2381 if err != nil { 2382 t.Fatalf("Error processing file: %v", err) 2383 } 2384 2385 expected := &LeafNodeOpts{ 2386 Host: "127.0.0.1", 2387 Port: 3333, 2388 Username: "derek", 2389 Password: "s3cr3t!", 2390 AuthTimeout: 2.2, 2391 Advertise: "me:22", 2392 TLSTimeout: 3.3, 2393 } 2394 if opts.LeafNode.TLSConfig == nil { 2395 t.Fatalf("Expected TLSConfig, got none") 2396 } 2397 if opts.LeafNode.tlsConfigOpts == nil { 2398 t.Fatalf("Expected TLSConfig snapshot, got none") 2399 } 2400 opts.LeafNode.TLSConfig = nil 2401 opts.LeafNode.tlsConfigOpts = nil 2402 if !reflect.DeepEqual(&opts.LeafNode, expected) { 2403 t.Fatalf("Expected %v, got %v", expected, opts.LeafNode) 2404 } 2405 } 2406 2407 func TestParsingLeafNodeRemotes(t *testing.T) { 2408 t.Run("parse config file with relative path", func(t *testing.T) { 2409 content := ` 2410 leafnodes { 2411 remotes = [ 2412 { 2413 url: nats-leaf://127.0.0.1:2222 2414 account: foobar // Local Account to bind to.. 2415 credentials: "./my.creds" 2416 } 2417 ] 2418 } 2419 ` 2420 conf := createConfFile(t, []byte(content)) 2421 opts, err := ProcessConfigFile(conf) 2422 if err != nil { 2423 t.Fatalf("Error processing file: %v", err) 2424 } 2425 if len(opts.LeafNode.Remotes) != 1 { 2426 t.Fatalf("Expected 1 remote, got %d", len(opts.LeafNode.Remotes)) 2427 } 2428 expected := &RemoteLeafOpts{ 2429 LocalAccount: "foobar", 2430 Credentials: "./my.creds", 2431 } 2432 u, _ := url.Parse("nats-leaf://127.0.0.1:2222") 2433 expected.URLs = append(expected.URLs, u) 2434 if !reflect.DeepEqual(opts.LeafNode.Remotes[0], expected) { 2435 t.Fatalf("Expected %v, got %v", expected, opts.LeafNode.Remotes[0]) 2436 } 2437 }) 2438 2439 t.Run("parse config file with tilde path", func(t *testing.T) { 2440 if runtime.GOOS == "windows" { 2441 t.SkipNow() 2442 } 2443 2444 origHome := os.Getenv("HOME") 2445 defer os.Setenv("HOME", origHome) 2446 os.Setenv("HOME", "/home/foo") 2447 2448 content := ` 2449 leafnodes { 2450 remotes = [ 2451 { 2452 url: nats-leaf://127.0.0.1:2222 2453 account: foobar // Local Account to bind to.. 2454 credentials: "~/my.creds" 2455 } 2456 ] 2457 } 2458 ` 2459 conf := createConfFile(t, []byte(content)) 2460 opts, err := ProcessConfigFile(conf) 2461 if err != nil { 2462 t.Fatalf("Error processing file: %v", err) 2463 } 2464 expected := &RemoteLeafOpts{ 2465 LocalAccount: "foobar", 2466 Credentials: "/home/foo/my.creds", 2467 } 2468 u, _ := url.Parse("nats-leaf://127.0.0.1:2222") 2469 expected.URLs = append(expected.URLs, u) 2470 if !reflect.DeepEqual(opts.LeafNode.Remotes[0], expected) { 2471 t.Fatalf("Expected %v, got %v", expected, opts.LeafNode.Remotes[0]) 2472 } 2473 }) 2474 2475 t.Run("url ordering", func(t *testing.T) { 2476 // 16! possible permutations. 2477 orderedURLs := make([]string, 0, 16) 2478 for i := 0; i < cap(orderedURLs); i++ { 2479 orderedURLs = append(orderedURLs, fmt.Sprintf("nats-leaf://host%d:7422", i)) 2480 } 2481 confURLs, err := json.Marshal(orderedURLs) 2482 if err != nil { 2483 t.Fatal(err) 2484 } 2485 2486 content := ` 2487 port: -1 2488 leafnodes { 2489 remotes = [ 2490 { 2491 dont_randomize: true 2492 urls: %[1]s 2493 } 2494 { 2495 urls: %[1]s 2496 } 2497 ] 2498 } 2499 ` 2500 conf := createConfFile(t, []byte(fmt.Sprintf(content, confURLs))) 2501 2502 s, _ := RunServerWithConfig(conf) 2503 defer s.Shutdown() 2504 2505 s.mu.Lock() 2506 r1 := s.leafRemoteCfgs[0] 2507 r2 := s.leafRemoteCfgs[1] 2508 s.mu.Unlock() 2509 2510 r1.RLock() 2511 gotOrdered := r1.urls 2512 r1.RUnlock() 2513 if got, want := len(gotOrdered), len(orderedURLs); got != want { 2514 t.Fatalf("Unexpected rem0 len URLs, got %d, want %d", got, want) 2515 } 2516 2517 // These should be IN order. 2518 for i := range orderedURLs { 2519 if got, want := gotOrdered[i].String(), orderedURLs[i]; got != want { 2520 t.Fatalf("Unexpected ordered url, got %s, want %s", got, want) 2521 } 2522 } 2523 2524 r2.RLock() 2525 gotRandom := r2.urls 2526 r2.RUnlock() 2527 if got, want := len(gotRandom), len(orderedURLs); got != want { 2528 t.Fatalf("Unexpected rem1 len URLs, got %d, want %d", got, want) 2529 } 2530 2531 // These should be OUT of order. 2532 var random bool 2533 for i := range orderedURLs { 2534 if gotRandom[i].String() != orderedURLs[i] { 2535 random = true 2536 break 2537 } 2538 } 2539 if !random { 2540 t.Fatal("Expected urls to be random") 2541 } 2542 }) 2543 } 2544 2545 func TestLargeMaxControlLine(t *testing.T) { 2546 confFileName := createConfFile(t, []byte(` 2547 max_control_line = 3000000000 2548 `)) 2549 if _, err := ProcessConfigFile(confFileName); err == nil { 2550 t.Fatalf("Expected an error from too large of a max_control_line entry") 2551 } 2552 } 2553 2554 func TestLargeMaxPayload(t *testing.T) { 2555 confFileName := createConfFile(t, []byte(` 2556 max_payload = 3000000000 2557 `)) 2558 if _, err := ProcessConfigFile(confFileName); err == nil { 2559 t.Fatalf("Expected an error from too large of a max_payload entry") 2560 } 2561 2562 confFileName = createConfFile(t, []byte(` 2563 max_payload = 100000 2564 max_pending = 50000 2565 `)) 2566 o := LoadConfig(confFileName) 2567 s, err := NewServer(o) 2568 if err == nil || !strings.Contains(err.Error(), "cannot be higher") { 2569 if s != nil { 2570 s.Shutdown() 2571 } 2572 t.Fatalf("Unexpected error: %v", err) 2573 } 2574 } 2575 2576 func TestHandleUnknownTopLevelConfigurationField(t *testing.T) { 2577 conf := createConfFile(t, []byte(` 2578 port: 1234 2579 streaming { 2580 id: "me" 2581 } 2582 `)) 2583 2584 // Verify that we get an error because of unknown "streaming" field. 2585 opts := &Options{} 2586 if err := opts.ProcessConfigFile(conf); err == nil || !strings.Contains(err.Error(), "streaming") { 2587 t.Fatal("Expected error, got none") 2588 } 2589 2590 // Verify that if that is set, we get no error 2591 NoErrOnUnknownFields(true) 2592 defer NoErrOnUnknownFields(false) 2593 2594 if err := opts.ProcessConfigFile(conf); err != nil { 2595 t.Fatalf("Unexpected error: %v", err) 2596 } 2597 if opts.Port != 1234 { 2598 t.Fatalf("Port was not parsed correctly: %v", opts.Port) 2599 } 2600 2601 // Verify that ignore works only on top level fields. 2602 changeCurrentConfigContentWithNewContent(t, conf, []byte(` 2603 port: 1234 2604 cluster { 2605 non_top_level_unknown_field: 123 2606 } 2607 streaming { 2608 id: "me" 2609 } 2610 `)) 2611 if err := opts.ProcessConfigFile(conf); err == nil || !strings.Contains(err.Error(), "non_top_level") { 2612 t.Fatal("Expected error, got none") 2613 } 2614 } 2615 2616 func TestSublistNoCacheConfig(t *testing.T) { 2617 confFileName := createConfFile(t, []byte(` 2618 disable_sublist_cache: true 2619 `)) 2620 opts, err := ProcessConfigFile(confFileName) 2621 if err != nil { 2622 t.Fatalf("Received an error reading config file: %v", err) 2623 } 2624 if !opts.NoSublistCache { 2625 t.Fatalf("Expected sublist cache to be disabled") 2626 } 2627 } 2628 2629 func TestSublistNoCacheConfigOnAccounts(t *testing.T) { 2630 confFileName := createConfFile(t, []byte(` 2631 listen: "127.0.0.1:-1" 2632 disable_sublist_cache: true 2633 2634 accounts { 2635 synadia { 2636 users [ {nkey : UBAAQWTW6CG2G6ANGNKB5U2B7HRWHSGMZEZX3AQSAJOQDAUGJD46LD2E} ] 2637 } 2638 nats.io { 2639 users [ {nkey : UC6NLCN7AS34YOJVCYD4PJ3QB7QGLYG5B5IMBT25VW5K4TNUJODM7BOX} ] 2640 } 2641 } 2642 no_sys_acc = true 2643 `)) 2644 2645 s, _ := RunServerWithConfig(confFileName) 2646 defer s.Shutdown() 2647 2648 // Check that all account sublists do not have caching enabled. 2649 ta := s.numReservedAccounts() + 2 2650 if la := s.numAccounts(); la != ta { 2651 t.Fatalf("Expected to have a server with %d active accounts, got %v", ta, la) 2652 } 2653 2654 s.accounts.Range(func(k, v any) bool { 2655 acc := v.(*Account) 2656 if acc == nil { 2657 t.Fatalf("Expected non-nil sublist for account") 2658 } 2659 if acc.sl.CacheEnabled() { 2660 t.Fatalf("Expected the account sublist to not have caching enabled") 2661 } 2662 return true 2663 }) 2664 } 2665 2666 func TestParsingResponsePermissions(t *testing.T) { 2667 template := ` 2668 listen: "127.0.0.1:-1" 2669 authorization { 2670 users [ 2671 { 2672 user: ivan 2673 password: pwd 2674 permissions { 2675 allow_responses { 2676 %s 2677 %s 2678 } 2679 } 2680 } 2681 ] 2682 } 2683 ` 2684 2685 check := func(t *testing.T, conf string, expectedError string, expectedMaxMsgs int, expectedTTL time.Duration) { 2686 t.Helper() 2687 opts, err := ProcessConfigFile(conf) 2688 if expectedError != "" { 2689 if err == nil || !strings.Contains(err.Error(), expectedError) { 2690 t.Fatalf("Expected error about %q, got %q", expectedError, err) 2691 } 2692 // OK! 2693 return 2694 } 2695 if err != nil { 2696 t.Fatalf("Error on process: %v", err) 2697 } 2698 u := opts.Users[0] 2699 p := u.Permissions.Response 2700 if p == nil { 2701 t.Fatalf("Expected response permissions to be set, it was not") 2702 } 2703 if n := p.MaxMsgs; n != expectedMaxMsgs { 2704 t.Fatalf("Expected response max msgs to be %v, got %v", expectedMaxMsgs, n) 2705 } 2706 if ttl := p.Expires; ttl != expectedTTL { 2707 t.Fatalf("Expected response ttl to be %v, got %v", expectedTTL, ttl) 2708 } 2709 } 2710 2711 // Check defaults 2712 conf := createConfFile(t, []byte(fmt.Sprintf(template, "", ""))) 2713 check(t, conf, "", DEFAULT_ALLOW_RESPONSE_MAX_MSGS, DEFAULT_ALLOW_RESPONSE_EXPIRATION) 2714 2715 conf = createConfFile(t, []byte(fmt.Sprintf(template, "max: 10", ""))) 2716 check(t, conf, "", 10, DEFAULT_ALLOW_RESPONSE_EXPIRATION) 2717 2718 conf = createConfFile(t, []byte(fmt.Sprintf(template, "", "ttl: 5s"))) 2719 check(t, conf, "", DEFAULT_ALLOW_RESPONSE_MAX_MSGS, 5*time.Second) 2720 2721 conf = createConfFile(t, []byte(fmt.Sprintf(template, "max: 0", ""))) 2722 check(t, conf, "", DEFAULT_ALLOW_RESPONSE_MAX_MSGS, DEFAULT_ALLOW_RESPONSE_EXPIRATION) 2723 2724 conf = createConfFile(t, []byte(fmt.Sprintf(template, "", `ttl: "0s"`))) 2725 check(t, conf, "", DEFAULT_ALLOW_RESPONSE_MAX_MSGS, DEFAULT_ALLOW_RESPONSE_EXPIRATION) 2726 2727 // Check normal values 2728 conf = createConfFile(t, []byte(fmt.Sprintf(template, "max: 10", `ttl: "5s"`))) 2729 check(t, conf, "", 10, 5*time.Second) 2730 2731 // Check negative values ok 2732 conf = createConfFile(t, []byte(fmt.Sprintf(template, "max: -1", `ttl: "5s"`))) 2733 check(t, conf, "", -1, 5*time.Second) 2734 2735 conf = createConfFile(t, []byte(fmt.Sprintf(template, "max: 10", `ttl: "-1s"`))) 2736 check(t, conf, "", 10, -1*time.Second) 2737 2738 conf = createConfFile(t, []byte(fmt.Sprintf(template, "max: -1", `ttl: "-1s"`))) 2739 check(t, conf, "", -1, -1*time.Second) 2740 2741 // Check parsing errors 2742 conf = createConfFile(t, []byte(fmt.Sprintf(template, "unknown_field: 123", ""))) 2743 check(t, conf, "Unknown field", 0, 0) 2744 2745 conf = createConfFile(t, []byte(fmt.Sprintf(template, "max: 10", "ttl: 123"))) 2746 check(t, conf, "not a duration string", 0, 0) 2747 2748 conf = createConfFile(t, []byte(fmt.Sprintf(template, "max: 10", "ttl: xyz"))) 2749 check(t, conf, "error parsing expires", 0, 0) 2750 } 2751 2752 func TestExpandPath(t *testing.T) { 2753 if runtime.GOOS == "windows" { 2754 origUserProfile := os.Getenv("USERPROFILE") 2755 origHomeDrive, origHomePath := os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH") 2756 defer func() { 2757 os.Setenv("USERPROFILE", origUserProfile) 2758 os.Setenv("HOMEDRIVE", origHomeDrive) 2759 os.Setenv("HOMEPATH", origHomePath) 2760 }() 2761 2762 cases := []struct { 2763 path string 2764 userProfile string 2765 homeDrive string 2766 homePath string 2767 2768 wantPath string 2769 wantErr bool 2770 }{ 2771 // Missing HOMEDRIVE and HOMEPATH. 2772 {path: "/Foo/Bar", userProfile: `C:\Foo\Bar`, wantPath: "/Foo/Bar"}, 2773 {path: "Foo/Bar", userProfile: `C:\Foo\Bar`, wantPath: "Foo/Bar"}, 2774 {path: "~/Fizz", userProfile: `C:\Foo\Bar`, wantPath: `C:\Foo\Bar\Fizz`}, 2775 {path: `${HOMEDRIVE}${HOMEPATH}\Fizz`, homeDrive: `C:`, homePath: `\Foo\Bar`, wantPath: `C:\Foo\Bar\Fizz`}, 2776 2777 // Missing USERPROFILE. 2778 {path: "~/Fizz", homeDrive: "X:", homePath: `\Foo\Bar`, wantPath: `X:\Foo\Bar\Fizz`}, 2779 2780 // Set all environment variables. HOMEDRIVE and HOMEPATH take 2781 // precedence. 2782 {path: "~/Fizz", userProfile: `C:\Foo\Bar`, 2783 homeDrive: "X:", homePath: `\Foo\Bar`, wantPath: `X:\Foo\Bar\Fizz`}, 2784 2785 // Missing all environment variables. 2786 {path: "~/Fizz", wantErr: true}, 2787 } 2788 for i, c := range cases { 2789 t.Run(fmt.Sprintf("windows case %d", i), func(t *testing.T) { 2790 os.Setenv("USERPROFILE", c.userProfile) 2791 os.Setenv("HOMEDRIVE", c.homeDrive) 2792 os.Setenv("HOMEPATH", c.homePath) 2793 2794 gotPath, err := expandPath(c.path) 2795 if !c.wantErr && err != nil { 2796 t.Fatalf("unexpected error: got=%v; want=%v", err, nil) 2797 } else if c.wantErr && err == nil { 2798 t.Fatalf("unexpected success: got=%v; want=%v", nil, "err") 2799 } 2800 2801 if gotPath != c.wantPath { 2802 t.Fatalf("unexpected path: got=%v; want=%v", gotPath, c.wantPath) 2803 } 2804 }) 2805 } 2806 2807 return 2808 } 2809 2810 // Unix tests 2811 2812 origHome := os.Getenv("HOME") 2813 defer os.Setenv("HOME", origHome) 2814 2815 cases := []struct { 2816 path string 2817 home string 2818 wantPath string 2819 wantErr bool 2820 }{ 2821 {path: "/foo/bar", home: "/fizz/buzz", wantPath: "/foo/bar"}, 2822 {path: "foo/bar", home: "/fizz/buzz", wantPath: "foo/bar"}, 2823 {path: "~/fizz", home: "/foo/bar", wantPath: "/foo/bar/fizz"}, 2824 {path: "$HOME/fizz", home: "/foo/bar", wantPath: "/foo/bar/fizz"}, 2825 2826 // missing HOME env var 2827 {path: "~/fizz", wantErr: true}, 2828 } 2829 for i, c := range cases { 2830 t.Run(fmt.Sprintf("unix case %d", i), func(t *testing.T) { 2831 os.Setenv("HOME", c.home) 2832 2833 gotPath, err := expandPath(c.path) 2834 if !c.wantErr && err != nil { 2835 t.Fatalf("unexpected error: got=%v; want=%v", err, nil) 2836 } else if c.wantErr && err == nil { 2837 t.Fatalf("unexpected success: got=%v; want=%v", nil, "err") 2838 } 2839 2840 if gotPath != c.wantPath { 2841 t.Fatalf("unexpected path: got=%v; want=%v", gotPath, c.wantPath) 2842 } 2843 }) 2844 } 2845 } 2846 2847 func TestNoAuthUserCode(t *testing.T) { 2848 confFileName := createConfFile(t, []byte(` 2849 listen: "127.0.0.1:-1" 2850 no_auth_user: $NO_AUTH_USER 2851 2852 accounts { 2853 synadia { 2854 users [ 2855 {user: "a", password: "a"}, 2856 {nkey : UBAAQWTW6CG2G6ANGNKB5U2B7HRWHSGMZEZX3AQSAJOQDAUGJD46LD2E}, 2857 ] 2858 } 2859 acc { 2860 users [ 2861 {user: "c", password: "c"} 2862 ] 2863 } 2864 } 2865 # config for $G 2866 authorization { 2867 users [ 2868 {user: "b", password: "b"} 2869 ] 2870 } 2871 `)) 2872 defer os.Unsetenv("NO_AUTH_USER") 2873 2874 for _, user := range []string{"a", "b", "b"} { 2875 t.Run(user, func(t *testing.T) { 2876 os.Setenv("NO_AUTH_USER", user) 2877 opts, err := ProcessConfigFile(confFileName) 2878 if err != nil { 2879 t.Fatalf("Received unexpected error %s", err) 2880 } else { 2881 opts.NoLog = true 2882 srv := RunServer(opts) 2883 nc, err := nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", opts.Port)) 2884 if err != nil { 2885 t.Fatalf("couldn't connect %s", err) 2886 } 2887 nc.Close() 2888 srv.Shutdown() 2889 } 2890 }) 2891 } 2892 2893 for _, badUser := range []string{"notthere", "UBAAQWTW6CG2G6ANGNKB5U2B7HRWHSGMZEZX3AQSAJOQDAUGJD46LD2F"} { 2894 t.Run(badUser, func(t *testing.T) { 2895 os.Setenv("NO_AUTH_USER", badUser) 2896 opts, err := ProcessConfigFile(confFileName) 2897 if err != nil { 2898 t.Fatalf("Received unexpected error %s", err) 2899 } 2900 s, err := NewServer(opts) 2901 if err != nil { 2902 if !strings.HasPrefix(err.Error(), "no_auth_user") { 2903 t.Fatalf("Received unexpected error %s", err) 2904 } 2905 return // error looks as expected 2906 } 2907 s.Shutdown() 2908 t.Fatalf("Received no error, where no_auth_user error was expected") 2909 }) 2910 } 2911 2912 } 2913 2914 const operatorJwtWithSysAccAndUrlResolver = ` 2915 listen: "127.0.0.1:-1" 2916 operator: eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJJVEdJNjNCUUszM1VNN1pBSzZWT1RXNUZEU01ESlNQU1pRQ0RMNUlLUzZQTVhBU0ROQ01RIiwiaWF0IjoxNTg5ODM5MjA1LCJpc3MiOiJPQ1k2REUyRVRTTjNVT0RGVFlFWEJaTFFMSTdYNEdTWFI1NE5aQzRCQkxJNlFDVFpVVDY1T0lWTiIsIm5hbWUiOiJPUCIsInN1YiI6Ik9DWTZERTJFVFNOM1VPREZUWUVYQlpMUUxJN1g0R1NYUjU0TlpDNEJCTEk2UUNUWlVUNjVPSVZOIiwidHlwZSI6Im9wZXJhdG9yIiwibmF0cyI6eyJhY2NvdW50X3NlcnZlcl91cmwiOiJodHRwOi8vbG9jYWxob3N0OjgwMDAvand0L3YxIiwib3BlcmF0b3Jfc2VydmljZV91cmxzIjpbIm5hdHM6Ly9sb2NhbGhvc3Q6NDIyMiJdLCJzeXN0ZW1fYWNjb3VudCI6IkFEWjU0N0IyNFdIUExXT0s3VE1MTkJTQTdGUUZYUjZVTTJOWjRISE5JQjdSREZWWlFGT1o0R1FRIn19.3u710KqMLwgXwsMvhxfEp9xzK84XyAZ-4dd6QY0T6hGj8Bw9mS-HcQ7HbvDDNU01S61tNFfpma_JR6LtB3ixBg 2917 ` 2918 2919 func TestReadOperatorJWT(t *testing.T) { 2920 confFileName := createConfFile(t, []byte(operatorJwtWithSysAccAndUrlResolver)) 2921 opts, err := ProcessConfigFile(confFileName) 2922 if err != nil { 2923 t.Fatalf("Received unexpected error %s", err) 2924 } 2925 if opts.SystemAccount != "ADZ547B24WHPLWOK7TMLNBSA7FQFXR6UM2NZ4HHNIB7RDFVZQFOZ4GQQ" { 2926 t.Fatalf("Expected different SystemAccount: %s", opts.SystemAccount) 2927 } 2928 if r, ok := opts.AccountResolver.(*URLAccResolver); !ok { 2929 t.Fatalf("Expected different SystemAccount: %s", opts.SystemAccount) 2930 } else if r.url != "http://localhost:8000/jwt/v1/accounts/" { 2931 t.Fatalf("Expected different SystemAccount: %s", r.url) 2932 } 2933 } 2934 2935 // using memory resolver so this test does not have to start the memory resolver 2936 const operatorJwtWithSysAccAndMemResolver = ` 2937 listen: "127.0.0.1:-1" 2938 // Operator "TESTOP" 2939 operator: eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiJLRTZRU0tWTU1VWFFKNFZCTDNSNDdGRFlIWElaTDRZSE1INjVIT0k1UjZCNUpPUkxVQlZBIiwiaWF0IjoxNTg5OTE2MzgyLCJpc3MiOiJPQVRUVkJYTElVTVRRT1FXVUEySU0zRkdUQlFRSEFHUEZaQTVET05NTlFSUlRQUjYzTERBTDM1WiIsIm5hbWUiOiJURVNUT1AiLCJzdWIiOiJPQVRUVkJYTElVTVRRT1FXVUEySU0zRkdUQlFRSEFHUEZaQTVET05NTlFSUlRQUjYzTERBTDM1WiIsInR5cGUiOiJvcGVyYXRvciIsIm5hdHMiOnsic3lzdGVtX2FjY291bnQiOiJBRFNQT1lNSFhKTjZKVllRQ0xSWjVYUTVJVU42QTNTMzNYQTROVjRWSDc0NDIzVTdVN1lSNFlWVyJ9fQ.HiyUtlk8kectKHeQHtuqFcjFt0RbYZE_WAqPCcoWlV2IFVdXuOTzShYEMgDmtgvsFG_zxNQOj08Gr6a06ovwBA 2940 resolver: MEMORY 2941 resolver_preload: { 2942 // Account "TESTSYS" 2943 ADSPOYMHXJN6JVYQCLRZ5XQ5IUN6A3S33XA4NV4VH74423U7U7YR4YVW: eyJ0eXAiOiJqd3QiLCJhbGciOiJlZDI1NTE5In0.eyJqdGkiOiI2WEtYUFZNTjdEVFlBSUE0R1JDWUxXUElSM1ZEM1Q2UVk2RFg3NURHTVFVWkdVWTJSRFNRIiwiaWF0IjoxNTg5OTE2MzIzLCJpc3MiOiJPQVRUVkJYTElVTVRRT1FXVUEySU0zRkdUQlFRSEFHUEZaQTVET05NTlFSUlRQUjYzTERBTDM1WiIsIm5hbWUiOiJURVNUU1lTIiwic3ViIjoiQURTUE9ZTUhYSk42SlZZUUNMUlo1WFE1SVVONkEzUzMzWEE0TlY0Vkg3NDQyM1U3VTdZUjRZVlciLCJ0eXBlIjoiYWNjb3VudCIsIm5hdHMiOnsibGltaXRzIjp7InN1YnMiOi0xLCJjb25uIjotMSwibGVhZiI6LTEsImltcG9ydHMiOi0xLCJleHBvcnRzIjotMSwiZGF0YSI6LTEsInBheWxvYWQiOi0xLCJ3aWxkY2FyZHMiOnRydWV9fX0.vhtWanIrOncdNfg-yO-7L61ccc-yRacvVtEsaIgWBEmW4czlEPhsiF1MkUKG91rtgcbwUf73ZIFEfja5MgFBAQ 2944 } 2945 ` 2946 2947 func TestReadOperatorJWTSystemAccountMatch(t *testing.T) { 2948 confFileName := createConfFile(t, []byte(operatorJwtWithSysAccAndMemResolver+` 2949 system_account: ADSPOYMHXJN6JVYQCLRZ5XQ5IUN6A3S33XA4NV4VH74423U7U7YR4YVW 2950 `)) 2951 opts, err := ProcessConfigFile(confFileName) 2952 if err != nil { 2953 t.Fatalf("Received unexpected error %s", err) 2954 } 2955 s, err := NewServer(opts) 2956 if err != nil { 2957 t.Fatalf("Received unexpected error %s", err) 2958 } 2959 s.Shutdown() 2960 } 2961 2962 func TestReadOperatorJWTSystemAccountMismatch(t *testing.T) { 2963 confFileName := createConfFile(t, []byte(operatorJwtWithSysAccAndMemResolver+` 2964 system_account: ADXJJCDCSRSMCOV25FXQW7R4QOG7R763TVEXBNWJHLBMBGWOJYG5XZBG 2965 `)) 2966 opts, err := ProcessConfigFile(confFileName) 2967 if err != nil { 2968 t.Fatalf("Received unexpected error %s", err) 2969 } 2970 s, err := NewServer(opts) 2971 if err == nil { 2972 s.Shutdown() 2973 t.Fatalf("Received no error") 2974 } else if !strings.Contains(err.Error(), "system_account in config and operator JWT must be identical") { 2975 t.Fatalf("Received unexpected error %s", err) 2976 } 2977 } 2978 2979 func TestReadOperatorAssertVersion(t *testing.T) { 2980 kp, _ := nkeys.CreateOperator() 2981 pk, _ := kp.PublicKey() 2982 op := jwt.NewOperatorClaims(pk) 2983 op.AssertServerVersion = "1.2.3" 2984 jwt, err := op.Encode(kp) 2985 if err != nil { 2986 t.Fatalf("Received unexpected error %s", err) 2987 } 2988 confFileName := createConfFile(t, []byte(fmt.Sprintf(` 2989 operator: %s 2990 resolver: MEM 2991 `, jwt))) 2992 opts, err := ProcessConfigFile(confFileName) 2993 if err != nil { 2994 t.Fatalf("Received unexpected error %s", err) 2995 } 2996 s, err := NewServer(opts) 2997 if err != nil { 2998 t.Fatalf("Received unexpected error %s", err) 2999 } 3000 s.Shutdown() 3001 } 3002 3003 func TestReadOperatorAssertVersionFail(t *testing.T) { 3004 kp, _ := nkeys.CreateOperator() 3005 pk, _ := kp.PublicKey() 3006 op := jwt.NewOperatorClaims(pk) 3007 op.AssertServerVersion = "10.20.30" 3008 jwt, err := op.Encode(kp) 3009 if err != nil { 3010 t.Fatalf("Received unexpected error %s", err) 3011 } 3012 confFileName := createConfFile(t, []byte(fmt.Sprintf(` 3013 operator: %s 3014 resolver: MEM 3015 `, jwt))) 3016 opts, err := ProcessConfigFile(confFileName) 3017 if err != nil { 3018 t.Fatalf("Received unexpected error %s", err) 3019 } 3020 s, err := NewServer(opts) 3021 if err == nil { 3022 s.Shutdown() 3023 t.Fatalf("Received no error") 3024 } else if !strings.Contains(err.Error(), "expected major version 10 > server major version") { 3025 t.Fatal("expected different error got: ", err) 3026 } 3027 } 3028 3029 func TestClusterNameAndGatewayNameConflict(t *testing.T) { 3030 conf := createConfFile(t, []byte(` 3031 listen: 127.0.0.1:-1 3032 cluster { 3033 name: A 3034 listen: 127.0.0.1:-1 3035 } 3036 gateway { 3037 name: B 3038 listen: 127.0.0.1:-1 3039 } 3040 `)) 3041 3042 opts, err := ProcessConfigFile(conf) 3043 if err != nil { 3044 t.Fatalf("Unexpected error: %v", err) 3045 } 3046 3047 if err := validateOptions(opts); err != ErrClusterNameConfigConflict { 3048 t.Fatalf("Expected ErrClusterNameConfigConflict got %v", err) 3049 } 3050 } 3051 3052 func TestDefaultAuthTimeout(t *testing.T) { 3053 opts := DefaultOptions() 3054 opts.AuthTimeout = 0 3055 s := RunServer(opts) 3056 defer s.Shutdown() 3057 3058 sopts := s.getOpts() 3059 if at := time.Duration(sopts.AuthTimeout * float64(time.Second)); at != AUTH_TIMEOUT { 3060 t.Fatalf("Expected auth timeout to be %v, got %v", AUTH_TIMEOUT, at) 3061 } 3062 s.Shutdown() 3063 3064 opts = DefaultOptions() 3065 tc := &TLSConfigOpts{ 3066 CertFile: "../test/configs/certs/server-cert.pem", 3067 KeyFile: "../test/configs/certs/server-key.pem", 3068 CaFile: "../test/configs/certs/ca.pem", 3069 Timeout: 4.0, 3070 } 3071 tlsConfig, err := GenTLSConfig(tc) 3072 if err != nil { 3073 t.Fatalf("Error generating tls config: %v", err) 3074 } 3075 opts.TLSConfig = tlsConfig 3076 opts.TLSTimeout = tc.Timeout 3077 s = RunServer(opts) 3078 defer s.Shutdown() 3079 3080 sopts = s.getOpts() 3081 if sopts.AuthTimeout != 5 { 3082 t.Fatalf("Expected auth timeout to be %v, got %v", 5, sopts.AuthTimeout) 3083 } 3084 } 3085 3086 func TestQueuePermissions(t *testing.T) { 3087 cfgFmt := ` 3088 listen: 127.0.0.1:-1 3089 no_auth_user: u 3090 authorization { 3091 users [{ 3092 user: u, password: pwd, permissions: { sub: { %s: ["foo.> *.dev"] } } 3093 }] 3094 }` 3095 errChan := make(chan error, 1) 3096 defer close(errChan) 3097 for _, test := range []struct { 3098 permType string 3099 queue string 3100 errExpected bool 3101 }{ 3102 {"allow", "queue.dev", false}, 3103 {"allow", "", true}, 3104 {"allow", "bad", true}, 3105 {"deny", "", false}, 3106 {"deny", "queue.dev", true}, 3107 } { 3108 t.Run(test.permType+test.queue, func(t *testing.T) { 3109 confFileName := createConfFile(t, []byte(fmt.Sprintf(cfgFmt, test.permType))) 3110 opts, err := ProcessConfigFile(confFileName) 3111 if err != nil { 3112 t.Fatalf("Received unexpected error %s", err) 3113 } 3114 opts.NoLog, opts.NoSigs = true, true 3115 s := RunServer(opts) 3116 defer s.Shutdown() 3117 nc, err := nats.Connect(fmt.Sprintf("nats://127.0.0.1:%d", opts.Port), 3118 nats.ErrorHandler(func(conn *nats.Conn, s *nats.Subscription, err error) { 3119 errChan <- err 3120 })) 3121 if err != nil { 3122 t.Fatalf("No error expected: %v", err) 3123 } 3124 defer nc.Close() 3125 if test.queue == "" { 3126 if _, err := nc.Subscribe("foo.bar", func(msg *nats.Msg) {}); err != nil { 3127 t.Fatalf("no error expected: %v", err) 3128 } 3129 } else { 3130 if _, err := nc.QueueSubscribe("foo.bar", test.queue, func(msg *nats.Msg) {}); err != nil { 3131 t.Fatalf("no error expected: %v", err) 3132 } 3133 } 3134 nc.Flush() 3135 select { 3136 case err := <-errChan: 3137 if !test.errExpected { 3138 t.Fatalf("Expected no error, got %v", err) 3139 } 3140 if !strings.Contains(err.Error(), `Permissions Violation for Subscription to "foo.bar"`) { 3141 t.Fatalf("error %v", err) 3142 } 3143 case <-time.After(150 * time.Millisecond): 3144 if test.errExpected { 3145 t.Fatal("Expected an error") 3146 } 3147 } 3148 }) 3149 3150 } 3151 } 3152 3153 func TestResolverPinnedAccountsFail(t *testing.T) { 3154 cfgFmt := ` 3155 operator: %s 3156 resolver: URL(foo.bar) 3157 resolver_pinned_accounts: [%s] 3158 ` 3159 3160 conf := createConfFile(t, []byte(fmt.Sprintf(cfgFmt, ojwt, "f"))) 3161 srv, err := NewServer(LoadConfig(conf)) 3162 defer srv.Shutdown() 3163 require_Error(t, err) 3164 require_Contains(t, err.Error(), " is not a valid public account nkey") 3165 3166 conf = createConfFile(t, []byte(fmt.Sprintf(cfgFmt, ojwt, "1, x"))) 3167 _, err = ProcessConfigFile(conf) 3168 require_Error(t, err) 3169 require_Contains(t, "parsing resolver_pinned_accounts: unsupported type") 3170 } 3171 3172 func TestMaxSubTokens(t *testing.T) { 3173 conf := createConfFile(t, []byte(` 3174 listen: 127.0.0.1:-1 3175 max_sub_tokens: 4 3176 `)) 3177 3178 s, _ := RunServerWithConfig(conf) 3179 defer s.Shutdown() 3180 3181 nc, err := nats.Connect(s.ClientURL()) 3182 require_NoError(t, err) 3183 defer nc.Close() 3184 3185 errs := make(chan error, 1) 3186 3187 nc.SetErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 3188 errs <- err 3189 }) 3190 3191 bad := "a.b.c.d.e" 3192 _, err = nc.SubscribeSync(bad) 3193 require_NoError(t, err) 3194 3195 select { 3196 case e := <-errs: 3197 if !strings.Contains(e.Error(), "too many tokens") { 3198 t.Fatalf("Got wrong error: %v", err) 3199 } 3200 case <-time.After(2 * time.Second): 3201 t.Fatal("Did not get the permissions error") 3202 } 3203 } 3204 3205 func TestGetStorageSize(t *testing.T) { 3206 tt := []struct { 3207 input string 3208 want int64 3209 err bool 3210 }{ 3211 {"1K", 1024, false}, 3212 {"1M", 1048576, false}, 3213 {"1G", 1073741824, false}, 3214 {"1T", 1099511627776, false}, 3215 {"1L", 0, true}, 3216 {"TT", 0, true}, 3217 {"", 0, false}, 3218 } 3219 3220 for _, v := range tt { 3221 var testErr bool 3222 got, err := getStorageSize(v.input) 3223 if err != nil { 3224 testErr = true 3225 } 3226 3227 if got != v.want || v.err != testErr { 3228 t.Errorf("Got: %v, want %v with error: %v", got, v.want, testErr) 3229 } 3230 } 3231 3232 } 3233 3234 func TestAuthorizationAndAccountsMisconfigurations(t *testing.T) { 3235 // There is a test called TestConfigCheck but we can't use it 3236 // because the place where the error will be reported will depend 3237 // if the error is found while parsing authorization{} or 3238 // accounts{}, but we can't control the internal parsing of those 3239 // (due to lexer giving back a map and iteration over map is random) 3240 // regardless of the ordering in the configuration file. 3241 // The test is also repeated 3242 for _, test := range []struct { 3243 name string 3244 config string 3245 err string 3246 }{ 3247 { 3248 "duplicate users", 3249 ` 3250 authorization = {users = [ {user: "user1", pass: "pwd"} ] } 3251 accounts { ACC { users = [ {user: "user1"} ] } } 3252 `, 3253 fmt.Sprintf("Duplicate user %q detected", "user1"), 3254 }, 3255 { 3256 "duplicate nkey", 3257 ` 3258 authorization = {users = [ {nkey: UC6NLCN7AS34YOJVCYD4PJ3QB7QGLYG5B5IMBT25VW5K4TNUJODM7BOX} ] } 3259 accounts { ACC { users = [ {nkey: UC6NLCN7AS34YOJVCYD4PJ3QB7QGLYG5B5IMBT25VW5K4TNUJODM7BOX} ] } } 3260 `, 3261 fmt.Sprintf("Duplicate nkey %q detected", "UC6NLCN7AS34YOJVCYD4PJ3QB7QGLYG5B5IMBT25VW5K4TNUJODM7BOX"), 3262 }, 3263 { 3264 "auth single user and password and accounts users", 3265 ` 3266 authorization = {user: "user1", password: "pwd"} 3267 accounts = { ACC { users = [ {user: "user2", pass: "pwd"} ] } } 3268 `, 3269 "Can not have a single user/pass", 3270 }, 3271 { 3272 "auth single user and password and accounts nkeys", 3273 ` 3274 authorization = {user: "user1", password: "pwd"} 3275 accounts = { ACC { users = [ {nkey: UC6NLCN7AS34YOJVCYD4PJ3QB7QGLYG5B5IMBT25VW5K4TNUJODM7BOX} ] } } 3276 `, 3277 "Can not have a single user/pass", 3278 }, 3279 { 3280 "auth token and accounts users", 3281 ` 3282 authorization = {token: "my_token"} 3283 accounts = { ACC { users = [ {user: "user2", pass: "pwd"} ] } } 3284 `, 3285 "Can not have a token", 3286 }, 3287 { 3288 "auth token and accounts nkeys", 3289 ` 3290 authorization = {token: "my_token"} 3291 accounts = { ACC { users = [ {nkey: UC6NLCN7AS34YOJVCYD4PJ3QB7QGLYG5B5IMBT25VW5K4TNUJODM7BOX} ] } } 3292 `, 3293 "Can not have a token", 3294 }, 3295 } { 3296 t.Run(test.name, func(t *testing.T) { 3297 conf := createConfFile(t, []byte(test.config)) 3298 if _, err := ProcessConfigFile(conf); err == nil || !strings.Contains(err.Error(), test.err) { 3299 t.Fatalf("Expected error %q, got %q", test.err, err.Error()) 3300 } 3301 }) 3302 } 3303 }