diff --git a/.golangci.yml b/.golangci.yml index 8cf464fd1..1ed75f028 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -109,6 +109,7 @@ linters-settings: - G306 - G401 - G403 + - G404 - G501 - G502 - G503 @@ -257,13 +258,13 @@ issues: - govet - path: cmd/telegraf/(main|printer).go - text: "Error return value of `outputBuffer.Write` is not checked" - - - path: cmd/telegraf/(main|printer).go - text: "unhandled-error: Unhandled error in call to function outputBuffer.Write" + text: "Error return value of `outputBuffer.Write` is not checked" #errcheck - path: _test\.go - text: "Potential hardcoded credentials" + text: "Potential hardcoded credentials" #gosec:G101 + + - path: _test\.go + text: "Use of weak random number generator" #gosec:G404 # Independently of option `exclude` we use default exclude patterns, # it can be disabled by this option. diff --git a/internal/internal.go b/internal/internal.go index 2bd0ba6d5..11e13d1c2 100644 --- a/internal/internal.go +++ b/internal/internal.go @@ -118,16 +118,14 @@ func SnakeCase(in string) string { } // RandomSleep will sleep for a random amount of time up to max. -// If the shutdown channel is closed, it will return before it has finished -// sleeping. +// If the shutdown channel is closed, it will return before it has finished sleeping. func RandomSleep(max time.Duration, shutdown chan struct{}) { - if max == 0 { + sleepDuration := RandomDuration(max) + if sleepDuration == 0 { return } - sleepns := rand.Int63n(max.Nanoseconds()) - - t := time.NewTimer(time.Nanosecond * time.Duration(sleepns)) + t := time.NewTimer(time.Nanosecond * sleepDuration) select { case <-t.C: return @@ -143,9 +141,7 @@ func RandomDuration(max time.Duration) time.Duration { return 0 } - sleepns := rand.Int63n(max.Nanoseconds()) - - return time.Duration(sleepns) + return time.Duration(rand.Int63n(max.Nanoseconds())) //nolint:gosec // G404: not security critical } // SleepContext sleeps until the context is closed or the duration is reached. diff --git a/plugins/inputs/example/example.go b/plugins/inputs/example/example.go index 5adea27a0..088e0f5e9 100644 --- a/plugins/inputs/example/example.go +++ b/plugins/inputs/example/example.go @@ -2,9 +2,11 @@ package example import ( + "crypto/rand" _ "embed" "fmt" - "math/rand" + "math" + "math/big" "time" "github.com/influxdata/telegraf" @@ -81,14 +83,14 @@ func (m *Example) Init() error { // Gather defines what data the plugin will gather. func (m *Example) Gather(acc telegraf.Accumulator) error { - // Imagine some completely arbitrary error occuring here + // Imagine some completely arbitrary error occurring here if m.NumberFields > 10 { return fmt.Errorf("too many fields") } - // For illustration we gather three metrics in one go + // For illustration, we gather three metrics in one go for run := 0; run < 3; run++ { - // Imagine an error occurs here but you want to keep the other + // Imagine an error occurs here, but you want to keep the other // metrics, then you cannot simply return, as this would drop // all later metrics. Simply accumulate errors in this case // and ignore the metric. @@ -101,11 +103,16 @@ func (m *Example) Gather(acc telegraf.Accumulator) error { fields := map[string]interface{}{"count": m.count} for i := int64(1); i < m.NumberFields; i++ { name := fmt.Sprintf("field%d", i) - value := 0.0 + var err error + value := big.NewInt(0) if m.EnableRandomVariable { - value = rand.Float64() + value, err = rand.Int(rand.Reader, big.NewInt(math.MaxUint32)) + if err != nil { + acc.AddError(err) + continue + } } - fields[name] = value + fields[name] = float64(value.Int64()) } // Construct the tags diff --git a/plugins/inputs/mock/mock.go b/plugins/inputs/mock/mock.go index cba2ca83b..38ff1a0d6 100644 --- a/plugins/inputs/mock/mock.go +++ b/plugins/inputs/mock/mock.go @@ -66,7 +66,7 @@ func (*Mock) SampleConfig() string { } func (m *Mock) Init() error { - m.rand = rand.New(rand.NewSource(time.Now().UnixNano())) + m.rand = rand.New(rand.NewSource(time.Now().UnixNano())) //nolint:gosec // G404: not security critical return nil } diff --git a/plugins/inputs/powerdns_recursor/protocol_v1.go b/plugins/inputs/powerdns_recursor/protocol_v1.go index 463c46eb6..e166a9f7f 100644 --- a/plugins/inputs/powerdns_recursor/protocol_v1.go +++ b/plugins/inputs/powerdns_recursor/protocol_v1.go @@ -2,12 +2,13 @@ package powerdns_recursor import ( "fmt" - "math/rand" "net" "os" "path/filepath" "time" + "github.com/google/uuid" + "github.com/influxdata/telegraf" ) @@ -19,8 +20,7 @@ import ( // The `data` field contains a list of commands to execute with // the \n character after every command. func (p *PowerdnsRecursor) gatherFromV1Server(address string, acc telegraf.Accumulator) error { - randomNumber := rand.Int63() - recvSocket := filepath.Join(p.SocketDir, fmt.Sprintf("pdns_recursor_telegraf%d", randomNumber)) + recvSocket := filepath.Join(p.SocketDir, fmt.Sprintf("pdns_recursor_telegraf%s", uuid.New().String())) laddr, err := net.ResolveUnixAddr("unixgram", recvSocket) if err != nil { diff --git a/plugins/inputs/powerdns_recursor/protocol_v2.go b/plugins/inputs/powerdns_recursor/protocol_v2.go index ad2d9f88f..dbeb4c96b 100644 --- a/plugins/inputs/powerdns_recursor/protocol_v2.go +++ b/plugins/inputs/powerdns_recursor/protocol_v2.go @@ -2,12 +2,13 @@ package powerdns_recursor import ( "fmt" - "math/rand" "net" "os" "path/filepath" "time" + "github.com/google/uuid" + "github.com/influxdata/telegraf" ) @@ -17,8 +18,7 @@ import ( // Datagram 1 => status: uint32 // Datagram 2 => data: byte[] (max 16_384 bytes) func (p *PowerdnsRecursor) gatherFromV2Server(address string, acc telegraf.Accumulator) error { - randomNumber := rand.Int63() - recvSocket := filepath.Join(p.SocketDir, fmt.Sprintf("pdns_recursor_telegraf%d", randomNumber)) + recvSocket := filepath.Join(p.SocketDir, fmt.Sprintf("pdns_recursor_telegraf%s", uuid.New().String())) laddr, err := net.ResolveUnixAddr("unixgram", recvSocket) if err != nil { diff --git a/plugins/inputs/statsd/running_stats.go b/plugins/inputs/statsd/running_stats.go index 1883406c4..ba4931156 100644 --- a/plugins/inputs/statsd/running_stats.go +++ b/plugins/inputs/statsd/running_stats.go @@ -81,7 +81,7 @@ func (rs *RunningStats) AddValue(v float64) { rs.perc = append(rs.perc, v) } else { // Reached limit, choose random index to overwrite in the percentile array - rs.perc[rand.Intn(len(rs.perc))] = v + rs.perc[rand.Intn(len(rs.perc))] = v //nolint:gosec // G404: not security critical } if len(rs.med) < rs.MedLimit { diff --git a/plugins/inputs/vsphere/endpoint.go b/plugins/inputs/vsphere/endpoint.go index 1c32dfb46..cefce029f 100644 --- a/plugins/inputs/vsphere/endpoint.go +++ b/plugins/inputs/vsphere/endpoint.go @@ -591,7 +591,7 @@ func (e *Endpoint) complexMetadataSelect(ctx context.Context, res *resourceKind, if n > maxMetadataSamples { // Shuffle samples into the maxMetadataSamples positions for i := 0; i < maxMetadataSamples; i++ { - j := int(rand.Int31n(int32(i + 1))) + j := int(rand.Int31n(int32(i + 1))) //nolint:gosec // G404: not security critical t := sampledObjects[i] sampledObjects[i] = sampledObjects[j] sampledObjects[j] = t