Skip to content

Commit

Permalink
Cherry picks for v2.10.19 RC5 (#5823)
Browse files Browse the repository at this point in the history
Includes:

  - #5782
  - #5785
  - #5757
  - #5789
  - #5790
  - #5793
  - #5794
  - #5809
  - #5812
  - #5816
  - #5819
  - #5818
  • Loading branch information
wallyqs authored Aug 23, 2024
2 parents 31a8dbf + 05b2ae6 commit 26c8196
Show file tree
Hide file tree
Showing 28 changed files with 761 additions and 299 deletions.
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/nats-io/nkeys v0.4.7
github.com/nats-io/nuid v1.0.1
go.uber.org/automaxprocs v1.5.3
golang.org/x/crypto v0.25.0
golang.org/x/sys v0.23.0
golang.org/x/crypto v0.26.0
golang.org/x/sys v0.24.0
golang.org/x/time v0.6.0
)
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,15 @@ go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
Expand Down
5 changes: 3 additions & 2 deletions internal/ocsp/ocsp.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,9 @@ func NewOCSPResponderBase(t *testing.T, issuerCertPEM, respCertPEM, respKeyPEM s
})

srv := &http.Server{
Addr: addr,
Handler: mux,
Addr: addr,
Handler: mux,
ReadTimeout: time.Second * 5,
}
go srv.ListenAndServe()
time.Sleep(1 * time.Second)
Expand Down
15 changes: 6 additions & 9 deletions server/accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package server

