get.pme.sh/pnats@v0.0.0-20240304004023-26bb5a137ed0/server/reload.go (about) 1 // Copyright 2017-2023 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 "crypto/tls" 18 "errors" 19 "fmt" 20 "net/url" 21 "reflect" 22 "sort" 23 "strings" 24 "sync/atomic" 25 "time" 26 27 "github.com/klauspost/compress/s2" 28 29 "github.com/nats-io/jwt/v2" 30 "github.com/nats-io/nuid" 31 ) 32 33 // FlagSnapshot captures the server options as specified by CLI flags at 34 // startup. This should not be modified once the server has started. 35 var FlagSnapshot *Options 36 37 type reloadContext struct { 38 oldClusterPerms *RoutePermissions 39 } 40 41 // option is a hot-swappable configuration setting. 42 type option interface { 43 // Apply the server option. 44 Apply(server *Server) 45 46 // IsLoggingChange indicates if this option requires reloading the logger. 47 IsLoggingChange() bool 48 49 // IsTraceLevelChange indicates if this option requires reloading cached trace level. 50 // Clients store trace level separately. 51 IsTraceLevelChange() bool 52 53 // IsAuthChange indicates if this option requires reloading authorization. 54 IsAuthChange() bool 55 56 // IsTLSChange indicates if this option requires reloading TLS. 57 IsTLSChange() bool 58 59 // IsClusterPermsChange indicates if this option requires reloading 60 // cluster permissions. 61 IsClusterPermsChange() bool 62 63 // IsClusterPoolSizeOrAccountsChange indicates if this option requires 64 // special handling for changes in cluster's pool size or accounts list. 65 IsClusterPoolSizeOrAccountsChange() bool 66 67 // IsJetStreamChange inidicates a change in the servers config for JetStream. 68 // Account changes will be handled separately in reloadAuthorization. 69 IsJetStreamChange() bool 70 71 // Indicates a change in the server that requires publishing the server's statz 72 IsStatszChange() bool 73 } 74 75 // noopOption is a base struct that provides default no-op behaviors. 76 type noopOption struct{} 77 78 func (n noopOption) IsLoggingChange() bool { 79 return false 80 } 81 82 func (n noopOption) IsTraceLevelChange() bool { 83 return false 84 } 85 86 func (n noopOption) IsAuthChange() bool { 87 return false 88 } 89 90 func (n noopOption) IsTLSChange() bool { 91 return false 92 } 93 94 func (n noopOption) IsClusterPermsChange() bool { 95 return false 96 } 97 98 func (n noopOption) IsClusterPoolSizeOrAccountsChange() bool { 99 return false 100 } 101 102 func (n noopOption) IsJetStreamChange() bool { 103 return false 104 } 105 106 func (n noopOption) IsStatszChange() bool { 107 return false 108 } 109 110 // loggingOption is a base struct that provides default option behaviors for 111 // logging-related options. 112 type loggingOption struct { 113 noopOption 114 } 115 116 func (l loggingOption) IsLoggingChange() bool { 117 return true 118 } 119 120 // traceLevelOption is a base struct that provides default option behaviors for 121 // tracelevel-related options. 122 type traceLevelOption struct { 123 loggingOption 124 } 125 126 func (l traceLevelOption) IsTraceLevelChange() bool { 127 return true 128 } 129 130 // traceOption implements the option interface for the `trace` setting. 131 type traceOption struct { 132 traceLevelOption 133 newValue bool 134 } 135 136 // Apply is a no-op because logging will be reloaded after options are applied. 137 func (t *traceOption) Apply(server *Server) { 138 server.Noticef("Reloaded: trace = %v", t.newValue) 139 } 140 141 // traceOption implements the option interface for the `trace` setting. 142 type traceVerboseOption struct { 143 traceLevelOption 144 newValue bool 145 } 146 147 // Apply is a no-op because logging will be reloaded after options are applied. 148 func (t *traceVerboseOption) Apply(server *Server) { 149 server.Noticef("Reloaded: trace_verbose = %v", t.newValue) 150 } 151 152 // debugOption implements the option interface for the `debug` setting. 153 type debugOption struct { 154 loggingOption 155 newValue bool 156 } 157 158 // Apply is mostly a no-op because logging will be reloaded after options are applied. 159 // However we will kick the raft nodes if they exist to reload. 160 func (d *debugOption) Apply(server *Server) { 161 server.Noticef("Reloaded: debug = %v", d.newValue) 162 server.reloadDebugRaftNodes(d.newValue) 163 } 164 165 // logtimeOption implements the option interface for the `logtime` setting. 166 type logtimeOption struct { 167 loggingOption 168 newValue bool 169 } 170 171 // Apply is a no-op because logging will be reloaded after options are applied. 172 func (l *logtimeOption) Apply(server *Server) { 173 server.Noticef("Reloaded: logtime = %v", l.newValue) 174 } 175 176 // logtimeUTCOption implements the option interface for the `logtime_utc` setting. 177 type logtimeUTCOption struct { 178 loggingOption 179 newValue bool 180 } 181 182 // Apply is a no-op because logging will be reloaded after options are applied. 183 func (l *logtimeUTCOption) Apply(server *Server) { 184 server.Noticef("Reloaded: logtime_utc = %v", l.newValue) 185 } 186 187 // logfileOption implements the option interface for the `log_file` setting. 188 type logfileOption struct { 189 loggingOption 190 newValue string 191 } 192 193 // Apply is a no-op because logging will be reloaded after options are applied. 194 func (l *logfileOption) Apply(server *Server) { 195 server.Noticef("Reloaded: log_file = %v", l.newValue) 196 } 197 198 // syslogOption implements the option interface for the `syslog` setting. 199 type syslogOption struct { 200 loggingOption 201 newValue bool 202 } 203 204 // Apply is a no-op because logging will be reloaded after options are applied. 205 func (s *syslogOption) Apply(server *Server) { 206 server.Noticef("Reloaded: syslog = %v", s.newValue) 207 } 208 209 // remoteSyslogOption implements the option interface for the `remote_syslog` 210 // setting. 211 type remoteSyslogOption struct { 212 loggingOption 213 newValue string 214 } 215 216 // Apply is a no-op because logging will be reloaded after options are applied. 217 func (r *remoteSyslogOption) Apply(server *Server) { 218 server.Noticef("Reloaded: remote_syslog = %v", r.newValue) 219 } 220 221 // tlsOption implements the option interface for the `tls` setting. 222 type tlsOption struct { 223 noopOption 224 newValue *tls.Config 225 } 226 227 // Apply the tls change. 228 func (t *tlsOption) Apply(server *Server) { 229 server.mu.Lock() 230 tlsRequired := t.newValue != nil 231 server.info.TLSRequired = tlsRequired && !server.getOpts().AllowNonTLS 232 message := "disabled" 233 if tlsRequired { 234 server.info.TLSVerify = (t.newValue.ClientAuth == tls.RequireAndVerifyClientCert) 235 message = "enabled" 236 } 237 server.mu.Unlock() 238 server.Noticef("Reloaded: tls = %s", message) 239 } 240 241 func (t *tlsOption) IsTLSChange() bool { 242 return true 243 } 244 245 // tlsTimeoutOption implements the option interface for the tls `timeout` 246 // setting. 247 type tlsTimeoutOption struct { 248 noopOption 249 newValue float64 250 } 251 252 // Apply is a no-op because the timeout will be reloaded after options are 253 // applied. 254 func (t *tlsTimeoutOption) Apply(server *Server) { 255 server.Noticef("Reloaded: tls timeout = %v", t.newValue) 256 } 257 258 // tlsPinnedCertOption implements the option interface for the tls `pinned_certs` setting. 259 type tlsPinnedCertOption struct { 260 noopOption 261 newValue PinnedCertSet 262 } 263 264 // Apply is a no-op because the pinned certs will be reloaded after options are applied. 265 func (t *tlsPinnedCertOption) Apply(server *Server) { 266 server.Noticef("Reloaded: %d pinned_certs", len(t.newValue)) 267 } 268 269 // tlsHandshakeFirst implements the option interface for the tls `handshake first` setting. 270 type tlsHandshakeFirst struct { 271 noopOption 272 newValue bool 273 } 274 275 // Apply is a no-op because the timeout will be reloaded after options are applied. 276 func (t *tlsHandshakeFirst) Apply(server *Server) { 277 server.Noticef("Reloaded: Client TLS handshake first: %v", t.newValue) 278 } 279 280 // tlsHandshakeFirstFallback implements the option interface for the tls `handshake first fallback delay` setting. 281 type tlsHandshakeFirstFallback struct { 282 noopOption 283 newValue time.Duration 284 } 285 286 // Apply is a no-op because the timeout will be reloaded after options are applied. 287 func (t *tlsHandshakeFirstFallback) Apply(server *Server) { 288 server.Noticef("Reloaded: Client TLS handshake first fallback delay: %v", t.newValue) 289 } 290 291 // authOption is a base struct that provides default option behaviors. 292 type authOption struct { 293 noopOption 294 } 295 296 func (o authOption) IsAuthChange() bool { 297 return true 298 } 299 300 // usernameOption implements the option interface for the `username` setting. 301 type usernameOption struct { 302 authOption 303 } 304 305 // Apply is a no-op because authorization will be reloaded after options are 306 // applied. 307 func (u *usernameOption) Apply(server *Server) { 308 server.Noticef("Reloaded: authorization username") 309 } 310 311 // passwordOption implements the option interface for the `password` setting. 312 type passwordOption struct { 313 authOption 314 } 315 316 // Apply is a no-op because authorization will be reloaded after options are 317 // applied. 318 func (p *passwordOption) Apply(server *Server) { 319 server.Noticef("Reloaded: authorization password") 320 } 321 322 // authorizationOption implements the option interface for the `token` 323 // authorization setting. 324 type authorizationOption struct { 325 authOption 326 } 327 328 // Apply is a no-op because authorization will be reloaded after options are 329 // applied. 330 func (a *authorizationOption) Apply(server *Server) { 331 server.Noticef("Reloaded: authorization token") 332 } 333 334 // authTimeoutOption implements the option interface for the authorization 335 // `timeout` setting. 336 type authTimeoutOption struct { 337 noopOption // Not authOption because this is a no-op; will be reloaded with options. 338 newValue float64 339 } 340 341 // Apply is a no-op because the timeout will be reloaded after options are 342 // applied. 343 func (a *authTimeoutOption) Apply(server *Server) { 344 server.Noticef("Reloaded: authorization timeout = %v", a.newValue) 345 } 346 347 // tagsOption implements the option interface for the `tags` setting. 348 type tagsOption struct { 349 noopOption // Not authOption because this is a no-op; will be reloaded with options. 350 } 351 352 func (u *tagsOption) Apply(server *Server) { 353 server.Noticef("Reloaded: tags") 354 } 355 356 func (u *tagsOption) IsStatszChange() bool { 357 return true 358 } 359 360 // usersOption implements the option interface for the authorization `users` 361 // setting. 362 type usersOption struct { 363 authOption 364 } 365 366 func (u *usersOption) Apply(server *Server) { 367 server.Noticef("Reloaded: authorization users") 368 } 369 370 // nkeysOption implements the option interface for the authorization `users` 371 // setting. 372 type nkeysOption struct { 373 authOption 374 } 375 376 func (u *nkeysOption) Apply(server *Server) { 377 server.Noticef("Reloaded: authorization nkey users") 378 } 379 380 // clusterOption implements the option interface for the `cluster` setting. 381 type clusterOption struct { 382 authOption 383 newValue ClusterOpts 384 permsChanged bool 385 accsAdded []string 386 accsRemoved []string 387 poolSizeChanged bool 388 compressChanged bool 389 } 390 391 // Apply the cluster change. 392 func (c *clusterOption) Apply(s *Server) { 393 // TODO: support enabling/disabling clustering. 394 s.mu.Lock() 395 tlsRequired := c.newValue.TLSConfig != nil 396 s.routeInfo.TLSRequired = tlsRequired 397 s.routeInfo.TLSVerify = tlsRequired 398 s.routeInfo.AuthRequired = c.newValue.Username != "" 399 if c.newValue.NoAdvertise { 400 s.routeInfo.ClientConnectURLs = nil 401 s.routeInfo.WSConnectURLs = nil 402 } else { 403 s.routeInfo.ClientConnectURLs = s.clientConnectURLs 404 s.routeInfo.WSConnectURLs = s.websocket.connectURLs 405 } 406 s.setRouteInfoHostPortAndIP() 407 var routes []*client 408 if c.compressChanged { 409 co := &s.getOpts().Cluster.Compression 410 newMode := co.Mode 411 s.forEachRoute(func(r *client) { 412 r.mu.Lock() 413 // Skip routes that are "not supported" (because they will never do 414 // compression) or the routes that have already the new compression 415 // mode. 416 if r.route.compression == CompressionNotSupported || r.route.compression == newMode { 417 r.mu.Unlock() 418 return 419 } 420 // We need to close the route if it had compression "off" or the new 421 // mode is compression "off", or if the new mode is "accept", because 422 // these require negotiation. 423 if r.route.compression == CompressionOff || newMode == CompressionOff || newMode == CompressionAccept { 424 routes = append(routes, r) 425 } else if newMode == CompressionS2Auto { 426 // If the mode is "s2_auto", we need to check if there is really 427 // need to change, and at any rate, we want to save the actual 428 // compression level here, not s2_auto. 429 r.updateS2AutoCompressionLevel(co, &r.route.compression) 430 } else { 431 // Simply change the compression writer 432 r.out.cw = s2.NewWriter(nil, s2WriterOptions(newMode)...) 433 r.route.compression = newMode 434 } 435 r.mu.Unlock() 436 }) 437 } 438 s.mu.Unlock() 439 if c.newValue.Name != "" && c.newValue.Name != s.ClusterName() { 440 s.setClusterName(c.newValue.Name) 441 } 442 for _, r := range routes { 443 r.closeConnection(ClientClosed) 444 } 445 s.Noticef("Reloaded: cluster") 446 if tlsRequired && c.newValue.TLSConfig.InsecureSkipVerify { 447 s.Warnf(clusterTLSInsecureWarning) 448 } 449 } 450 451 func (c *clusterOption) IsClusterPermsChange() bool { 452 return c.permsChanged 453 } 454 455 func (c *clusterOption) IsClusterPoolSizeOrAccountsChange() bool { 456 return c.poolSizeChanged || len(c.accsAdded) > 0 || len(c.accsRemoved) > 0 457 } 458 459 func (c *clusterOption) diffPoolAndAccounts(old *ClusterOpts) { 460 c.poolSizeChanged = c.newValue.PoolSize != old.PoolSize 461 addLoop: 462 for _, na := range c.newValue.PinnedAccounts { 463 for _, oa := range old.PinnedAccounts { 464 if na == oa { 465 continue addLoop 466 } 467 } 468 c.accsAdded = append(c.accsAdded, na) 469 } 470 removeLoop: 471 for _, oa := range old.PinnedAccounts { 472 for _, na := range c.newValue.PinnedAccounts { 473 if oa == na { 474 continue removeLoop 475 } 476 } 477 c.accsRemoved = append(c.accsRemoved, oa) 478 } 479 } 480 481 // routesOption implements the option interface for the cluster `routes` 482 // setting. 483 type routesOption struct { 484 noopOption 485 add []*url.URL 486 remove []*url.URL 487 } 488 489 // Apply the route changes by adding and removing the necessary routes. 490 func (r *routesOption) Apply(server *Server) { 491 server.mu.Lock() 492 routes := make([]*client, server.numRoutes()) 493 i := 0 494 server.forEachRoute(func(r *client) { 495 routes[i] = r 496 i++ 497 }) 498 // If there was a change, notify monitoring code that it should 499 // update the route URLs if /varz endpoint is inspected. 500 if len(r.add)+len(r.remove) > 0 { 501 server.varzUpdateRouteURLs = true 502 } 503 server.mu.Unlock() 504 505 // Remove routes. 506 for _, remove := range r.remove { 507 for _, client := range routes { 508 var url *url.URL 509 client.mu.Lock() 510 if client.route != nil { 511 url = client.route.url 512 } 513 client.mu.Unlock() 514 if url != nil && urlsAreEqual(url, remove) { 515 // Do not attempt to reconnect when route is removed. 516 client.setNoReconnect() 517 client.closeConnection(RouteRemoved) 518 server.Noticef("Removed route %v", remove) 519 } 520 } 521 } 522 523 // Add routes. 524 server.mu.Lock() 525 server.solicitRoutes(r.add, server.getOpts().Cluster.PinnedAccounts) 526 server.mu.Unlock() 527 528 server.Noticef("Reloaded: cluster routes") 529 } 530 531 // maxConnOption implements the option interface for the `max_connections` 532 // setting. 533 type maxConnOption struct { 534 noopOption 535 newValue int 536 } 537 538 // Apply the max connections change by closing random connections til we are 539 // below the limit if necessary. 540 func (m *maxConnOption) Apply(server *Server) { 541 server.mu.Lock() 542 var ( 543 clients = make([]*client, len(server.clients)) 544 i = 0 545 ) 546 // Map iteration is random, which allows us to close random connections. 547 for _, client := range server.clients { 548 clients[i] = client 549 i++ 550 } 551 server.mu.Unlock() 552 553 if m.newValue > 0 && len(clients) > m.newValue { 554 // Close connections til we are within the limit. 555 var ( 556 numClose = len(clients) - m.newValue 557 closed = 0 558 ) 559 for _, client := range clients { 560 client.maxConnExceeded() 561 closed++ 562 if closed >= numClose { 563 break 564 } 565 } 566 server.Noticef("Closed %d connections to fall within max_connections", closed) 567 } 568 server.Noticef("Reloaded: max_connections = %v", m.newValue) 569 } 570 571 // pidFileOption implements the option interface for the `pid_file` setting. 572 type pidFileOption struct { 573 noopOption 574 newValue string 575 } 576 577 // Apply the setting by logging the pid to the new file. 578 func (p *pidFileOption) Apply(server *Server) { 579 if p.newValue == "" { 580 return 581 } 582 if err := server.logPid(); err != nil { 583 server.Errorf("Failed to write pidfile: %v", err) 584 } 585 server.Noticef("Reloaded: pid_file = %v", p.newValue) 586 } 587 588 // portsFileDirOption implements the option interface for the `portFileDir` setting. 589 type portsFileDirOption struct { 590 noopOption 591 oldValue string 592 newValue string 593 } 594 595 func (p *portsFileDirOption) Apply(server *Server) { 596 server.deletePortsFile(p.oldValue) 597 server.logPorts() 598 server.Noticef("Reloaded: ports_file_dir = %v", p.newValue) 599 } 600 601 // maxControlLineOption implements the option interface for the 602 // `max_control_line` setting. 603 type maxControlLineOption struct { 604 noopOption 605 newValue int32 606 } 607 608 // Apply the setting by updating each client. 609 func (m *maxControlLineOption) Apply(server *Server) { 610 mcl := int32(m.newValue) 611 server.mu.Lock() 612 for _, client := range server.clients { 613 atomic.StoreInt32(&client.mcl, mcl) 614 } 615 server.mu.Unlock() 616 server.Noticef("Reloaded: max_control_line = %d", mcl) 617 } 618 619 // maxPayloadOption implements the option interface for the `max_payload` 620 // setting. 621 type maxPayloadOption struct { 622 noopOption 623 newValue int32 624 } 625 626 // Apply the setting by updating the server info and each client. 627 func (m *maxPayloadOption) Apply(server *Server) { 628 server.mu.Lock() 629 server.info.MaxPayload = m.newValue 630 for _, client := range server.clients { 631 atomic.StoreInt32(&client.mpay, int32(m.newValue)) 632 } 633 server.mu.Unlock() 634 server.Noticef("Reloaded: max_payload = %d", m.newValue) 635 } 636 637 // pingIntervalOption implements the option interface for the `ping_interval` 638 // setting. 639 type pingIntervalOption struct { 640 noopOption 641 newValue time.Duration 642 } 643 644 // Apply is a no-op because the ping interval will be reloaded after options 645 // are applied. 646 func (p *pingIntervalOption) Apply(server *Server) { 647 server.Noticef("Reloaded: ping_interval = %s", p.newValue) 648 } 649 650 // maxPingsOutOption implements the option interface for the `ping_max` 651 // setting. 652 type maxPingsOutOption struct { 653 noopOption 654 newValue int 655 } 656 657 // Apply is a no-op because the ping interval will be reloaded after options 658 // are applied. 659 func (m *maxPingsOutOption) Apply(server *Server) { 660 server.Noticef("Reloaded: ping_max = %d", m.newValue) 661 } 662 663 // writeDeadlineOption implements the option interface for the `write_deadline` 664 // setting. 665 type writeDeadlineOption struct { 666 noopOption 667 newValue time.Duration 668 } 669 670 // Apply is a no-op because the write deadline will be reloaded after options 671 // are applied. 672 func (w *writeDeadlineOption) Apply(server *Server) { 673 server.Noticef("Reloaded: write_deadline = %s", w.newValue) 674 } 675 676 // clientAdvertiseOption implements the option interface for the `client_advertise` setting. 677 type clientAdvertiseOption struct { 678 noopOption 679 newValue string 680 } 681 682 // Apply the setting by updating the server info and regenerate the infoJSON byte array. 683 func (c *clientAdvertiseOption) Apply(server *Server) { 684 server.mu.Lock() 685 server.setInfoHostPort() 686 server.mu.Unlock() 687 server.Noticef("Reload: client_advertise = %s", c.newValue) 688 } 689 690 // accountsOption implements the option interface. 691 // Ensure that authorization code is executed if any change in accounts 692 type accountsOption struct { 693 authOption 694 } 695 696 // Apply is a no-op. Changes will be applied in reloadAuthorization 697 func (a *accountsOption) Apply(s *Server) { 698 s.Noticef("Reloaded: accounts") 699 } 700 701 // For changes to a server's config. 702 type jetStreamOption struct { 703 noopOption 704 newValue bool 705 } 706 707 func (a *jetStreamOption) Apply(s *Server) { 708 s.Noticef("Reloaded: JetStream") 709 } 710 711 func (jso jetStreamOption) IsJetStreamChange() bool { 712 return true 713 } 714 715 func (jso jetStreamOption) IsStatszChange() bool { 716 return true 717 } 718 719 type ocspOption struct { 720 tlsOption 721 newValue *OCSPConfig 722 } 723 724 func (a *ocspOption) Apply(s *Server) { 725 s.Noticef("Reloaded: OCSP") 726 } 727 728 type ocspResponseCacheOption struct { 729 tlsOption 730 newValue *OCSPResponseCacheConfig 731 } 732 733 func (a *ocspResponseCacheOption) Apply(s *Server) { 734 s.Noticef("Reloaded OCSP peer cache") 735 } 736 737 // connectErrorReports implements the option interface for the `connect_error_reports` 738 // setting. 739 type connectErrorReports struct { 740 noopOption 741 newValue int 742 } 743 744 // Apply is a no-op because the value will be reloaded after options are applied. 745 func (c *connectErrorReports) Apply(s *Server) { 746 s.Noticef("Reloaded: connect_error_reports = %v", c.newValue) 747 } 748 749 // connectErrorReports implements the option interface for the `connect_error_reports` 750 // setting. 751 type reconnectErrorReports struct { 752 noopOption 753 newValue int 754 } 755 756 // Apply is a no-op because the value will be reloaded after options are applied. 757 func (r *reconnectErrorReports) Apply(s *Server) { 758 s.Noticef("Reloaded: reconnect_error_reports = %v", r.newValue) 759 } 760 761 // maxTracedMsgLenOption implements the option interface for the `max_traced_msg_len` setting. 762 type maxTracedMsgLenOption struct { 763 noopOption 764 newValue int 765 } 766 767 // Apply the setting by updating the maximum traced message length. 768 func (m *maxTracedMsgLenOption) Apply(server *Server) { 769 server.mu.Lock() 770 defer server.mu.Unlock() 771 server.opts.MaxTracedMsgLen = m.newValue 772 server.Noticef("Reloaded: max_traced_msg_len = %d", m.newValue) 773 } 774 775 type mqttAckWaitReload struct { 776 noopOption 777 newValue time.Duration 778 } 779 780 func (o *mqttAckWaitReload) Apply(s *Server) { 781 s.Noticef("Reloaded: MQTT ack_wait = %v", o.newValue) 782 } 783 784 type mqttMaxAckPendingReload struct { 785 noopOption 786 newValue uint16 787 } 788 789 func (o *mqttMaxAckPendingReload) Apply(s *Server) { 790 s.mqttUpdateMaxAckPending(o.newValue) 791 s.Noticef("Reloaded: MQTT max_ack_pending = %v", o.newValue) 792 } 793 794 type mqttStreamReplicasReload struct { 795 noopOption 796 newValue int 797 } 798 799 func (o *mqttStreamReplicasReload) Apply(s *Server) { 800 s.Noticef("Reloaded: MQTT stream_replicas = %v", o.newValue) 801 } 802 803 type mqttConsumerReplicasReload struct { 804 noopOption 805 newValue int 806 } 807 808 func (o *mqttConsumerReplicasReload) Apply(s *Server) { 809 s.Noticef("Reloaded: MQTT consumer_replicas = %v", o.newValue) 810 } 811 812 type mqttConsumerMemoryStorageReload struct { 813 noopOption 814 newValue bool 815 } 816 817 func (o *mqttConsumerMemoryStorageReload) Apply(s *Server) { 818 s.Noticef("Reloaded: MQTT consumer_memory_storage = %v", o.newValue) 819 } 820 821 type mqttInactiveThresholdReload struct { 822 noopOption 823 newValue time.Duration 824 } 825 826 func (o *mqttInactiveThresholdReload) Apply(s *Server) { 827 s.Noticef("Reloaded: MQTT consumer_inactive_threshold = %v", o.newValue) 828 } 829 830 type profBlockRateReload struct { 831 noopOption 832 newValue int 833 } 834 835 func (o *profBlockRateReload) Apply(s *Server) { 836 s.setBlockProfileRate(o.newValue) 837 s.Noticef("Reloaded: prof_block_rate = %v", o.newValue) 838 } 839 840 type leafNodeOption struct { 841 noopOption 842 tlsFirstChanged bool 843 compressionChanged bool 844 } 845 846 func (l *leafNodeOption) Apply(s *Server) { 847 opts := s.getOpts() 848 if l.tlsFirstChanged { 849 s.Noticef("Reloaded: LeafNode TLS HandshakeFirst value is: %v", opts.LeafNode.TLSHandshakeFirst) 850 for _, r := range opts.LeafNode.Remotes { 851 s.Noticef("Reloaded: LeafNode Remote to %v TLS HandshakeFirst value is: %v", r.URLs, r.TLSHandshakeFirst) 852 } 853 } 854 if l.compressionChanged { 855 var leafs []*client 856 acceptSideCompOpts := &opts.LeafNode.Compression 857 858 s.mu.RLock() 859 // First, update our internal leaf remote configurations with the new 860 // compress options. 861 // Since changing the remotes (as in adding/removing) is currently not 862 // supported, we know that we should have the same number in Options 863 // than in leafRemoteCfgs, but to be sure, use the max size. 864 max := len(opts.LeafNode.Remotes) 865 if l := len(s.leafRemoteCfgs); l < max { 866 max = l 867 } 868 for i := 0; i < max; i++ { 869 lr := s.leafRemoteCfgs[i] 870 lr.Lock() 871 lr.Compression = opts.LeafNode.Remotes[i].Compression 872 lr.Unlock() 873 } 874 875 for _, l := range s.leafs { 876 var co *CompressionOpts 877 878 l.mu.Lock() 879 if r := l.leaf.remote; r != nil { 880 co = &r.Compression 881 } else { 882 co = acceptSideCompOpts 883 } 884 newMode := co.Mode 885 // Skip leaf connections that are "not supported" (because they 886 // will never do compression) or the ones that have already the 887 // new compression mode. 888 if l.leaf.compression == CompressionNotSupported || l.leaf.compression == newMode { 889 l.mu.Unlock() 890 continue 891 } 892 // We need to close the connections if it had compression "off" or the new 893 // mode is compression "off", or if the new mode is "accept", because 894 // these require negotiation. 895 if l.leaf.compression == CompressionOff || newMode == CompressionOff || newMode == CompressionAccept { 896 leafs = append(leafs, l) 897 } else if newMode == CompressionS2Auto { 898 // If the mode is "s2_auto", we need to check if there is really 899 // need to change, and at any rate, we want to save the actual 900 // compression level here, not s2_auto. 901 l.updateS2AutoCompressionLevel(co, &l.leaf.compression) 902 } else { 903 // Simply change the compression writer 904 l.out.cw = s2.NewWriter(nil, s2WriterOptions(newMode)...) 905 l.leaf.compression = newMode 906 } 907 l.mu.Unlock() 908 } 909 s.mu.RUnlock() 910 // Close the connections for which negotiation is required. 911 for _, l := range leafs { 912 l.closeConnection(ClientClosed) 913 } 914 s.Noticef("Reloaded: LeafNode compression settings") 915 } 916 } 917 918 // Compares options and disconnects clients that are no longer listed in pinned certs. Lock must not be held. 919 func (s *Server) recheckPinnedCerts(curOpts *Options, newOpts *Options) { 920 s.mu.Lock() 921 disconnectClients := []*client{} 922 protoToPinned := map[int]PinnedCertSet{} 923 if !reflect.DeepEqual(newOpts.TLSPinnedCerts, curOpts.TLSPinnedCerts) { 924 protoToPinned[NATS] = curOpts.TLSPinnedCerts 925 } 926 if !reflect.DeepEqual(newOpts.MQTT.TLSPinnedCerts, curOpts.MQTT.TLSPinnedCerts) { 927 protoToPinned[MQTT] = curOpts.MQTT.TLSPinnedCerts 928 } 929 if !reflect.DeepEqual(newOpts.Websocket.TLSPinnedCerts, curOpts.Websocket.TLSPinnedCerts) { 930 protoToPinned[WS] = curOpts.Websocket.TLSPinnedCerts 931 } 932 for _, c := range s.clients { 933 if c.kind != CLIENT { 934 continue 935 } 936 if pinned, ok := protoToPinned[c.clientType()]; ok { 937 if !c.matchesPinnedCert(pinned) { 938 disconnectClients = append(disconnectClients, c) 939 } 940 } 941 } 942 checkClients := func(kind int, clients map[uint64]*client, set PinnedCertSet) { 943 for _, c := range clients { 944 if c.kind == kind && !c.matchesPinnedCert(set) { 945 disconnectClients = append(disconnectClients, c) 946 } 947 } 948 } 949 if !reflect.DeepEqual(newOpts.LeafNode.TLSPinnedCerts, curOpts.LeafNode.TLSPinnedCerts) { 950 checkClients(LEAF, s.leafs, newOpts.LeafNode.TLSPinnedCerts) 951 } 952 if !reflect.DeepEqual(newOpts.Cluster.TLSPinnedCerts, curOpts.Cluster.TLSPinnedCerts) { 953 s.forEachRoute(func(c *client) { 954 if !c.matchesPinnedCert(newOpts.Cluster.TLSPinnedCerts) { 955 disconnectClients = append(disconnectClients, c) 956 } 957 }) 958 } 959 if s.gateway.enabled && reflect.DeepEqual(newOpts.Gateway.TLSPinnedCerts, curOpts.Gateway.TLSPinnedCerts) { 960 gw := s.gateway 961 gw.RLock() 962 for _, c := range gw.out { 963 if !c.matchesPinnedCert(newOpts.Gateway.TLSPinnedCerts) { 964 disconnectClients = append(disconnectClients, c) 965 } 966 } 967 checkClients(GATEWAY, gw.in, newOpts.Gateway.TLSPinnedCerts) 968 gw.RUnlock() 969 } 970 s.mu.Unlock() 971 if len(disconnectClients) > 0 { 972 s.Noticef("Disconnect %d clients due to pinned certs reload", len(disconnectClients)) 973 for _, c := range disconnectClients { 974 c.closeConnection(TLSHandshakeError) 975 } 976 } 977 } 978 979 // Reload reads the current configuration file and calls out to ReloadOptions 980 // to apply the changes. This returns an error if the server was not started 981 // with a config file or an option which doesn't support hot-swapping was changed. 982 func (s *Server) Reload() error { 983 s.mu.Lock() 984 configFile := s.configFile 985 s.mu.Unlock() 986 if configFile == "" { 987 return errors.New("can only reload config when a file is provided using -c or --config") 988 } 989 990 newOpts, err := ProcessConfigFile(configFile) 991 if err != nil { 992 // TODO: Dump previous good config to a .bak file? 993 return err 994 } 995 return s.ReloadOptions(newOpts) 996 } 997 998 // ReloadOptions applies any supported options from the provided Option 999 // type. This returns an error if an option which doesn't support 1000 // hot-swapping was changed. 1001 func (s *Server) ReloadOptions(newOpts *Options) error { 1002 s.mu.Lock() 1003 1004 curOpts := s.getOpts() 1005 1006 // Wipe trusted keys if needed when we have an operator. 1007 if len(curOpts.TrustedOperators) > 0 && len(curOpts.TrustedKeys) > 0 { 1008 curOpts.TrustedKeys = nil 1009 } 1010 1011 clientOrgPort := curOpts.Port 1012 clusterOrgPort := curOpts.Cluster.Port 1013 gatewayOrgPort := curOpts.Gateway.Port 1014 leafnodesOrgPort := curOpts.LeafNode.Port 1015 websocketOrgPort := curOpts.Websocket.Port 1016 mqttOrgPort := curOpts.MQTT.Port 1017 1018 s.mu.Unlock() 1019 1020 // In case "-cluster ..." was provided through the command line, this will 1021 // properly set the Cluster.Host/Port etc... 1022 if l := curOpts.Cluster.ListenStr; l != _EMPTY_ { 1023 newOpts.Cluster.ListenStr = l 1024 overrideCluster(newOpts) 1025 } 1026 1027 // Apply flags over config file settings. 1028 newOpts = MergeOptions(newOpts, FlagSnapshot) 1029 1030 // Need more processing for boolean flags... 1031 if FlagSnapshot != nil { 1032 applyBoolFlags(newOpts, FlagSnapshot) 1033 } 1034 1035 setBaselineOptions(newOpts) 1036 1037 // setBaselineOptions sets Port to 0 if set to -1 (RANDOM port) 1038 // If that's the case, set it to the saved value when the accept loop was 1039 // created. 1040 if newOpts.Port == 0 { 1041 newOpts.Port = clientOrgPort 1042 } 1043 // We don't do that for cluster, so check against -1. 1044 if newOpts.Cluster.Port == -1 { 1045 newOpts.Cluster.Port = clusterOrgPort 1046 } 1047 if newOpts.Gateway.Port == -1 { 1048 newOpts.Gateway.Port = gatewayOrgPort 1049 } 1050 if newOpts.LeafNode.Port == -1 { 1051 newOpts.LeafNode.Port = leafnodesOrgPort 1052 } 1053 if newOpts.Websocket.Port == -1 { 1054 newOpts.Websocket.Port = websocketOrgPort 1055 } 1056 if newOpts.MQTT.Port == -1 { 1057 newOpts.MQTT.Port = mqttOrgPort 1058 } 1059 1060 if err := s.reloadOptions(curOpts, newOpts); err != nil { 1061 return err 1062 } 1063 1064 s.recheckPinnedCerts(curOpts, newOpts) 1065 1066 s.mu.Lock() 1067 s.configTime = time.Now().UTC() 1068 s.updateVarzConfigReloadableFields(s.varz) 1069 s.mu.Unlock() 1070 return nil 1071 } 1072 func applyBoolFlags(newOpts, flagOpts *Options) { 1073 // Reset fields that may have been set to `true` in 1074 // MergeOptions() when some of the flags default to `true` 1075 // but have not been explicitly set and therefore value 1076 // from config file should take precedence. 1077 for name, val := range newOpts.inConfig { 1078 f := reflect.ValueOf(newOpts).Elem() 1079 names := strings.Split(name, ".") 1080 for _, name := range names { 1081 f = f.FieldByName(name) 1082 } 1083 f.SetBool(val) 1084 } 1085 // Now apply value (true or false) from flags that have 1086 // been explicitly set in command line 1087 for name, val := range flagOpts.inCmdLine { 1088 f := reflect.ValueOf(newOpts).Elem() 1089 names := strings.Split(name, ".") 1090 for _, name := range names { 1091 f = f.FieldByName(name) 1092 } 1093 f.SetBool(val) 1094 } 1095 } 1096 1097 // reloadOptions reloads the server config with the provided options. If an 1098 // option that doesn't support hot-swapping is changed, this returns an error. 1099 func (s *Server) reloadOptions(curOpts, newOpts *Options) error { 1100 // Apply to the new options some of the options that may have been set 1101 // that can't be configured in the config file (this can happen in 1102 // applications starting NATS Server programmatically). 1103 newOpts.CustomClientAuthentication = curOpts.CustomClientAuthentication 1104 newOpts.CustomRouterAuthentication = curOpts.CustomRouterAuthentication 1105 1106 changed, err := s.diffOptions(newOpts) 1107 if err != nil { 1108 return err 1109 } 1110 1111 if len(changed) != 0 { 1112 if err := validateOptions(newOpts); err != nil { 1113 return err 1114 } 1115 } 1116 1117 // Create a context that is used to pass special info that we may need 1118 // while applying the new options. 1119 ctx := reloadContext{oldClusterPerms: curOpts.Cluster.Permissions} 1120 s.setOpts(newOpts) 1121 s.applyOptions(&ctx, changed) 1122 return nil 1123 } 1124 1125 // For the purpose of comparing, impose a order on slice data types where order does not matter 1126 func imposeOrder(value interface{}) error { 1127 switch value := value.(type) { 1128 case []*Account: 1129 sort.Slice(value, func(i, j int) bool { 1130 return value[i].Name < value[j].Name 1131 }) 1132 for _, a := range value { 1133 sort.Slice(a.imports.streams, func(i, j int) bool { 1134 return a.imports.streams[i].acc.Name < a.imports.streams[j].acc.Name 1135 }) 1136 } 1137 case []*User: 1138 sort.Slice(value, func(i, j int) bool { 1139 return value[i].Username < value[j].Username 1140 }) 1141 case []*NkeyUser: 1142 sort.Slice(value, func(i, j int) bool { 1143 return value[i].Nkey < value[j].Nkey 1144 }) 1145 case []*url.URL: 1146 sort.Slice(value, func(i, j int) bool { 1147 return value[i].String() < value[j].String() 1148 }) 1149 case []string: 1150 sort.Strings(value) 1151 case []*jwt.OperatorClaims: 1152 sort.Slice(value, func(i, j int) bool { 1153 return value[i].Issuer < value[j].Issuer 1154 }) 1155 case GatewayOpts: 1156 sort.Slice(value.Gateways, func(i, j int) bool { 1157 return value.Gateways[i].Name < value.Gateways[j].Name 1158 }) 1159 case WebsocketOpts: 1160 sort.Strings(value.AllowedOrigins) 1161 case string, bool, uint8, int, int32, int64, time.Duration, float64, nil, LeafNodeOpts, ClusterOpts, *tls.Config, PinnedCertSet, 1162 *URLAccResolver, *MemAccResolver, *DirAccResolver, *CacheDirAccResolver, Authentication, MQTTOpts, jwt.TagList, 1163 *OCSPConfig, map[string]string, JSLimitOpts, StoreCipher, *OCSPResponseCacheConfig: 1164 // explicitly skipped types 1165 case *AuthCallout: 1166 default: 1167 // this will fail during unit tests 1168 return fmt.Errorf("OnReload, sort or explicitly skip type: %s", 1169 reflect.TypeOf(value)) 1170 } 1171 return nil 1172 } 1173 1174 // diffOptions returns a slice containing options which have been changed. If 1175 // an option that doesn't support hot-swapping is changed, this returns an 1176 // error. 1177 func (s *Server) diffOptions(newOpts *Options) ([]option, error) { 1178 var ( 1179 oldConfig = reflect.ValueOf(s.getOpts()).Elem() 1180 newConfig = reflect.ValueOf(newOpts).Elem() 1181 diffOpts = []option{} 1182 1183 // Need to keep track of whether JS is being disabled 1184 // to prevent changing limits at runtime. 1185 jsEnabled = s.JetStreamEnabled() 1186 disableJS bool 1187 jsMemLimitsChanged bool 1188 jsFileLimitsChanged bool 1189 jsStoreDirChanged bool 1190 ) 1191 for i := 0; i < oldConfig.NumField(); i++ { 1192 field := oldConfig.Type().Field(i) 1193 // field.PkgPath is empty for exported fields, and is not for unexported ones. 1194 // We skip the unexported fields. 1195 if field.PkgPath != _EMPTY_ { 1196 continue 1197 } 1198 var ( 1199 oldValue = oldConfig.Field(i).Interface() 1200 newValue = newConfig.Field(i).Interface() 1201 ) 1202 if err := imposeOrder(oldValue); err != nil { 1203 return nil, err 1204 } 1205 if err := imposeOrder(newValue); err != nil { 1206 return nil, err 1207 } 1208 1209 optName := strings.ToLower(field.Name) 1210 // accounts and users (referencing accounts) will always differ as accounts 1211 // contain internal state, say locks etc..., so we don't bother here. 1212 // This also avoids races with atomic stats counters 1213 if optName != "accounts" && optName != "users" { 1214 if changed := !reflect.DeepEqual(oldValue, newValue); !changed { 1215 // Check to make sure we are running JetStream if we think we should be. 1216 if optName == "jetstream" && newValue.(bool) { 1217 if !jsEnabled { 1218 diffOpts = append(diffOpts, &jetStreamOption{newValue: true}) 1219 } 1220 } 1221 continue 1222 } 1223 } 1224 switch optName { 1225 case "traceverbose": 1226 diffOpts = append(diffOpts, &traceVerboseOption{newValue: newValue.(bool)}) 1227 case "trace": 1228 diffOpts = append(diffOpts, &traceOption{newValue: newValue.(bool)}) 1229 case "debug": 1230 diffOpts = append(diffOpts, &debugOption{newValue: newValue.(bool)}) 1231 case "logtime": 1232 diffOpts = append(diffOpts, &logtimeOption{newValue: newValue.(bool)}) 1233 case "logtimeutc": 1234 diffOpts = append(diffOpts, &logtimeUTCOption{newValue: newValue.(bool)}) 1235 case "logfile": 1236 diffOpts = append(diffOpts, &logfileOption{newValue: newValue.(string)}) 1237 case "syslog": 1238 diffOpts = append(diffOpts, &syslogOption{newValue: newValue.(bool)}) 1239 case "remotesyslog": 1240 diffOpts = append(diffOpts, &remoteSyslogOption{newValue: newValue.(string)}) 1241 case "tlsconfig": 1242 diffOpts = append(diffOpts, &tlsOption{newValue: newValue.(*tls.Config)}) 1243 case "tlstimeout": 1244 diffOpts = append(diffOpts, &tlsTimeoutOption{newValue: newValue.(float64)}) 1245 case "tlspinnedcerts": 1246 diffOpts = append(diffOpts, &tlsPinnedCertOption{newValue: newValue.(PinnedCertSet)}) 1247 case "tlshandshakefirst": 1248 diffOpts = append(diffOpts, &tlsHandshakeFirst{newValue: newValue.(bool)}) 1249 case "tlshandshakefirstfallback": 1250 diffOpts = append(diffOpts, &tlsHandshakeFirstFallback{newValue: newValue.(time.Duration)}) 1251 case "username": 1252 diffOpts = append(diffOpts, &usernameOption{}) 1253 case "password": 1254 diffOpts = append(diffOpts, &passwordOption{}) 1255 case "tags": 1256 diffOpts = append(diffOpts, &tagsOption{}) 1257 case "authorization": 1258 diffOpts = append(diffOpts, &authorizationOption{}) 1259 case "authtimeout": 1260 diffOpts = append(diffOpts, &authTimeoutOption{newValue: newValue.(float64)}) 1261 case "users": 1262 diffOpts = append(diffOpts, &usersOption{}) 1263 case "nkeys": 1264 diffOpts = append(diffOpts, &nkeysOption{}) 1265 case "cluster": 1266 newClusterOpts := newValue.(ClusterOpts) 1267 oldClusterOpts := oldValue.(ClusterOpts) 1268 if err := validateClusterOpts(oldClusterOpts, newClusterOpts); err != nil { 1269 return nil, err 1270 } 1271 co := &clusterOption{ 1272 newValue: newClusterOpts, 1273 permsChanged: !reflect.DeepEqual(newClusterOpts.Permissions, oldClusterOpts.Permissions), 1274 compressChanged: !reflect.DeepEqual(oldClusterOpts.Compression, newClusterOpts.Compression), 1275 } 1276 co.diffPoolAndAccounts(&oldClusterOpts) 1277 // If there are added accounts, first make sure that we can look them up. 1278 // If we can't let's fail the reload. 1279 for _, acc := range co.accsAdded { 1280 if _, err := s.LookupAccount(acc); err != nil { 1281 return nil, fmt.Errorf("unable to add account %q to the list of dedicated routes: %v", acc, err) 1282 } 1283 } 1284 // If pool_size has been set to negative (but was not before), then let's 1285 // add the system account to the list of removed accounts (we don't have 1286 // to check if already there, duplicates are ok in that case). 1287 if newClusterOpts.PoolSize < 0 && oldClusterOpts.PoolSize >= 0 { 1288 if sys := s.SystemAccount(); sys != nil { 1289 co.accsRemoved = append(co.accsRemoved, sys.GetName()) 1290 } 1291 } 1292 diffOpts = append(diffOpts, co) 1293 case "routes": 1294 add, remove := diffRoutes(oldValue.([]*url.URL), newValue.([]*url.URL)) 1295 diffOpts = append(diffOpts, &routesOption{add: add, remove: remove}) 1296 case "maxconn": 1297 diffOpts = append(diffOpts, &maxConnOption{newValue: newValue.(int)}) 1298 case "pidfile": 1299 diffOpts = append(diffOpts, &pidFileOption{newValue: newValue.(string)}) 1300 case "portsfiledir": 1301 diffOpts = append(diffOpts, &portsFileDirOption{newValue: newValue.(string), oldValue: oldValue.(string)}) 1302 case "maxcontrolline": 1303 diffOpts = append(diffOpts, &maxControlLineOption{newValue: newValue.(int32)}) 1304 case "maxpayload": 1305 diffOpts = append(diffOpts, &maxPayloadOption{newValue: newValue.(int32)}) 1306 case "pinginterval": 1307 diffOpts = append(diffOpts, &pingIntervalOption{newValue: newValue.(time.Duration)}) 1308 case "maxpingsout": 1309 diffOpts = append(diffOpts, &maxPingsOutOption{newValue: newValue.(int)}) 1310 case "writedeadline": 1311 diffOpts = append(diffOpts, &writeDeadlineOption{newValue: newValue.(time.Duration)}) 1312 case "clientadvertise": 1313 cliAdv := newValue.(string) 1314 if cliAdv != "" { 1315 // Validate ClientAdvertise syntax 1316 if _, _, err := parseHostPort(cliAdv, 0); err != nil { 1317 return nil, fmt.Errorf("invalid ClientAdvertise value of %s, err=%v", cliAdv, err) 1318 } 1319 } 1320 diffOpts = append(diffOpts, &clientAdvertiseOption{newValue: cliAdv}) 1321 case "accounts": 1322 diffOpts = append(diffOpts, &accountsOption{}) 1323 case "resolver", "accountresolver", "accountsresolver": 1324 // We can't move from no resolver to one. So check for that. 1325 if (oldValue == nil && newValue != nil) || 1326 (oldValue != nil && newValue == nil) { 1327 return nil, fmt.Errorf("config reload does not support moving to or from an account resolver") 1328 } 1329 diffOpts = append(diffOpts, &accountsOption{}) 1330 case "accountresolvertlsconfig": 1331 diffOpts = append(diffOpts, &accountsOption{}) 1332 case "gateway": 1333 // Not supported for now, but report warning if configuration of gateway 1334 // is actually changed so that user knows that it won't take effect. 1335 1336 // Any deep-equal is likely to fail for when there is a TLSConfig. so 1337 // remove for the test. 1338 tmpOld := oldValue.(GatewayOpts) 1339 tmpNew := newValue.(GatewayOpts) 1340 tmpOld.TLSConfig = nil 1341 tmpNew.TLSConfig = nil 1342 tmpOld.tlsConfigOpts = nil 1343 tmpNew.tlsConfigOpts = nil 1344 1345 // Need to do the same for remote gateways' TLS configs. 1346 // But we can't just set remotes' TLSConfig to nil otherwise this 1347 // would lose the real TLS configuration. 1348 tmpOld.Gateways = copyRemoteGWConfigsWithoutTLSConfig(tmpOld.Gateways) 1349 tmpNew.Gateways = copyRemoteGWConfigsWithoutTLSConfig(tmpNew.Gateways) 1350 1351 // If there is really a change prevents reload. 1352 if !reflect.DeepEqual(tmpOld, tmpNew) { 1353 // See TODO(ik) note below about printing old/new values. 1354 return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", 1355 field.Name, oldValue, newValue) 1356 } 1357 case "leafnode": 1358 // Similar to gateways 1359 tmpOld := oldValue.(LeafNodeOpts) 1360 tmpNew := newValue.(LeafNodeOpts) 1361 tmpOld.TLSConfig = nil 1362 tmpNew.TLSConfig = nil 1363 tmpOld.tlsConfigOpts = nil 1364 tmpNew.tlsConfigOpts = nil 1365 // We will allow TLSHandshakeFirst to me config reloaded. First, 1366 // we just want to detect if there was a change in the leafnodes{} 1367 // block, and if not, we will check the remotes. 1368 handshakeFirstChanged := tmpOld.TLSHandshakeFirst != tmpNew.TLSHandshakeFirst 1369 // If changed, set them (in the temporary variables) to false so that the 1370 // rest of the comparison does not fail. 1371 if handshakeFirstChanged { 1372 tmpOld.TLSHandshakeFirst, tmpNew.TLSHandshakeFirst = false, false 1373 } else if len(tmpOld.Remotes) == len(tmpNew.Remotes) { 1374 // Since we don't support changes in the remotes, we will do a 1375 // simple pass to see if there was a change of this field. 1376 for i := 0; i < len(tmpOld.Remotes); i++ { 1377 if tmpOld.Remotes[i].TLSHandshakeFirst != tmpNew.Remotes[i].TLSHandshakeFirst { 1378 handshakeFirstChanged = true 1379 break 1380 } 1381 } 1382 } 1383 // We also support config reload for compression. Check if it changed before 1384 // blanking them out for the deep-equal check at the end. 1385 compressionChanged := !reflect.DeepEqual(tmpOld.Compression, tmpNew.Compression) 1386 if compressionChanged { 1387 tmpOld.Compression, tmpNew.Compression = CompressionOpts{}, CompressionOpts{} 1388 } else if len(tmpOld.Remotes) == len(tmpNew.Remotes) { 1389 // Same that for tls first check, do the remotes now. 1390 for i := 0; i < len(tmpOld.Remotes); i++ { 1391 if !reflect.DeepEqual(tmpOld.Remotes[i].Compression, tmpNew.Remotes[i].Compression) { 1392 compressionChanged = true 1393 break 1394 } 1395 } 1396 } 1397 1398 // Need to do the same for remote leafnodes' TLS configs. 1399 // But we can't just set remotes' TLSConfig to nil otherwise this 1400 // would lose the real TLS configuration. 1401 tmpOld.Remotes = copyRemoteLNConfigForReloadCompare(tmpOld.Remotes) 1402 tmpNew.Remotes = copyRemoteLNConfigForReloadCompare(tmpNew.Remotes) 1403 1404 // Special check for leafnode remotes changes which are not supported right now. 1405 leafRemotesChanged := func(a, b LeafNodeOpts) bool { 1406 if len(a.Remotes) != len(b.Remotes) { 1407 return true 1408 } 1409 1410 // Check whether all remotes URLs are still the same. 1411 for _, oldRemote := range a.Remotes { 1412 var found bool 1413 1414 if oldRemote.LocalAccount == _EMPTY_ { 1415 oldRemote.LocalAccount = globalAccountName 1416 } 1417 1418 for _, newRemote := range b.Remotes { 1419 // Bind to global account in case not defined. 1420 if newRemote.LocalAccount == _EMPTY_ { 1421 newRemote.LocalAccount = globalAccountName 1422 } 1423 1424 if reflect.DeepEqual(oldRemote, newRemote) { 1425 found = true 1426 break 1427 } 1428 } 1429 if !found { 1430 return true 1431 } 1432 } 1433 1434 return false 1435 } 1436 1437 // First check whether remotes changed at all. If they did not, 1438 // skip them in the complete equal check. 1439 if !leafRemotesChanged(tmpOld, tmpNew) { 1440 tmpOld.Remotes = nil 1441 tmpNew.Remotes = nil 1442 } 1443 1444 // Special check for auth users to detect changes. 1445 // If anything is off will fall through and fail below. 1446 // If we detect they are semantically the same we nil them out 1447 // to pass the check below. 1448 if tmpOld.Users != nil || tmpNew.Users != nil { 1449 if len(tmpOld.Users) == len(tmpNew.Users) { 1450 oua := make(map[string]*User, len(tmpOld.Users)) 1451 nua := make(map[string]*User, len(tmpOld.Users)) 1452 for _, u := range tmpOld.Users { 1453 oua[u.Username] = u 1454 } 1455 for _, u := range tmpNew.Users { 1456 nua[u.Username] = u 1457 } 1458 same := true 1459 for uname, u := range oua { 1460 // If we can not find new one with same name, drop through to fail. 1461 nu, ok := nua[uname] 1462 if !ok { 1463 same = false 1464 break 1465 } 1466 // If username or password or account different break. 1467 if u.Username != nu.Username || u.Password != nu.Password || u.Account.GetName() != nu.Account.GetName() { 1468 same = false 1469 break 1470 } 1471 } 1472 // We can nil out here. 1473 if same { 1474 tmpOld.Users, tmpNew.Users = nil, nil 1475 } 1476 } 1477 } 1478 1479 // If there is really a change prevents reload. 1480 if !reflect.DeepEqual(tmpOld, tmpNew) { 1481 // See TODO(ik) note below about printing old/new values. 1482 return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", 1483 field.Name, oldValue, newValue) 1484 } 1485 1486 diffOpts = append(diffOpts, &leafNodeOption{ 1487 tlsFirstChanged: handshakeFirstChanged, 1488 compressionChanged: compressionChanged, 1489 }) 1490 case "jetstream": 1491 new := newValue.(bool) 1492 old := oldValue.(bool) 1493 if new != old { 1494 diffOpts = append(diffOpts, &jetStreamOption{newValue: new}) 1495 } 1496 1497 // Mark whether JS will be disabled. 1498 disableJS = !new 1499 case "storedir": 1500 new := newValue.(string) 1501 old := oldValue.(string) 1502 modified := new != old 1503 1504 // Check whether JS is being disabled and/or storage dir attempted to change. 1505 if jsEnabled && modified { 1506 if new == _EMPTY_ { 1507 // This means that either JS is being disabled or it is using an temp dir. 1508 // Allow the change but error in case JS was not disabled. 1509 jsStoreDirChanged = true 1510 } else { 1511 return nil, fmt.Errorf("config reload not supported for jetstream storage directory") 1512 } 1513 } 1514 case "jetstreammaxmemory", "jetstreammaxstore": 1515 old := oldValue.(int64) 1516 new := newValue.(int64) 1517 1518 // Check whether JS is being disabled and/or limits are being changed. 1519 var ( 1520 modified = new != old 1521 fromUnset = old == -1 1522 fromSet = !fromUnset 1523 toUnset = new == -1 1524 toSet = !toUnset 1525 ) 1526 if jsEnabled && modified { 1527 // Cannot change limits from dynamic storage at runtime. 1528 switch { 1529 case fromSet && toUnset: 1530 // Limits changed but it may mean that JS is being disabled, 1531 // keep track of the change and error in case it is not. 1532 switch optName { 1533 case "jetstreammaxmemory": 1534 jsMemLimitsChanged = true 1535 case "jetstreammaxstore": 1536 jsFileLimitsChanged = true 1537 default: 1538 return nil, fmt.Errorf("config reload not supported for jetstream max memory and store") 1539 } 1540 case fromUnset && toSet: 1541 // Prevent changing from dynamic max memory / file at runtime. 1542 return nil, fmt.Errorf("config reload not supported for jetstream dynamic max memory and store") 1543 default: 1544 return nil, fmt.Errorf("config reload not supported for jetstream max memory and store") 1545 } 1546 } 1547 case "websocket": 1548 // Similar to gateways 1549 tmpOld := oldValue.(WebsocketOpts) 1550 tmpNew := newValue.(WebsocketOpts) 1551 tmpOld.TLSConfig, tmpOld.tlsConfigOpts = nil, nil 1552 tmpNew.TLSConfig, tmpNew.tlsConfigOpts = nil, nil 1553 // If there is really a change prevents reload. 1554 if !reflect.DeepEqual(tmpOld, tmpNew) { 1555 // See TODO(ik) note below about printing old/new values. 1556 return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", 1557 field.Name, oldValue, newValue) 1558 } 1559 case "mqtt": 1560 diffOpts = append(diffOpts, &mqttAckWaitReload{newValue: newValue.(MQTTOpts).AckWait}) 1561 diffOpts = append(diffOpts, &mqttMaxAckPendingReload{newValue: newValue.(MQTTOpts).MaxAckPending}) 1562 diffOpts = append(diffOpts, &mqttStreamReplicasReload{newValue: newValue.(MQTTOpts).StreamReplicas}) 1563 diffOpts = append(diffOpts, &mqttConsumerReplicasReload{newValue: newValue.(MQTTOpts).ConsumerReplicas}) 1564 diffOpts = append(diffOpts, &mqttConsumerMemoryStorageReload{newValue: newValue.(MQTTOpts).ConsumerMemoryStorage}) 1565 diffOpts = append(diffOpts, &mqttInactiveThresholdReload{newValue: newValue.(MQTTOpts).ConsumerInactiveThreshold}) 1566 1567 // Nil out/set to 0 the options that we allow to be reloaded so that 1568 // we only fail reload if some that we don't support are changed. 1569 tmpOld := oldValue.(MQTTOpts) 1570 tmpNew := newValue.(MQTTOpts) 1571 tmpOld.TLSConfig, tmpOld.tlsConfigOpts, tmpOld.AckWait, tmpOld.MaxAckPending, tmpOld.StreamReplicas, tmpOld.ConsumerReplicas, tmpOld.ConsumerMemoryStorage = nil, nil, 0, 0, 0, 0, false 1572 tmpOld.ConsumerInactiveThreshold = 0 1573 tmpNew.TLSConfig, tmpNew.tlsConfigOpts, tmpNew.AckWait, tmpNew.MaxAckPending, tmpNew.StreamReplicas, tmpNew.ConsumerReplicas, tmpNew.ConsumerMemoryStorage = nil, nil, 0, 0, 0, 0, false 1574 tmpNew.ConsumerInactiveThreshold = 0 1575 1576 if !reflect.DeepEqual(tmpOld, tmpNew) { 1577 // See TODO(ik) note below about printing old/new values. 1578 return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", 1579 field.Name, oldValue, newValue) 1580 } 1581 tmpNew.AckWait = newValue.(MQTTOpts).AckWait 1582 tmpNew.MaxAckPending = newValue.(MQTTOpts).MaxAckPending 1583 tmpNew.StreamReplicas = newValue.(MQTTOpts).StreamReplicas 1584 tmpNew.ConsumerReplicas = newValue.(MQTTOpts).ConsumerReplicas 1585 tmpNew.ConsumerMemoryStorage = newValue.(MQTTOpts).ConsumerMemoryStorage 1586 tmpNew.ConsumerInactiveThreshold = newValue.(MQTTOpts).ConsumerInactiveThreshold 1587 case "connecterrorreports": 1588 diffOpts = append(diffOpts, &connectErrorReports{newValue: newValue.(int)}) 1589 case "reconnecterrorreports": 1590 diffOpts = append(diffOpts, &reconnectErrorReports{newValue: newValue.(int)}) 1591 case "nolog", "nosigs": 1592 // Ignore NoLog and NoSigs options since they are not parsed and only used in 1593 // testing. 1594 continue 1595 case "disableshortfirstping": 1596 newOpts.DisableShortFirstPing = oldValue.(bool) 1597 continue 1598 case "maxtracedmsglen": 1599 diffOpts = append(diffOpts, &maxTracedMsgLenOption{newValue: newValue.(int)}) 1600 case "port": 1601 // check to see if newValue == 0 and continue if so. 1602 if newValue == 0 { 1603 // ignore RANDOM_PORT 1604 continue 1605 } 1606 fallthrough 1607 case "noauthuser": 1608 if oldValue != _EMPTY_ && newValue == _EMPTY_ { 1609 for _, user := range newOpts.Users { 1610 if user.Username == oldValue { 1611 return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", 1612 field.Name, oldValue, newValue) 1613 } 1614 } 1615 } else { 1616 return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", 1617 field.Name, oldValue, newValue) 1618 } 1619 case "systemaccount": 1620 if oldValue != DEFAULT_SYSTEM_ACCOUNT || newValue != _EMPTY_ { 1621 return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", 1622 field.Name, oldValue, newValue) 1623 } 1624 case "ocspconfig": 1625 diffOpts = append(diffOpts, &ocspOption{newValue: newValue.(*OCSPConfig)}) 1626 case "ocspcacheconfig": 1627 diffOpts = append(diffOpts, &ocspResponseCacheOption{newValue: newValue.(*OCSPResponseCacheConfig)}) 1628 case "profblockrate": 1629 new := newValue.(int) 1630 old := oldValue.(int) 1631 if new != old { 1632 diffOpts = append(diffOpts, &profBlockRateReload{newValue: new}) 1633 } 1634 default: 1635 // TODO(ik): Implement String() on those options to have a nice print. 1636 // %v is difficult to figure what's what, %+v print private fields and 1637 // would print passwords. Tried json.Marshal but it is too verbose for 1638 // the URL array. 1639 1640 // Bail out if attempting to reload any unsupported options. 1641 return nil, fmt.Errorf("config reload not supported for %s: old=%v, new=%v", 1642 field.Name, oldValue, newValue) 1643 } 1644 } 1645 1646 // If not disabling JS but limits have changed then it is an error. 1647 if !disableJS { 1648 if jsMemLimitsChanged || jsFileLimitsChanged { 1649 return nil, fmt.Errorf("config reload not supported for jetstream max memory and max store") 1650 } 1651 if jsStoreDirChanged { 1652 return nil, fmt.Errorf("config reload not supported for jetstream storage dir") 1653 } 1654 } 1655 1656 return diffOpts, nil 1657 } 1658 1659 func copyRemoteGWConfigsWithoutTLSConfig(current []*RemoteGatewayOpts) []*RemoteGatewayOpts { 1660 l := len(current) 1661 if l == 0 { 1662 return nil 1663 } 1664 rgws := make([]*RemoteGatewayOpts, 0, l) 1665 for _, rcfg := range current { 1666 cp := *rcfg 1667 cp.TLSConfig = nil 1668 cp.tlsConfigOpts = nil 1669 rgws = append(rgws, &cp) 1670 } 1671 return rgws 1672 } 1673 1674 func copyRemoteLNConfigForReloadCompare(current []*RemoteLeafOpts) []*RemoteLeafOpts { 1675 l := len(current) 1676 if l == 0 { 1677 return nil 1678 } 1679 rlns := make([]*RemoteLeafOpts, 0, l) 1680 for _, rcfg := range current { 1681 cp := *rcfg 1682 cp.TLSConfig = nil 1683 cp.tlsConfigOpts = nil 1684 cp.TLSHandshakeFirst = false 1685 // This is set only when processing a CONNECT, so reset here so that we 1686 // don't fail the DeepEqual comparison. 1687 cp.TLS = false 1688 // For now, remove DenyImports/Exports since those get modified at runtime 1689 // to add JS APIs. 1690 cp.DenyImports, cp.DenyExports = nil, nil 1691 // Remove compression mode 1692 cp.Compression = CompressionOpts{} 1693 rlns = append(rlns, &cp) 1694 } 1695 return rlns 1696 } 1697 1698 func (s *Server) applyOptions(ctx *reloadContext, opts []option) { 1699 var ( 1700 reloadLogging = false 1701 reloadAuth = false 1702 reloadClusterPerms = false 1703 reloadClientTrcLvl = false 1704 reloadJetstream = false 1705 jsEnabled = false 1706 isStatszChange = false 1707 co *clusterOption 1708 ) 1709 for _, opt := range opts { 1710 opt.Apply(s) 1711 if opt.IsLoggingChange() { 1712 reloadLogging = true 1713 } 1714 if opt.IsTraceLevelChange() { 1715 reloadClientTrcLvl = true 1716 } 1717 if opt.IsAuthChange() { 1718 reloadAuth = true 1719 } 1720 if opt.IsClusterPoolSizeOrAccountsChange() { 1721 co = opt.(*clusterOption) 1722 } 1723 if opt.IsClusterPermsChange() { 1724 reloadClusterPerms = true 1725 } 1726 if opt.IsJetStreamChange() { 1727 reloadJetstream = true 1728 jsEnabled = opt.(*jetStreamOption).newValue 1729 } 1730 if opt.IsStatszChange() { 1731 isStatszChange = true 1732 } 1733 } 1734 1735 if reloadLogging { 1736 s.ConfigureLogger() 1737 } 1738 if reloadClientTrcLvl { 1739 s.reloadClientTraceLevel() 1740 } 1741 if reloadAuth { 1742 s.reloadAuthorization() 1743 } 1744 if reloadClusterPerms { 1745 s.reloadClusterPermissions(ctx.oldClusterPerms) 1746 } 1747 newOpts := s.getOpts() 1748 // If we need to reload cluster pool/per-account, then co will be not nil 1749 if co != nil { 1750 s.reloadClusterPoolAndAccounts(co, newOpts) 1751 } 1752 if reloadJetstream { 1753 if !jsEnabled { 1754 s.DisableJetStream() 1755 } else if !s.JetStreamEnabled() { 1756 if err := s.restartJetStream(); err != nil { 1757 s.Warnf("Can't start JetStream: %v", err) 1758 } 1759 } 1760 // Make sure to reset the internal loop's version of JS. 1761 s.resetInternalLoopInfo() 1762 } 1763 if isStatszChange { 1764 s.sendStatszUpdate() 1765 } 1766 1767 // For remote gateways and leafnodes, make sure that their TLS configuration 1768 // is updated (since the config is "captured" early and changes would otherwise 1769 // not be visible). 1770 if s.gateway.enabled { 1771 s.gateway.updateRemotesTLSConfig(newOpts) 1772 } 1773 if len(newOpts.LeafNode.Remotes) > 0 { 1774 s.updateRemoteLeafNodesTLSConfig(newOpts) 1775 } 1776 1777 // Always restart OCSP monitoring on reload. 1778 if err := s.reloadOCSP(); err != nil { 1779 s.Warnf("Can't restart OCSP features: %v", err) 1780 } 1781 1782 s.Noticef("Reloaded server configuration") 1783 } 1784 1785 // This will send a reset to the internal send loop. 1786 func (s *Server) resetInternalLoopInfo() { 1787 var resetCh chan struct{} 1788 s.mu.Lock() 1789 if s.sys != nil { 1790 // can't hold the lock as go routine reading it may be waiting for lock as well 1791 resetCh = s.sys.resetCh 1792 } 1793 s.mu.Unlock() 1794 1795 if resetCh != nil { 1796 resetCh <- struct{}{} 1797 } 1798 } 1799 1800 // Update all cached debug and trace settings for every client 1801 func (s *Server) reloadClientTraceLevel() { 1802 opts := s.getOpts() 1803 1804 if opts.NoLog { 1805 return 1806 } 1807 1808 // Create a list of all clients. 1809 // Update their trace level when not holding server or gateway lock 1810 1811 s.mu.Lock() 1812 clientCnt := 1 + len(s.clients) + len(s.grTmpClients) + s.numRoutes() + len(s.leafs) 1813 s.mu.Unlock() 1814 1815 s.gateway.RLock() 1816 clientCnt += len(s.gateway.in) + len(s.gateway.outo) 1817 s.gateway.RUnlock() 1818 1819 clients := make([]*client, 0, clientCnt) 1820 1821 s.mu.Lock() 1822 if s.eventsEnabled() { 1823 clients = append(clients, s.sys.client) 1824 } 1825 1826 cMaps := []map[uint64]*client{s.clients, s.grTmpClients, s.leafs} 1827 for _, m := range cMaps { 1828 for _, c := range m { 1829 clients = append(clients, c) 1830 } 1831 } 1832 s.forEachRoute(func(c *client) { 1833 clients = append(clients, c) 1834 }) 1835 s.mu.Unlock() 1836 1837 s.gateway.RLock() 1838 for _, c := range s.gateway.in { 1839 clients = append(clients, c) 1840 } 1841 clients = append(clients, s.gateway.outo...) 1842 s.gateway.RUnlock() 1843 1844 for _, c := range clients { 1845 // client.trace is commonly read while holding the lock 1846 c.mu.Lock() 1847 c.setTraceLevel() 1848 c.mu.Unlock() 1849 } 1850 } 1851 1852 // reloadAuthorization reconfigures the server authorization settings, 1853 // disconnects any clients who are no longer authorized, and removes any 1854 // unauthorized subscriptions. 1855 func (s *Server) reloadAuthorization() { 1856 // This map will contain the names of accounts that have their streams 1857 // import configuration changed. 1858 var awcsti map[string]struct{} 1859 checkJetStream := false 1860 opts := s.getOpts() 1861 s.mu.Lock() 1862 1863 deletedAccounts := make(map[string]*Account) 1864 1865 // This can not be changed for now so ok to check server's trustedKeys unlocked. 1866 // If plain configured accounts, process here. 1867 if s.trustedKeys == nil { 1868 // Make a map of the configured account names so we figure out the accounts 1869 // that should be removed later on. 1870 configAccs := make(map[string]struct{}, len(opts.Accounts)) 1871 for _, acc := range opts.Accounts { 1872 configAccs[acc.GetName()] = struct{}{} 1873 } 1874 // Now range over existing accounts and keep track of the ones deleted 1875 // so some cleanup can be made after releasing the server lock. 1876 s.accounts.Range(func(k, v interface{}) bool { 1877 an, acc := k.(string), v.(*Account) 1878 // Exclude default and system account from this test since those 1879 // may not actually be in opts.Accounts. 1880 if an == DEFAULT_GLOBAL_ACCOUNT || an == DEFAULT_SYSTEM_ACCOUNT { 1881 return true 1882 } 1883 // Check check if existing account is still in opts.Accounts. 1884 if _, ok := configAccs[an]; !ok { 1885 deletedAccounts[an] = acc 1886 s.accounts.Delete(k) 1887 } 1888 return true 1889 }) 1890 // This will update existing and add new ones. 1891 awcsti, _ = s.configureAccounts(true) 1892 s.configureAuthorization() 1893 // Double check any JetStream configs. 1894 checkJetStream = s.getJetStream() != nil 1895 } else if opts.AccountResolver != nil { 1896 s.configureResolver() 1897 if _, ok := s.accResolver.(*MemAccResolver); ok { 1898 // Check preloads so we can issue warnings etc if needed. 1899 s.checkResolvePreloads() 1900 // With a memory resolver we want to do something similar to configured accounts. 1901 // We will walk the accounts and delete them if they are no longer present via fetch. 1902 // If they are present we will force a claim update to process changes. 1903 s.accounts.Range(func(k, v interface{}) bool { 1904 acc := v.(*Account) 1905 // Skip global account. 1906 if acc == s.gacc { 1907 return true 1908 } 1909 accName := acc.GetName() 1910 // Release server lock for following actions 1911 s.mu.Unlock() 1912 accClaims, claimJWT, _ := s.fetchAccountClaims(accName) 1913 if accClaims != nil { 1914 if err := s.updateAccountWithClaimJWT(acc, claimJWT); err != nil { 1915 s.Noticef("Reloaded: deleting account [bad claims]: %q", accName) 1916 s.accounts.Delete(k) 1917 } 1918 } else { 1919 s.Noticef("Reloaded: deleting account [removed]: %q", accName) 1920 s.accounts.Delete(k) 1921 } 1922 // Regrab server lock. 1923 s.mu.Lock() 1924 return true 1925 }) 1926 } 1927 } 1928 1929 var ( 1930 cclientsa [64]*client 1931 cclients = cclientsa[:0] 1932 clientsa [64]*client 1933 clients = clientsa[:0] 1934 routesa [64]*client 1935 routes = routesa[:0] 1936 ) 1937 1938 // Gather clients that changed accounts. We will close them and they 1939 // will reconnect, doing the right thing. 1940 for _, client := range s.clients { 1941 if s.clientHasMovedToDifferentAccount(client) { 1942 cclients = append(cclients, client) 1943 } else { 1944 clients = append(clients, client) 1945 } 1946 } 1947 s.forEachRoute(func(route *client) { 1948 routes = append(routes, route) 1949 }) 1950 // Check here for any system/internal clients which will not be in the servers map of normal clients. 1951 if s.sys != nil && s.sys.account != nil && !opts.NoSystemAccount { 1952 s.accounts.Store(s.sys.account.Name, s.sys.account) 1953 } 1954 1955 s.accounts.Range(func(k, v interface{}) bool { 1956 acc := v.(*Account) 1957 acc.mu.RLock() 1958 // Check for sysclients accounting, ignore the system account. 1959 if acc.sysclients > 0 && (s.sys == nil || s.sys.account != acc) { 1960 for c := range acc.clients { 1961 if c.kind != CLIENT && c.kind != LEAF { 1962 clients = append(clients, c) 1963 } 1964 } 1965 } 1966 acc.mu.RUnlock() 1967 return true 1968 }) 1969 1970 var resetCh chan struct{} 1971 if s.sys != nil { 1972 // can't hold the lock as go routine reading it may be waiting for lock as well 1973 resetCh = s.sys.resetCh 1974 } 1975 s.mu.Unlock() 1976 1977 // Clear some timers and remove service import subs for deleted accounts. 1978 for _, acc := range deletedAccounts { 1979 acc.mu.Lock() 1980 clearTimer(&acc.etmr) 1981 clearTimer(&acc.ctmr) 1982 for _, se := range acc.exports.services { 1983 se.clearResponseThresholdTimer() 1984 } 1985 acc.mu.Unlock() 1986 acc.removeAllServiceImportSubs() 1987 } 1988 1989 if resetCh != nil { 1990 resetCh <- struct{}{} 1991 } 1992 1993 // Check that publish retained messages sources are still allowed to publish. 1994 s.mqttCheckPubRetainedPerms() 1995 1996 // Close clients that have moved accounts 1997 for _, client := range cclients { 1998 client.closeConnection(ClientClosed) 1999 } 2000 2001 for _, c := range clients { 2002 // Disconnect any unauthorized clients. 2003 // Ignore internal clients. 2004 if (c.kind == CLIENT || c.kind == LEAF) && !s.isClientAuthorized(c) { 2005 c.authViolation() 2006 continue 2007 } 2008 // Check to make sure account is correct. 2009 c.swapAccountAfterReload() 2010 // Remove any unauthorized subscriptions and check for account imports. 2011 c.processSubsOnConfigReload(awcsti) 2012 } 2013 2014 for _, route := range routes { 2015 // Disconnect any unauthorized routes. 2016 // Do this only for routes that were accepted, not initiated 2017 // because in the later case, we don't have the user name/password 2018 // of the remote server. 2019 if !route.isSolicitedRoute() && !s.isRouterAuthorized(route) { 2020 route.setNoReconnect() 2021 route.authViolation() 2022 } 2023 } 2024 2025 if res := s.AccountResolver(); res != nil { 2026 res.Reload() 2027 } 2028 2029 // We will double check all JetStream configs on a reload. 2030 if checkJetStream { 2031 if err := s.enableJetStreamAccounts(); err != nil { 2032 s.Errorf(err.Error()) 2033 } 2034 } 2035 } 2036 2037 // Returns true if given client current account has changed (or user 2038 // no longer exist) in the new config, false if the user did not 2039 // change accounts. 2040 // Server lock is held on entry. 2041 func (s *Server) clientHasMovedToDifferentAccount(c *client) bool { 2042 var ( 2043 nu *NkeyUser 2044 u *User 2045 ) 2046 c.mu.Lock() 2047 defer c.mu.Unlock() 2048 if c.opts.Nkey != _EMPTY_ { 2049 if s.nkeys != nil { 2050 nu = s.nkeys[c.opts.Nkey] 2051 } 2052 } else if c.opts.Username != _EMPTY_ { 2053 if s.users != nil { 2054 u = s.users[c.opts.Username] 2055 } 2056 } else { 2057 return false 2058 } 2059 // Get the current account name 2060 var curAccName string 2061 if c.acc != nil { 2062 curAccName = c.acc.Name 2063 } 2064 if nu != nil && nu.Account != nil { 2065 return curAccName != nu.Account.Name 2066 } else if u != nil && u.Account != nil { 2067 return curAccName != u.Account.Name 2068 } 2069 // user/nkey no longer exists. 2070 return true 2071 } 2072 2073 // reloadClusterPermissions reconfigures the cluster's permssions 2074 // and set the permissions to all existing routes, sending an 2075 // update INFO protocol so that remote can resend their local 2076 // subs if needed, and sending local subs matching cluster's 2077 // import subjects. 2078 func (s *Server) reloadClusterPermissions(oldPerms *RoutePermissions) { 2079 s.mu.Lock() 2080 newPerms := s.getOpts().Cluster.Permissions 2081 routes := make(map[uint64]*client, s.numRoutes()) 2082 // Get all connected routes 2083 s.forEachRoute(func(route *client) { 2084 route.mu.Lock() 2085 routes[route.cid] = route 2086 route.mu.Unlock() 2087 }) 2088 // If new permissions is nil, then clear routeInfo import/export 2089 if newPerms == nil { 2090 s.routeInfo.Import = nil 2091 s.routeInfo.Export = nil 2092 } else { 2093 s.routeInfo.Import = newPerms.Import 2094 s.routeInfo.Export = newPerms.Export 2095 } 2096 infoJSON := generateInfoJSON(&s.routeInfo) 2097 s.mu.Unlock() 2098 2099 // Close connections for routes that don't understand async INFO. 2100 for _, route := range routes { 2101 route.mu.Lock() 2102 close := route.opts.Protocol < RouteProtoInfo 2103 cid := route.cid 2104 route.mu.Unlock() 2105 if close { 2106 route.closeConnection(RouteRemoved) 2107 delete(routes, cid) 2108 } 2109 } 2110 2111 // If there are no route left, we are done 2112 if len(routes) == 0 { 2113 return 2114 } 2115 2116 // Fake clients to test cluster permissions 2117 oldPermsTester := &client{} 2118 oldPermsTester.setRoutePermissions(oldPerms) 2119 newPermsTester := &client{} 2120 newPermsTester.setRoutePermissions(newPerms) 2121 2122 var ( 2123 _localSubs [4096]*subscription 2124 subsNeedSUB = map[*client][]*subscription{} 2125 subsNeedUNSUB = map[*client][]*subscription{} 2126 deleteRoutedSubs []*subscription 2127 ) 2128 2129 getRouteForAccount := func(accName string, poolIdx int) *client { 2130 for _, r := range routes { 2131 r.mu.Lock() 2132 ok := (poolIdx >= 0 && poolIdx == r.route.poolIdx) || (string(r.route.accName) == accName) || r.route.noPool 2133 r.mu.Unlock() 2134 if ok { 2135 return r 2136 } 2137 } 2138 return nil 2139 } 2140 2141 // First set the new permissions on all routes. 2142 for _, route := range routes { 2143 route.mu.Lock() 2144 route.setRoutePermissions(newPerms) 2145 route.mu.Unlock() 2146 } 2147 2148 // Then, go over all accounts and gather local subscriptions that need to be 2149 // sent over as SUB or removed as UNSUB, and routed subscriptions that need 2150 // to be dropped due to export permissions. 2151 s.accounts.Range(func(_, v interface{}) bool { 2152 acc := v.(*Account) 2153 acc.mu.RLock() 2154 accName, sl, poolIdx := acc.Name, acc.sl, acc.routePoolIdx 2155 acc.mu.RUnlock() 2156 // Get the route handling this account. If no route or sublist, bail out. 2157 route := getRouteForAccount(accName, poolIdx) 2158 if route == nil || sl == nil { 2159 return true 2160 } 2161 localSubs := _localSubs[:0] 2162 sl.localSubs(&localSubs, false) 2163 2164 // Go through all local subscriptions 2165 for _, sub := range localSubs { 2166 // Get all subs that can now be imported 2167 subj := string(sub.subject) 2168 couldImportThen := oldPermsTester.canImport(subj) 2169 canImportNow := newPermsTester.canImport(subj) 2170 if canImportNow { 2171 // If we could not before, then will need to send a SUB protocol. 2172 if !couldImportThen { 2173 subsNeedSUB[route] = append(subsNeedSUB[route], sub) 2174 } 2175 } else if couldImportThen { 2176 // We were previously able to import this sub, but now 2177 // we can't so we need to send an UNSUB protocol 2178 subsNeedUNSUB[route] = append(subsNeedUNSUB[route], sub) 2179 } 2180 } 2181 deleteRoutedSubs = deleteRoutedSubs[:0] 2182 route.mu.Lock() 2183 for key, sub := range route.subs { 2184 if an := strings.Fields(key)[0]; an != accName { 2185 continue 2186 } 2187 // If we can't export, we need to drop the subscriptions that 2188 // we have on behalf of this route. 2189 subj := string(sub.subject) 2190 if !route.canExport(subj) { 2191 delete(route.subs, string(sub.sid)) 2192 deleteRoutedSubs = append(deleteRoutedSubs, sub) 2193 } 2194 } 2195 route.mu.Unlock() 2196 // Remove as a batch all the subs that we have removed from each route. 2197 sl.RemoveBatch(deleteRoutedSubs) 2198 return true 2199 }) 2200 2201 // Send an update INFO, which will allow remote server to show 2202 // our current route config in monitoring and resend subscriptions 2203 // that we now possibly allow with a change of Export permissions. 2204 for _, route := range routes { 2205 route.mu.Lock() 2206 route.enqueueProto(infoJSON) 2207 // Now send SUB and UNSUB protocols as needed. 2208 if subs, ok := subsNeedSUB[route]; ok && len(subs) > 0 { 2209 route.sendRouteSubProtos(subs, false, nil) 2210 } 2211 if unsubs, ok := subsNeedUNSUB[route]; ok && len(unsubs) > 0 { 2212 route.sendRouteUnSubProtos(unsubs, false, nil) 2213 } 2214 route.mu.Unlock() 2215 } 2216 } 2217 2218 func (s *Server) reloadClusterPoolAndAccounts(co *clusterOption, opts *Options) { 2219 s.mu.Lock() 2220 // Prevent adding new routes until we are ready to do so. 2221 s.routesReject = true 2222 var ch chan struct{} 2223 // For accounts that have been added to the list of dedicated routes, 2224 // send a protocol to their current assigned routes to allow the 2225 // other side to prepare for the changes. 2226 if len(co.accsAdded) > 0 { 2227 protosSent := 0 2228 s.accAddedReqID = nuid.Next() 2229 for _, an := range co.accsAdded { 2230 if s.accRoutes == nil { 2231 s.accRoutes = make(map[string]map[string]*client) 2232 } 2233 // In case a config reload was first done on another server, 2234 // we may have already switched this account to a dedicated route. 2235 // But we still want to send the protocol over the routes that 2236 // would have otherwise handled it. 2237 if _, ok := s.accRoutes[an]; !ok { 2238 s.accRoutes[an] = make(map[string]*client) 2239 } 2240 if a, ok := s.accounts.Load(an); ok { 2241 acc := a.(*Account) 2242 acc.mu.Lock() 2243 sl := acc.sl 2244 // Get the current route pool index before calling setRouteInfo. 2245 rpi := acc.routePoolIdx 2246 // Switch to per-account route if not already done. 2247 if rpi >= 0 { 2248 s.setRouteInfo(acc) 2249 } else { 2250 // If it was transitioning, make sure we set it to the state 2251 // that indicates that it has a dedicated route 2252 if rpi == accTransitioningToDedicatedRoute { 2253 acc.routePoolIdx = accDedicatedRoute 2254 } 2255 // Otherwise get the route pool index it would have been before 2256 // the move so we can send the protocol to those routes. 2257 rpi = s.computeRoutePoolIdx(acc) 2258 } 2259 acc.mu.Unlock() 2260 // Generate the INFO protocol to send indicating that this account 2261 // is being moved to a dedicated route. 2262 ri := Info{ 2263 RoutePoolSize: s.routesPoolSize, 2264 RouteAccount: an, 2265 RouteAccReqID: s.accAddedReqID, 2266 } 2267 proto := generateInfoJSON(&ri) 2268 // Go over each remote's route at pool index `rpi` and remove 2269 // remote subs for this account and send the protocol. 2270 s.forEachRouteIdx(rpi, func(r *client) bool { 2271 r.mu.Lock() 2272 // Exclude routes to servers that don't support pooling. 2273 if !r.route.noPool { 2274 if subs := r.removeRemoteSubsForAcc(an); len(subs) > 0 { 2275 sl.RemoveBatch(subs) 2276 } 2277 r.enqueueProto(proto) 2278 protosSent++ 2279 } 2280 r.mu.Unlock() 2281 return true 2282 }) 2283 } 2284 } 2285 if protosSent > 0 { 2286 s.accAddedCh = make(chan struct{}, protosSent) 2287 ch = s.accAddedCh 2288 } 2289 } 2290 // Collect routes that need to be closed. 2291 routes := make(map[*client]struct{}) 2292 // Collect the per-account routes that need to be closed. 2293 if len(co.accsRemoved) > 0 { 2294 for _, an := range co.accsRemoved { 2295 if remotes, ok := s.accRoutes[an]; ok && remotes != nil { 2296 for _, r := range remotes { 2297 if r != nil { 2298 r.setNoReconnect() 2299 routes[r] = struct{}{} 2300 } 2301 } 2302 } 2303 } 2304 } 2305 // If the pool size has changed, we need to close all pooled routes. 2306 if co.poolSizeChanged { 2307 s.forEachNonPerAccountRoute(func(r *client) { 2308 routes[r] = struct{}{} 2309 }) 2310 } 2311 // If there are routes to close, we need to release the server lock. 2312 // Same if we need to wait on responses from the remotes when 2313 // processing new per-account routes. 2314 if len(routes) > 0 || len(ch) > 0 { 2315 s.mu.Unlock() 2316 2317 for done := false; !done && len(ch) > 0; { 2318 select { 2319 case <-ch: 2320 case <-time.After(2 * time.Second): 2321 s.Warnf("Timed out waiting for confirmation from all routes regarding per-account routes changes") 2322 done = true 2323 } 2324 } 2325 2326 for r := range routes { 2327 r.closeConnection(RouteRemoved) 2328 } 2329 2330 s.mu.Lock() 2331 } 2332 // Clear the accAddedCh/ReqID fields in case they were set. 2333 s.accAddedReqID, s.accAddedCh = _EMPTY_, nil 2334 // Now that per-account routes that needed to be closed are closed, 2335 // remove them from s.accRoutes. Doing so before would prevent 2336 // removeRoute() to do proper cleanup because the route would not 2337 // be found in s.accRoutes. 2338 for _, an := range co.accsRemoved { 2339 delete(s.accRoutes, an) 2340 // Do not lookup and call setRouteInfo() on the accounts here. 2341 // We need first to set the new s.routesPoolSize value and 2342 // anyway, there is no need to do here if the pool size has 2343 // changed (since it will be called for all accounts). 2344 } 2345 // We have already added the accounts to s.accRoutes that needed to 2346 // be added. 2347 2348 // We should always have at least the system account with a dedicated route, 2349 // but in case we have a configuration that disables pooling and without 2350 // a system account, possibly set the accRoutes to nil. 2351 if len(opts.Cluster.PinnedAccounts) == 0 { 2352 s.accRoutes = nil 2353 } 2354 // Now deal with pool size updates. 2355 if ps := opts.Cluster.PoolSize; ps > 0 { 2356 s.routesPoolSize = ps 2357 s.routeInfo.RoutePoolSize = ps 2358 } else { 2359 s.routesPoolSize = 1 2360 s.routeInfo.RoutePoolSize = 0 2361 } 2362 // If the pool size has changed, we need to recompute all accounts' route 2363 // pool index. Note that the added/removed accounts will be reset there 2364 // too, but that's ok (we could use a map to exclude them, but not worth it). 2365 if co.poolSizeChanged { 2366 s.accounts.Range(func(_, v interface{}) bool { 2367 acc := v.(*Account) 2368 acc.mu.Lock() 2369 s.setRouteInfo(acc) 2370 acc.mu.Unlock() 2371 return true 2372 }) 2373 } else if len(co.accsRemoved) > 0 { 2374 // For accounts that no longer have a dedicated route, we need to send 2375 // the subsriptions on the existing pooled routes for those accounts. 2376 for _, an := range co.accsRemoved { 2377 if a, ok := s.accounts.Load(an); ok { 2378 acc := a.(*Account) 2379 acc.mu.Lock() 2380 // First call this which will assign a new route pool index. 2381 s.setRouteInfo(acc) 2382 // Get the value so we can send the subscriptions interest 2383 // on all routes with this pool index. 2384 rpi := acc.routePoolIdx 2385 acc.mu.Unlock() 2386 s.forEachRouteIdx(rpi, func(r *client) bool { 2387 // We have the guarantee that if the route exists, it 2388 // is not a new one that would have been created when 2389 // we released the server lock if some routes needed 2390 // to be closed, because we have set s.routesReject 2391 // to `true` at the top of this function. 2392 s.sendSubsToRoute(r, rpi, an) 2393 return true 2394 }) 2395 } 2396 } 2397 } 2398 // Allow routes to be accepted now. 2399 s.routesReject = false 2400 // If there is a pool size change or added accounts, solicit routes now. 2401 if co.poolSizeChanged || len(co.accsAdded) > 0 { 2402 s.solicitRoutes(opts.Routes, co.accsAdded) 2403 } 2404 s.mu.Unlock() 2405 } 2406 2407 // validateClusterOpts ensures the new ClusterOpts does not change some of the 2408 // fields that do not support reload. 2409 func validateClusterOpts(old, new ClusterOpts) error { 2410 if old.Host != new.Host { 2411 return fmt.Errorf("config reload not supported for cluster host: old=%s, new=%s", 2412 old.Host, new.Host) 2413 } 2414 if old.Port != new.Port { 2415 return fmt.Errorf("config reload not supported for cluster port: old=%d, new=%d", 2416 old.Port, new.Port) 2417 } 2418 // Validate Cluster.Advertise syntax 2419 if new.Advertise != "" { 2420 if _, _, err := parseHostPort(new.Advertise, 0); err != nil { 2421 return fmt.Errorf("invalid Cluster.Advertise value of %s, err=%v", new.Advertise, err) 2422 } 2423 } 2424 return nil 2425 } 2426 2427 // diffRoutes diffs the old routes and the new routes and returns the ones that 2428 // should be added and removed from the server. 2429 func diffRoutes(old, new []*url.URL) (add, remove []*url.URL) { 2430 // Find routes to remove. 2431 removeLoop: 2432 for _, oldRoute := range old { 2433 for _, newRoute := range new { 2434 if urlsAreEqual(oldRoute, newRoute) { 2435 continue removeLoop 2436 } 2437 } 2438 remove = append(remove, oldRoute) 2439 } 2440 2441 // Find routes to add. 2442 addLoop: 2443 for _, newRoute := range new { 2444 for _, oldRoute := range old { 2445 if urlsAreEqual(oldRoute, newRoute) { 2446 continue addLoop 2447 } 2448 } 2449 add = append(add, newRoute) 2450 } 2451 2452 return add, remove 2453 }