From 9a43019c8a6b2376e9f846dfe860faaa2eb293ef Mon Sep 17 00:00:00 2001 From: Edoardo Spadolini Date: Wed, 20 Nov 2024 17:02:45 +0100 Subject: [PATCH 1/3] Get rid of math/rand in favor of math/rand/v2 --- .golangci.yml | 2 ++ .../dynamoathenamigration/migration_test.go | 17 ++++++----------- examples/teleport-usage/main.go | 4 ++-- integrations/lib/backoff/backoff.go | 4 ++-- .../controllers/resources/testlib/env.go | 9 ++++----- lib/auth/accountrecovery_test.go | 2 +- lib/auth/auth.go | 13 ++++++------- lib/auth/keystore/gcp_kms_test.go | 8 ++++---- lib/auth/kube_test.go | 6 ++---- lib/auth/password_test.go | 2 +- lib/auth/trustedcluster_test.go | 13 +++++-------- lib/auth/usertoken_test.go | 2 +- lib/benchmark/ssh.go | 4 ++-- lib/events/dynamoevents/dynamoevents_test.go | 9 ++++----- lib/events/export/date_exporter_test.go | 10 +++++----- lib/kube/proxy/transport.go | 11 ++++------- lib/proxy/router_test.go | 2 +- lib/resumption/handover_test.go | 6 +++--- lib/reversetunnel/track/tracker_test.go | 17 ++++++----------- lib/services/fanoutv2_test.go | 4 ++-- lib/srv/db/proxyserver.go | 12 +++++------- lib/sshutils/sftp/sftp_test.go | 11 ++++++----- lib/utils/concurrentqueue/queue_test.go | 4 ++-- lib/utils/loadbalancer.go | 4 ++-- lib/utils/utils.go | 4 ++-- lib/web/app/match.go | 2 +- lib/web/desktop.go | 2 +- .../sso/configure/flags/file_reader_test.go | 9 +++------ 28 files changed, 85 insertions(+), 108 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 4298cda741594..30bbb975728ff 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -89,6 +89,8 @@ linters-settings: deny: - pkg: io/ioutil desc: 'use "io" or "os" packages instead' + - pkg: math/rand$ + desc: 'use "math/rand/v2" or "crypto/rand" instead' - pkg: github.com/golang/protobuf desc: 'use "google.golang.org/protobuf"' - pkg: github.com/hashicorp/go-uuid diff --git a/examples/dynamoathenamigration/migration_test.go b/examples/dynamoathenamigration/migration_test.go index 1b682cca53e29..40aca246a9b43 100644 --- a/examples/dynamoathenamigration/migration_test.go +++ b/examples/dynamoathenamigration/migration_test.go @@ -22,7 +22,7 @@ import ( "errors" "fmt" "io" - "math/rand" + "math/rand/v2" "os" "path/filepath" "sort" @@ -39,6 +39,7 @@ import ( apievents "github.com/gravitational/teleport/api/types/events" "github.com/gravitational/teleport/api/utils/prompt" + "github.com/gravitational/teleport/api/utils/retryutils" "github.com/gravitational/teleport/lib/utils" ) @@ -190,7 +191,7 @@ func (m *mockEmitter) EmitAuditEvent(ctx context.Context, in apievents.AuditEven // Without it, in rare cases after 50 events still some worker were not able // to read message because of other processing it immediately. select { - case <-time.After(time.Duration(rand.Intn(50)+50) * time.Microsecond): + case <-time.After(retryutils.HalfJitter(100 * time.Microsecond)): return nil case <-ctx.Done(): return ctx.Err() @@ -695,8 +696,6 @@ func generateExportFilesFromLines(t *testing.T, lines []string) (file *os.File, } func generateExportFileOfSize(t *testing.T, wantSize int, minDate, maxDate string) (*os.File, int) { - rnd := rand.New(rand.NewSource(time.Now().UnixNano())) - f, err := os.CreateTemp(t.TempDir(), "*") require.NoError(t, err) require.NoError(t, err) @@ -705,7 +704,7 @@ func generateExportFileOfSize(t *testing.T, wantSize int, minDate, maxDate strin var noOfEvents, size int for size < wantSize { noOfEvents++ - line := eventLineFromTime(randomTime(t, minDate, maxDate, rnd).Format(time.DateOnly)) + line := eventLineFromTime(randomTime(t, minDate, maxDate).Format(time.DateOnly)) size += len(line) _, err = zw.Write([]byte(line + "\n")) require.NoError(t, err) @@ -717,16 +716,12 @@ func generateExportFileOfSize(t *testing.T, wantSize int, minDate, maxDate strin return f, noOfEvents } -func randomTime(t *testing.T, minStr, maxStr string, rnd *rand.Rand) time.Time { +func randomTime(t *testing.T, minStr, maxStr string) time.Time { min, err := time.Parse(time.DateOnly, minStr) require.NoError(t, err) max, err := time.Parse(time.DateOnly, maxStr) require.NoError(t, err) - minUnix := min.Unix() - maxUnix := max.Unix() - delta := maxUnix - minUnix - sec := rnd.Int63n(delta) + minUnix - return time.Unix(sec, 0) + return min.Add(rand.N(max.Sub(min))) } func eventLineFromTime(eventTime string) string { diff --git a/examples/teleport-usage/main.go b/examples/teleport-usage/main.go index c58fbac748e0f..0e9a12a5720d3 100644 --- a/examples/teleport-usage/main.go +++ b/examples/teleport-usage/main.go @@ -22,7 +22,7 @@ import ( "fmt" "log" "math" - "math/rand" + "math/rand/v2" "os" "reflect" "strconv" @@ -334,7 +334,7 @@ func (a *adaptiveRateLimiter) wait(permits float64) { durationToWait := time.Duration(permits / a.permitCapacity * float64(time.Second)) time.Sleep(durationToWait) - if rand.Intn(10) == 0 { + if rand.N(10) == 0 { a.adjustUp() } } diff --git a/integrations/lib/backoff/backoff.go b/integrations/lib/backoff/backoff.go index 92ad845626308..e563486879f55 100644 --- a/integrations/lib/backoff/backoff.go +++ b/integrations/lib/backoff/backoff.go @@ -20,7 +20,7 @@ package backoff import ( "context" - "math/rand" + "math/rand/v2" "time" "github.com/gravitational/trace" @@ -58,7 +58,7 @@ func NewDecorrWithMul(base, cap time.Duration, mul int64, clock clockwork.Clock) } func (backoff *decorr) Do(ctx context.Context) error { - backoff.sleep = backoff.base + rand.Int63n(backoff.sleep*backoff.mul-backoff.base) + backoff.sleep = backoff.base + rand.N(backoff.sleep*backoff.mul-backoff.base) if backoff.sleep > backoff.cap { backoff.sleep = backoff.cap } diff --git a/integrations/operator/controllers/resources/testlib/env.go b/integrations/operator/controllers/resources/testlib/env.go index 4f35bcff10c60..df04115401b59 100644 --- a/integrations/operator/controllers/resources/testlib/env.go +++ b/integrations/operator/controllers/resources/testlib/env.go @@ -20,7 +20,7 @@ package testlib import ( "context" - "math/rand" + "math/rand/v2" "os" "path/filepath" "runtime" @@ -88,12 +88,11 @@ func deleteNamespaceForTest(t *testing.T, kc kclient.Client, ns *core.Namespace) require.NoError(t, err) } -var letterRunes = []rune("abcdefghijklmnopqrstuvwxyz1234567890") - func ValidRandomResourceName(prefix string) string { - b := make([]rune, 5) + const letters = "abcdefghijklmnopqrstuvwxyz1234567890" + b := make([]byte, 5) for i := range b { - b[i] = letterRunes[rand.Intn(len(letterRunes))] + b[i] = letters[rand.N(len(letters))] } return prefix + string(b) } diff --git a/lib/auth/accountrecovery_test.go b/lib/auth/accountrecovery_test.go index be0312661e2c6..1b53462c410cd 100644 --- a/lib/auth/accountrecovery_test.go +++ b/lib/auth/accountrecovery_test.go @@ -23,7 +23,7 @@ import ( "encoding/binary" "encoding/hex" "fmt" - "math/rand" + "math/rand/v2" "net/netip" "strings" "testing" diff --git a/lib/auth/auth.go b/lib/auth/auth.go index b9d91381cd51c..48d645b1b6cd7 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -38,7 +38,7 @@ import ( "io" "log/slog" "math/big" - insecurerand "math/rand" + mathrand "math/rand/v2" "net" "os" "regexp" @@ -1334,8 +1334,7 @@ func (a *Server) runPeriodicOperations() { // to avoid contention on the database in case if there are multiple // auth servers running - so they don't compete trying // to update the same resources. - r := insecurerand.New(insecurerand.NewSource(a.GetClock().Now().UnixNano())) - period := defaults.HighResPollingPeriod + time.Duration(r.Intn(int(defaults.HighResPollingPeriod/time.Second)))*time.Second + period := retryutils.HalfJitter(2 * defaults.HighResPollingPeriod) ticker := interval.NewMulti( a.GetClock(), @@ -1430,7 +1429,7 @@ func (a *Server) runPeriodicOperations() { case <-a.closeCtx.Done(): return case <-remoteClustersRefresh.Next(): - a.refreshRemoteClusters(a.closeCtx, r) + a.refreshRemoteClusters(a.closeCtx) } } }() @@ -1859,7 +1858,7 @@ var ( ) // refreshRemoteClusters updates connection status of all remote clusters. -func (a *Server) refreshRemoteClusters(ctx context.Context, rnd *insecurerand.Rand) { +func (a *Server) refreshRemoteClusters(ctx context.Context) { remoteClusters, err := a.Services.GetRemoteClusters(ctx) if err != nil { log.WithError(err).Error("Failed to load remote clusters for status refresh") @@ -1873,7 +1872,7 @@ func (a *Server) refreshRemoteClusters(ctx context.Context, rnd *insecurerand.Ra } // randomize the order to optimize for multiple auth servers running in parallel - rnd.Shuffle(len(remoteClusters), func(i, j int) { + mathrand.Shuffle(len(remoteClusters), func(i, j int) { remoteClusters[i], remoteClusters[j] = remoteClusters[j], remoteClusters[i] }) @@ -4825,7 +4824,7 @@ func (a *Server) PingInventory(ctx context.Context, req proto.InventoryPingReque return proto.InventoryPingResponse{}, trace.NotFound("no control stream found for server %q", req.ServerID) } - id := insecurerand.Uint64() + id := mathrand.Uint64() if !req.ControlLog { // this ping doesn't pass through the control log, so just execute it immediately. diff --git a/lib/auth/keystore/gcp_kms_test.go b/lib/auth/keystore/gcp_kms_test.go index e43825b8c7526..922d8b4e3d051 100644 --- a/lib/auth/keystore/gcp_kms_test.go +++ b/lib/auth/keystore/gcp_kms_test.go @@ -25,7 +25,7 @@ import ( "crypto/x509/pkix" "encoding/pem" "math/big" - "math/rand" + mathrandv1 "math/rand" //nolint:depguard // only used for deterministic output "net" "strings" "sync" @@ -206,7 +206,7 @@ func (f *fakeGCPKMSServer) AsymmetricSign(ctx context.Context, req *kmspb.Asymme return nil, trace.BadParameter("unsupported digest type %T", typedDigest) } - testRand := rand.New(rand.NewSource(0)) + testRand := mathrandv1.New(mathrandv1.NewSource(0)) sig, err := signer.Sign(testRand, digest, alg) if err != nil { return nil, trace.Wrap(err) @@ -517,7 +517,7 @@ func TestGCPKMSKeystore(t *testing.T) { Key: clientPrivKey.SSHPublicKey(), CertType: ssh.HostCert, } - err = cert.SignCert(rand.New(rand.NewSource(0)), sshSigner) + err = cert.SignCert(mathrandv1.New(mathrandv1.NewSource(0)), sshSigner) if tc.expectSignError { require.Error(t, err, "expected to get error signing SSH cert") return @@ -545,7 +545,7 @@ func TestGCPKMSKeystore(t *testing.T) { }, } _, err = x509.CreateCertificate( - rand.New(rand.NewSource(0)), + mathrandv1.New(mathrandv1.NewSource(0)), template, tlsCA.Cert, clientPrivKey.Public(), diff --git a/lib/auth/kube_test.go b/lib/auth/kube_test.go index 08af05f555701..501b0ecea4f38 100644 --- a/lib/auth/kube_test.go +++ b/lib/auth/kube_test.go @@ -19,10 +19,10 @@ package auth import ( + "crypto/rand" "crypto/x509" "crypto/x509/pkix" "encoding/pem" - "math/rand" "testing" "time" @@ -112,9 +112,7 @@ func newTestCSR(subj pkix.Name) ([]byte, error) { x509CSR := &x509.CertificateRequest{ Subject: subj, } - // Use math/rand to avoid blocking on system entropy. - rng := rand.New(rand.NewSource(0)) - derCSR, err := x509.CreateCertificateRequest(rng, x509CSR, priv) + derCSR, err := x509.CreateCertificateRequest(rand.Reader, x509CSR, priv) if err != nil { return nil, err } diff --git a/lib/auth/password_test.go b/lib/auth/password_test.go index c9a3866488bad..3306062fddff5 100644 --- a/lib/auth/password_test.go +++ b/lib/auth/password_test.go @@ -22,7 +22,7 @@ import ( "context" "encoding/base32" "fmt" - "math/rand" + "math/rand/v2" "testing" "time" diff --git a/lib/auth/trustedcluster_test.go b/lib/auth/trustedcluster_test.go index f1581dbc64fee..c65287c5064ff 100644 --- a/lib/auth/trustedcluster_test.go +++ b/lib/auth/trustedcluster_test.go @@ -21,7 +21,6 @@ package auth import ( "context" "fmt" - insecurerand "math/rand" "testing" "time" @@ -44,7 +43,6 @@ import ( func TestRemoteClusterStatus(t *testing.T) { ctx := context.Background() a := newTestAuthServer(ctx, t) - rnd := insecurerand.New(insecurerand.NewSource(a.GetClock().Now().UnixNano())) rc, err := types.NewRemoteCluster("rc") require.NoError(t, err) @@ -53,7 +51,7 @@ func TestRemoteClusterStatus(t *testing.T) { // This scenario deals with only one remote cluster, so it never hits the limit on status updates. // TestRefreshRemoteClusters focuses on verifying the update limit logic. - a.refreshRemoteClusters(ctx, rnd) + a.refreshRemoteClusters(ctx) wantRC := rc // Initially, no tunnels exist and status should be "offline". @@ -83,7 +81,7 @@ func TestRemoteClusterStatus(t *testing.T) { require.NoError(t, err) require.NoError(t, a.UpsertTunnelConnection(tc2)) - a.refreshRemoteClusters(ctx, rnd) + a.refreshRemoteClusters(ctx) // With active tunnels, the status is "online" and last_heartbeat is set to // the latest tunnel heartbeat. @@ -96,7 +94,7 @@ func TestRemoteClusterStatus(t *testing.T) { // Delete the latest connection. require.NoError(t, a.DeleteTunnelConnection(tc2.GetClusterName(), tc2.GetName())) - a.refreshRemoteClusters(ctx, rnd) + a.refreshRemoteClusters(ctx) // The status should remain the same, since tc1 still exists. // The last_heartbeat should remain the same, since tc1 has an older @@ -109,7 +107,7 @@ func TestRemoteClusterStatus(t *testing.T) { // Delete the remaining connection require.NoError(t, a.DeleteTunnelConnection(tc1.GetClusterName(), tc1.GetName())) - a.refreshRemoteClusters(ctx, rnd) + a.refreshRemoteClusters(ctx) // The status should switch to "offline". // The last_heartbeat should remain the same. @@ -162,7 +160,6 @@ func TestRefreshRemoteClusters(t *testing.T) { require.LessOrEqual(t, tt.clustersNeedUpdate, tt.clustersTotal) a := newTestAuthServer(ctx, t) - rnd := insecurerand.New(insecurerand.NewSource(a.GetClock().Now().UnixNano())) allClusters := make(map[string]types.RemoteCluster) for i := 0; i < tt.clustersTotal; i++ { @@ -186,7 +183,7 @@ func TestRefreshRemoteClusters(t *testing.T) { } } - a.refreshRemoteClusters(ctx, rnd) + a.refreshRemoteClusters(ctx) clusters, err := a.GetRemoteClusters(ctx) require.NoError(t, err) diff --git a/lib/auth/usertoken_test.go b/lib/auth/usertoken_test.go index e7482fc2ce4f0..4592f95955d41 100644 --- a/lib/auth/usertoken_test.go +++ b/lib/auth/usertoken_test.go @@ -22,7 +22,7 @@ import ( "context" "encoding/base32" "fmt" - "math/rand" + "math/rand/v2" "testing" "time" diff --git a/lib/benchmark/ssh.go b/lib/benchmark/ssh.go index ab9a1645bcafe..454a594b7309e 100644 --- a/lib/benchmark/ssh.go +++ b/lib/benchmark/ssh.go @@ -20,7 +20,7 @@ package benchmark import ( "context" - "math/rand" + "math/rand/v2" "github.com/gravitational/trace" @@ -81,7 +81,7 @@ func chooseRandomHost(hosts []types.Server) string { name := hosts[0].GetName() return name + ":0" default: - name := hosts[rand.Intn(len(hosts))].GetName() + name := hosts[rand.N(len(hosts))].GetName() return name + ":0" } } diff --git a/lib/events/dynamoevents/dynamoevents_test.go b/lib/events/dynamoevents/dynamoevents_test.go index 8d8c2b5050da9..0e868ac837a0c 100644 --- a/lib/events/dynamoevents/dynamoevents_test.go +++ b/lib/events/dynamoevents/dynamoevents_test.go @@ -22,7 +22,7 @@ import ( "context" "encoding/json" "fmt" - "math/rand" + "math/rand/v2" "net/http" "net/http/httptest" "net/url" @@ -596,12 +596,11 @@ func generateEvent(sessionID session.ID, index int64, query string) apievents.Au } } -var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") - func randStringAlpha(n int) string { - b := make([]rune, n) + const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + b := make([]byte, n) for i := range b { - b[i] = letterRunes[rand.Intn(len(letterRunes))] + b[i] = letters[rand.N(len(letters))] } return string(b) } diff --git a/lib/events/export/date_exporter_test.go b/lib/events/export/date_exporter_test.go index a6907ade60015..f2c27e4a12797 100644 --- a/lib/events/export/date_exporter_test.go +++ b/lib/events/export/date_exporter_test.go @@ -21,7 +21,7 @@ package export import ( "context" "fmt" - "math/rand" + "math/rand/v2" "strconv" "sync" "testing" @@ -407,8 +407,8 @@ func (c *fakeClient) ExportUnstructuredEvents(ctx context.Context, req *auditlog // randomly truncate the chunk and append an error to simulate flake. we target a 33% failure rate // since event export is more frequent than chunk listing. var fail bool - if c.randomFlake && rand.Int()%3 == 0 { - chunk = chunk[:rand.Intn(len(chunk))] + if c.randomFlake && rand.N(3) == 0 { + chunk = chunk[:rand.N(len(chunk))] fail = true } @@ -438,8 +438,8 @@ func (c *fakeClient) GetEventExportChunks(ctx context.Context, req *auditlogpb.G // randomly truncate the chunk list and append an error to simulate flake. we target a 50% failure rate // since chunk listing is less frequent than event export. var fail bool - if c.randomFlake && rand.Int()%2 == 0 { - eec = eec[:rand.Intn(len(eec))] + if c.randomFlake && rand.N(2) == 0 { + eec = eec[:rand.N(len(eec))] fail = true } diff --git a/lib/kube/proxy/transport.go b/lib/kube/proxy/transport.go index 1e8e0067ed9e4..87217b39a0a4b 100644 --- a/lib/kube/proxy/transport.go +++ b/lib/kube/proxy/transport.go @@ -23,7 +23,7 @@ import ( "crypto/tls" "crypto/x509" "fmt" - "math/rand" + "math/rand/v2" "net" "net/http" "time" @@ -316,12 +316,9 @@ func (f *Forwarder) localClusterDialer(kubeClusterName string, opts ...contextDi } // Shuffle the list of servers to avoid always connecting to the same // server. - rand.Shuffle( - len(kubeServers), - func(i, j int) { - kubeServers[i], kubeServers[j] = kubeServers[j], kubeServers[i] - }, - ) + rand.Shuffle(len(kubeServers), func(i, j int) { + kubeServers[i], kubeServers[j] = kubeServers[j], kubeServers[i] + }) var errs []error // Validate that the requested kube cluster is registered. diff --git a/lib/proxy/router_test.go b/lib/proxy/router_test.go index 177875fda2fd6..660f9fd435762 100644 --- a/lib/proxy/router_test.go +++ b/lib/proxy/router_test.go @@ -21,7 +21,7 @@ package proxy import ( "bytes" "context" - "math/rand" + "math/rand/v2" "net" "testing" diff --git a/lib/resumption/handover_test.go b/lib/resumption/handover_test.go index 6b504866209ee..303593e6471a1 100644 --- a/lib/resumption/handover_test.go +++ b/lib/resumption/handover_test.go @@ -19,7 +19,7 @@ package resumption import ( "context" "encoding/binary" - "math/rand" + "math/rand/v2" "net" "net/netip" "os" @@ -64,12 +64,12 @@ func TestHandover(t *testing.T) { srv := &net.TCPAddr{ IP: net.IPv4(127, 0, 0, 1), - Port: 1 + rand.Intn(65535), + Port: 1 + rand.N(65536-1), } clt := &net.TCPAddr{ IP: clientAddr.AsSlice(), Zone: clientAddr.Zone(), - Port: 1 + rand.Intn(65535), + Port: 1 + rand.N(65536-1), } go handleConnection(utils.NewConnWithAddr(c2, srv, clt)) diff --git a/lib/reversetunnel/track/tracker_test.go b/lib/reversetunnel/track/tracker_test.go index e5fd610a31851..b1fe9746c5ba1 100644 --- a/lib/reversetunnel/track/tracker_test.go +++ b/lib/reversetunnel/track/tracker_test.go @@ -20,7 +20,7 @@ package track import ( "fmt" - pr "math/rand" + "math/rand/v2" "sync" "testing" "time" @@ -52,7 +52,7 @@ func (s *simpleTestProxies) RemoveRandProxies(n int) { rms := make([]bool, len(s.proxies)) rmc := 0 for rmc < n { - i := pr.Int() % len(s.proxies) + i := rand.N(len(s.proxies)) if !rms[i] { rms[i] = true rmc++ @@ -74,7 +74,7 @@ func (s *simpleTestProxies) GetRandProxy() (p testProxy, ok bool) { ok = false return } - i := pr.Int() % len(s.proxies) + i := rand.N(len(s.proxies)) return s.proxies[i], true } @@ -120,23 +120,18 @@ type testProxy struct { func newTestProxy(life time.Duration) testProxy { principals := make([]string, 0, 3) for i := 0; i < 3; i++ { - p := fmt.Sprintf("proxy-%d", pr.Int()) + p := fmt.Sprintf("proxy-%d", rand.Int()) principals = append(principals, p) } return testProxy{principals, life} } func prDuration(min time.Duration, max time.Duration) time.Duration { - mn, mx := int64(min), int64(max) - rslt := pr.Int63n(mx-mn) + mn - return time.Duration(rslt) + return min + rand.N(max-min) } func jitter(t time.Duration) time.Duration { - maxJitter := t / 5 - baseJitter := time.Duration(pr.Uint64()) - j := baseJitter % maxJitter - return t + j + return t + rand.N(t/5) } func TestBasic(t *testing.T) { diff --git a/lib/services/fanoutv2_test.go b/lib/services/fanoutv2_test.go index 0b142009386b8..e1a8ff9e20df9 100644 --- a/lib/services/fanoutv2_test.go +++ b/lib/services/fanoutv2_test.go @@ -20,7 +20,7 @@ package services import ( "context" - "math/rand" + "math/rand/v2" "testing" "time" @@ -112,7 +112,7 @@ func TestFanoutV2StreamOrdering(t *testing.T) { var inputs []string for i := 0; i < events; i++ { kind := "spam" - if rand.Int()%2 == 0 { + if rand.N(2) == 0 { kind = "eggs" } inputs = append(inputs, kind) diff --git a/lib/srv/db/proxyserver.go b/lib/srv/db/proxyserver.go index fb72e2accfe0d..3a2bacd8610e1 100644 --- a/lib/srv/db/proxyserver.go +++ b/lib/srv/db/proxyserver.go @@ -26,7 +26,7 @@ import ( "fmt" "io" "log/slog" - "math/rand" + "math/rand/v2" "net" "sort" "strconv" @@ -111,10 +111,9 @@ type ShuffleFunc func([]types.DatabaseServer) []types.DatabaseServer // ShuffleRandom is a ShuffleFunc that randomizes the order of database servers. // Used to provide load balancing behavior when proxying to multiple agents. func ShuffleRandom(servers []types.DatabaseServer) []types.DatabaseServer { - rand.New(rand.NewSource(time.Now().UnixNano())).Shuffle( - len(servers), func(i, j int) { - servers[i], servers[j] = servers[j], servers[i] - }) + rand.Shuffle(len(servers), func(i, j int) { + servers[i], servers[j] = servers[j], servers[i] + }) return servers } @@ -379,8 +378,7 @@ func (s *ProxyServer) handleConnection(conn net.Conn) error { // the MySQL.ServerVersion set in configuration if the first one is not available. // Function picks a random server each time if more than one are available. func getMySQLVersionFromServer(servers []types.DatabaseServer) string { - count := len(servers) - db := servers[rand.Intn(count)].GetDatabase() + db := servers[rand.N(len(servers))].GetDatabase() return db.GetMySQLServerVersion() } diff --git a/lib/sshutils/sftp/sftp_test.go b/lib/sshutils/sftp/sftp_test.go index f43a2a956ef67..7be2b5ae0f9ab 100644 --- a/lib/sshutils/sftp/sftp_test.go +++ b/lib/sshutils/sftp/sftp_test.go @@ -21,9 +21,10 @@ package sftp import ( "bytes" "context" + cryptorand "crypto/rand" "fmt" "io" - "math/rand" + mathrand "math/rand/v2" "net/http" "net/http/httptest" "os" @@ -31,7 +32,6 @@ import ( "strconv" "strings" "testing" - "time" "github.com/google/go-cmp/cmp" "github.com/gravitational/trace" @@ -723,9 +723,10 @@ func createFile(t *testing.T, path string) { }() // populate file with random amount of random contents - r := rand.New(rand.NewSource(time.Now().Unix())) - lr := io.LimitReader(r, r.Int63n(fileMaxSize)+1) - _, err = io.Copy(f, lr) + buf := make([]byte, mathrand.N(fileMaxSize)+1) + _, err = cryptorand.Read(buf) + require.NoError(t, err) + _, err = f.Write(buf) require.NoError(t, err) } diff --git a/lib/utils/concurrentqueue/queue_test.go b/lib/utils/concurrentqueue/queue_test.go index 9c986fdfbe56e..83e1e82575583 100644 --- a/lib/utils/concurrentqueue/queue_test.go +++ b/lib/utils/concurrentqueue/queue_test.go @@ -19,7 +19,7 @@ package concurrentqueue import ( - "math/rand" + "math/rand/v2" "testing" "time" @@ -35,7 +35,7 @@ func TestOrdering(t *testing.T) { q := New(func(v int) int { // introduce a short random delay to ensure that work // completes out of order. - time.Sleep(time.Duration(rand.Int63n(int64(time.Millisecond * 12)))) + time.Sleep(rand.N(time.Millisecond * 12)) return v }, Workers(10)) t.Cleanup(func() { require.NoError(t, q.Close()) }) diff --git a/lib/utils/loadbalancer.go b/lib/utils/loadbalancer.go index 26558a8c0b4c5..c201f8e60a79c 100644 --- a/lib/utils/loadbalancer.go +++ b/lib/utils/loadbalancer.go @@ -22,7 +22,7 @@ import ( "context" "errors" "io" - "math/rand" + "math/rand/v2" "net" "sync" "time" @@ -94,7 +94,7 @@ func randomPolicy() loadBalancerPolicy { if len(backends) == 0 { return NetAddr{}, trace.ConnectionProblem(nil, "no backends") } - i := rand.Intn(len(backends)) + i := rand.N(len(backends)) return backends[i], nil } } diff --git a/lib/utils/utils.go b/lib/utils/utils.go index 5da5b39d05685..1990f39ad23e2 100644 --- a/lib/utils/utils.go +++ b/lib/utils/utils.go @@ -24,7 +24,7 @@ import ( "fmt" "io" "io/fs" - "math/rand" + "math/rand/v2" "net" "net/url" "os" @@ -529,7 +529,7 @@ func ChooseRandomString(slice []string) string { case 1: return slice[0] default: - return slice[rand.Intn(len(slice))] + return slice[rand.N(len(slice))] } } diff --git a/lib/web/app/match.go b/lib/web/app/match.go index ad57f02e008e9..6a4339d93200f 100644 --- a/lib/web/app/match.go +++ b/lib/web/app/match.go @@ -20,7 +20,7 @@ package app import ( "context" - "math/rand" + "math/rand/v2" "slices" "strings" diff --git a/lib/web/desktop.go b/lib/web/desktop.go index 227480b79077c..b72d4108b5ef8 100644 --- a/lib/web/desktop.go +++ b/lib/web/desktop.go @@ -25,7 +25,7 @@ import ( "crypto/tls" "errors" "io" - "math/rand" + "math/rand/v2" "net" "net/http" "sync" diff --git a/tool/tctl/sso/configure/flags/file_reader_test.go b/tool/tctl/sso/configure/flags/file_reader_test.go index 742f0352b49a3..d235a55c0b8a5 100644 --- a/tool/tctl/sso/configure/flags/file_reader_test.go +++ b/tool/tctl/sso/configure/flags/file_reader_test.go @@ -17,12 +17,11 @@ package flags import ( - "math/rand" + "crypto/rand" "os" "path/filepath" "strings" "testing" - "time" "github.com/stretchr/testify/require" ) @@ -50,11 +49,9 @@ func TestFileReader(t *testing.T) { // random string fn = filepath.Join(tmp, "random.txt") - src := rand.NewSource(time.Now().UnixNano()) buf := make([]byte, 1024*1024) - for ix := range buf { - buf[ix] = byte(src.Int63()) - } + _, err = rand.Read(buf) + require.NoError(t, err) err = os.WriteFile(fn, buf, 0777) require.NoError(t, err) err = reader.Set(fn) From 93614be56f72dac7102048a2fdc5e9f3471d8d95 Mon Sep 17 00:00:00 2001 From: Edoardo Spadolini Date: Wed, 20 Nov 2024 17:04:17 +0100 Subject: [PATCH 2/3] Update retryutils to use rand.N --- api/utils/retryutils/jitter.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/utils/retryutils/jitter.go b/api/utils/retryutils/jitter.go index caa20a9647b40..89db496afbf57 100644 --- a/api/utils/retryutils/jitter.go +++ b/api/utils/retryutils/jitter.go @@ -76,7 +76,7 @@ func FullJitter(d time.Duration) time.Duration { return 0 } - return time.Duration(rand.Int64N(int64(d))) + return rand.N(d) } // HalfJitter is a jitter on the range [d/2, d). This is a large range and most @@ -92,7 +92,7 @@ func HalfJitter(d time.Duration) time.Duration { return d } - return d - frac + time.Duration(rand.Int64N(int64(frac))) + return d - frac + rand.N(frac) } // SeventhJitter returns a jitter on the range [6d/7, d). Prefer smaller jitters @@ -108,5 +108,5 @@ func SeventhJitter(d time.Duration) time.Duration { return d } - return d - frac + time.Duration(rand.Int64N(int64(frac))) + return d - frac + rand.N(frac) } From 8999ee6dddcb3f14a813584f7b0a21eacfc5f92e Mon Sep 17 00:00:00 2001 From: Edoardo Spadolini Date: Thu, 21 Nov 2024 13:34:47 +0100 Subject: [PATCH 3/3] Update e ref --- e | 2 +- e_imports.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/e b/e index 34d99edff3320..b4bb763b45204 160000 --- a/e +++ b/e @@ -1 +1 @@ -Subproject commit 34d99edff3320b09cbcf89c2add57da3899d48be +Subproject commit b4bb763b4520494f929e2997c07ca3e93f45f0b0 diff --git a/e_imports.go b/e_imports.go index 5b7f5d9f3ccfa..32eb84c7ff814 100644 --- a/e_imports.go +++ b/e_imports.go @@ -76,6 +76,7 @@ import ( _ "github.com/elimity-com/scim/schema" _ "github.com/ghodss/yaml" _ "github.com/go-jose/go-jose/v3" + _ "github.com/go-jose/go-jose/v3/json" _ "github.com/go-piv/piv-go/piv" _ "github.com/gogo/protobuf/proto" _ "github.com/google/go-attestation/attest" @@ -156,6 +157,7 @@ import ( _ "gopkg.in/check.v1" _ "k8s.io/apimachinery/pkg/util/yaml" + _ "github.com/gravitational/teleport/api" _ "github.com/gravitational/teleport/api/accessrequest" _ "github.com/gravitational/teleport/api/breaker" _ "github.com/gravitational/teleport/api/client" @@ -173,6 +175,7 @@ import ( _ "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" _ "github.com/gravitational/teleport/api/gen/proto/go/teleport/externalauditstorage/v1" _ "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + _ "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1" _ "github.com/gravitational/teleport/api/gen/proto/go/teleport/label/v1" _ "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1" _ "github.com/gravitational/teleport/api/gen/proto/go/teleport/mfa/v1" @@ -203,6 +206,7 @@ import ( _ "github.com/gravitational/teleport/api/types/secreports" _ "github.com/gravitational/teleport/api/types/secreports/convert/v1" _ "github.com/gravitational/teleport/api/types/trait" + _ "github.com/gravitational/teleport/api/types/trait/convert/v1" _ "github.com/gravitational/teleport/api/types/userloginstate" _ "github.com/gravitational/teleport/api/types/wrappers" _ "github.com/gravitational/teleport/api/utils"