import (
"bytes"
"cmp"
"encoding/hex"
"errors"
"fmt"
Expand All @@ -25,7 +26,7 @@ import (
"net/http"
"net/textproto"
"reflect"
"sort"
"slices"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -349,10 +350,8 @@ func (a *Account) updateRemoteServer(m *AccountNumConns) []*client {
// conservative and bit harsh here. Clients will reconnect if we over compensate.
var clients []*client
if mtce {
clients := a.getClientsLocked()
sort.Slice(clients, func(i, j int) bool {
return clients[i].start.After(clients[j].start)
})
clients = a.getClientsLocked()
slices.SortFunc(clients, func(i, j *client) int { return -i.start.Compare(j.start) }) // reserve
over := (len(a.clients) - int(a.sysclients) + int(a.nrclients)) - int(a.mconns)
if over < len(clients) {
clients = clients[:over]
Expand Down Expand Up @@ -669,7 +668,7 @@ func (a *Account) AddWeightedMappings(src string, dests ...*MapDest) error {
}
dests = append(dests, &destination{tr, aw})
}
sort.Slice(dests, func(i, j int) bool { return dests[i].weight < dests[j].weight })
slices.SortFunc(dests, func(i, j *destination) int { return cmp.Compare(i.weight, j.weight) })

var lw uint8
for _, d := range dests {
Expand Down Expand Up @@ -3567,9 +3566,7 @@ func (s *Server) updateAccountClaimsWithRefresh(a *Account, ac *jwt.AccountClaim

// Sort if we are over the limit.
if a.MaxTotalConnectionsReached() {
sort.Slice(clients, func(i, j int) bool {
return clients[i].start.After(clients[j].start)
})
slices.SortFunc(clients, func(i, j *client) int { return -i.start.Compare(j.start) }) // sort in reverse order
}

// If JetStream is enabled for this server we will call into configJetStream for the account
Expand Down
57 changes: 30 additions & 27 deletions server/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -857,33 +857,6 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) (au
// If we have a jwt and a userClaim, make sure we have the Account, etc associated.
// We need to look up the account. This will use an account resolver if one is present.
if juc != nil {
allowedConnTypes, err := convertAllowedConnectionTypes(juc.AllowedConnectionTypes)
if err != nil {
// We got an error, which means some connection types were unknown. As long as
// a valid one is returned, we proceed with auth. If not, we have to reject.
// In other words, suppose that JWT allows "WEBSOCKET" in the array. No error
// is returned and allowedConnTypes will contain "WEBSOCKET" only.
// Client will be rejected if not a websocket client, or proceed with rest of
// auth if it is.
// Now suppose JWT allows "WEBSOCKET, MQTT" and say MQTT is not known by this
// server. In this case, allowedConnTypes would contain "WEBSOCKET" and we
// would get `err` indicating that "MQTT" is an unknown connection type.
// If a websocket client connects, it should still be allowed, since after all
// the admin wanted to allow websocket and mqtt connection types.
// However, say that the JWT only allows "MQTT" (and again suppose this server
// does not know about MQTT connection type), then since the allowedConnTypes
// map would be empty (no valid types found), and since empty means allow-all,
// then we should reject because the intent was to allow connections for this
// user only as an MQTT client.
c.Debugf("%v", err)
if len(allowedConnTypes) == 0 {
return false
}
}
if !c.connectionTypeAllowed(allowedConnTypes) {
c.Debugf("Connection type not allowed")
return false
}
issuer := juc.Issuer
if juc.IssuerAccount != _EMPTY_ {
issuer = juc.IssuerAccount
Expand Down Expand Up @@ -926,6 +899,36 @@ func (s *Server) processClientOrLeafAuthentication(c *client, opts *Options) (au
c.Debugf("Account does not allow bearer tokens")
return false
}
// We check the allowed connection types, but only after processing
// of scoped signer (so that it updates `juc` with what is defined
// in the account.
allowedConnTypes, err := convertAllowedConnectionTypes(juc.AllowedConnectionTypes)
if err != nil {
// We got an error, which means some connection types were unknown. As long as
// a valid one is returned, we proceed with auth. If not, we have to reject.
// In other words, suppose that JWT allows "WEBSOCKET" in the array. No error
// is returned and allowedConnTypes will contain "WEBSOCKET" only.
// Client will be rejected if not a websocket client, or proceed with rest of
// auth if it is.
// Now suppose JWT allows "WEBSOCKET, MQTT" and say MQTT is not known by this
// server. In this case, allowedConnTypes would contain "WEBSOCKET" and we
// would get `err` indicating that "MQTT" is an unknown connection type.
// If a websocket client connects, it should still be allowed, since after all
// the admin wanted to allow websocket and mqtt connection types.
// However, say that the JWT only allows "MQTT" (and again suppose this server
// does not know about MQTT connection type), then since the allowedConnTypes
// map would be empty (no valid types found), and since empty means allow-all,
// then we should reject because the intent was to allow connections for this
// user only as an MQTT client.
c.Debugf("%v", err)
if len(allowedConnTypes) == 0 {
return false
}
}
if !c.connectionTypeAllowed(allowedConnTypes) {
c.Debugf("Connection type not allowed")
return false
}
// skip validation of nonce when presented with a bearer token
// FIXME: if BearerToken is only for WSS, need check for server with that port enabled
if !juc.BearerToken {
Expand Down
10 changes: 5 additions & 5 deletions server/auth_callout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
"fmt"
"os"
"reflect"
"sort"
"slices"
"strings"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -709,9 +709,9 @@ func TestAuthCalloutOperatorModeBasics(t *testing.T) {
t.Fatalf("Expected to be switched to %q, but got %q", tpub, userInfo.Account)
}
require_True(t, len(userInfo.Permissions.Publish.Allow) == 2)
sort.Strings(userInfo.Permissions.Publish.Allow)
slices.Sort(userInfo.Permissions.Publish.Allow)
require_Equal(t, "foo.>", userInfo.Permissions.Publish.Allow[1])
sort.Strings(userInfo.Permissions.Subscribe.Allow)
slices.Sort(userInfo.Permissions.Subscribe.Allow)
require_True(t, len(userInfo.Permissions.Subscribe.Allow) == 2)
require_Equal(t, "foo.>", userInfo.Permissions.Subscribe.Allow[1])
}
Expand Down Expand Up @@ -834,9 +834,9 @@ func testAuthCalloutScopedUser(t *testing.T, allowAnyAccount bool) {
t.Fatalf("Expected to be switched to %q, but got %q", tpub, userInfo.Account)
}
require_True(t, len(userInfo.Permissions.Publish.Allow) == 2)
sort.Strings(userInfo.Permissions.Publish.Allow)
slices.Sort(userInfo.Permissions.Publish.Allow)
require_Equal(t, "foo.>", userInfo.Permissions.Publish.Allow[1])
sort.Strings(userInfo.Permissions.Subscribe.Allow)
slices.Sort(userInfo.Permissions.Subscribe.Allow)
require_True(t, len(userInfo.Permissions.Subscribe.Allow) == 2)
require_Equal(t, "foo.>", userInfo.Permissions.Subscribe.Allow[1])

Expand Down
5 changes: 3 additions & 2 deletions server/avl/seqset.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
package avl

import (
"cmp"
"encoding/binary"
"errors"
"math/bits"
"sort"
"slices"
)

// SequenceSet is a memory and encoding optimized set for storing unsigned ints.
Expand Down Expand Up @@ -209,7 +210,7 @@ func Union(ssa ...*SequenceSet) *SequenceSet {
return nil
}
// Sort so we can clone largest.
sort.Slice(ssa, func(i, j int) bool { return ssa[i].Size() > ssa[j].Size() })
slices.SortFunc(ssa, func(i, j *SequenceSet) int { return -cmp.Compare(i.Size(), j.Size()) }) // reverse order
ss := ssa[0].Clone()

// Insert the rest through range call.
Expand Down
8 changes: 8 additions & 0 deletions server/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -5857,6 +5857,14 @@ func (c *client) Warnf(format string, v ...any) {
c.srv.Warnf(format, v...)
}

func (c *client) rateLimitFormatWarnf(format string, v ...any) {
if _, loaded := c.srv.rateLimitLogging.LoadOrStore(format, time.Now()); loaded {
return
}
statement := fmt.Sprintf(format, v...)
c.Warnf("%s", statement)
}

func (c *client) RateLimitWarnf(format string, v ...any) {
// Do the check before adding the client info to the format...
statement := fmt.Sprintf(format, v...)
Expand Down
Loading

0 comments on commit 26c8196

Please sign in to comment.