fix(secrets): Warn if OS limit for locked memory is too low (#12993)

This commit is contained in:
Sven Rebhan 2023-04-03 10:49:07 +02:00 committed by GitHub
parent 5fdeae1ab1
commit d8adb1edf2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 1 deletions

View File

@ -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

View File

@ -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{})
@ -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)
}

View File

@ -10,6 +10,7 @@ import (
"github.com/kardianos/service"
"github.com/urfave/cli/v2"
"golang.org/x/sys/windows"
"github.com/influxdata/telegraf/logger"
)
@ -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)

View File

@ -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
@ -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()
}

View File

@ -4,6 +4,7 @@ import (
"fmt"
"regexp"
"strings"
"sync/atomic"
"github.com/awnumar/memguard"
@ -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
@ -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
@ -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