Skip to content

Commit

Permalink
fix(secrets): Warn if OS limit for locked memory is too low (influxda…
Browse files Browse the repository at this point in the history
  • Loading branch information
srebhan authored Apr 3, 2023
1 parent 5fdeae1 commit d8adb1e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 1 deletion.
12 changes: 12 additions & 0 deletions cmd/telegraf/telegraf.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,18 @@ func (t *Telegraf) runAgent(ctx context.Context, c *config.Config, reloadConfig
log.Printf("W! Deprecated secretstores: %d and %d options", count[0], count[1])
}

// Compute the amount of locked memory needed for the secrets
required := 2 * c.NumberSecrets * uint64(os.Getpagesize())
available := getLockedMemoryLimit()
if required > available {
required /= 1024
available /= 1024
log.Printf("I! Found %d secrets...", c.NumberSecrets)
msg := fmt.Sprintf("Insufficient lockable memory %dkb when %dkb is required.", available, required)
msg += " Please increase the limit for Telegraf in your Operating System!"
log.Printf("W! " + color.RedString(msg))
}

ag := agent.NewAgent(c)

// Notify systemd that telegraf is ready
Expand Down
20 changes: 19 additions & 1 deletion cmd/telegraf/telegraf_posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

package main

import "github.com/urfave/cli/v2"
import (
"log"
"syscall"

"github.com/urfave/cli/v2"
)

func (t *Telegraf) Run() error {
stop = make(chan struct{})
Expand All @@ -12,3 +17,16 @@ func (t *Telegraf) Run() error {
func cliFlags() []cli.Flag {
return []cli.Flag{}
}

func getLockedMemoryLimit() uint64 {
// From https://elixir.bootlin.com/linux/latest/source/include/uapi/asm-generic/resource.h#L35
const rLimitMemlock = 8

var limit syscall.Rlimit
if err := syscall.Getrlimit(rLimitMemlock, &limit); err != nil {
log.Printf("E! Cannot get limit for locked memory: %v", err)
return 0
}
//nolint:unconvert // required for e.g. FreeBSD that has the field as int64
return uint64(limit.Max)
}
11 changes: 11 additions & 0 deletions cmd/telegraf/telegraf_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/kardianos/service"
"github.com/urfave/cli/v2"
"golang.org/x/sys/windows"

"github.com/influxdata/telegraf/logger"
)
Expand Down Expand Up @@ -45,6 +46,16 @@ func cliFlags() []cli.Flag {
}
}

func getLockedMemoryLimit() uint64 {
handle := windows.CurrentProcess()

var min, max uintptr
var flag uint32
windows.GetProcessWorkingSetSizeEx(handle, &min, &max, &flag)

return uint64(max)
}

func (t *Telegraf) Run() error {
// Register the eventlog logging target for windows.
err := logger.RegisterEventLogger(t.serviceName)
Expand Down
5 changes: 5 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ type Config struct {
version *semver.Version

Persister *persister.Persister

NumberSecrets uint64
}

// Ordered plugins used to keep the order in which they appear in a file
Expand Down Expand Up @@ -471,6 +473,9 @@ func (c *Config) LoadAll(configFiles ...string) error {
c.Agent.SnmpTranslator = "netsnmp"
}

// Check if there is enough lockable memory for the secret
c.NumberSecrets = uint64(secretCount.Load())

// Let's link all secrets to their secret-stores
return c.LinkSecrets()
}
Expand Down
9 changes: 9 additions & 0 deletions config/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"regexp"
"strings"
"sync/atomic"

"github.com/awnumar/memguard"

Expand All @@ -25,6 +26,8 @@ var secretStorePattern = regexp.MustCompile(`^\w+$`)
// in a secret-store.
var secretPattern = regexp.MustCompile(`@\{(\w+:\w+)\}`)

var secretCount atomic.Int64

// Secret safely stores sensitive data such as a password or token
type Secret struct {
enclave *memguard.Enclave
Expand Down Expand Up @@ -60,6 +63,9 @@ func (s *Secret) UnmarshalText(b []byte) error {

// Initialize the secret content
func (s *Secret) init(secret []byte) {
// Keep track of the number of secrets...
secretCount.Add(1)

// Remember if the secret is completely empty
s.notempty = len(secret) != 0

Expand Down Expand Up @@ -87,6 +93,9 @@ func (s *Secret) Destroy() {
lockbuf.Destroy()
}
s.enclave = nil

// Keep track of the number of secrets...
secretCount.Add(-1)
}

// Empty return if the secret is completely empty
Expand Down

0 comments on commit d8adb1e

Please sign in to comment.