Skip to content

Commit

Permalink
drop privileges when running node exporter
Browse files Browse the repository at this point in the history
  • Loading branch information
sni committed Nov 12, 2023
1 parent 66e40d0 commit b77c3b4
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Changes
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
This file documents the revision history for the SNClient+ agent.

next:
- drop privileges when running node exporter

0.12 Tue Nov 7 23:52:33 CET 2023
- add built-in check_http / check_tcp / check_dns
- add check_omd check
Expand Down
6 changes: 6 additions & 0 deletions packaging/snclient.ini
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ default module =
; agent max memory - set a memory limit for the agent (agent will be restarted if the rss is higher, set to 0 to disabled)
;agent max memory = 256M

; agent user - set user this agent should run as (requires root permissions)
;agent user = nobody

; port - Port to use for the node exporter.
;port = ${/settings/WEB/server/port}

Expand Down Expand Up @@ -161,6 +164,9 @@ agent address = 127.0.0.1:9990
; agent max memory - set a memory limit for the agent (agent will be restarted if the rss is higher, set to 0 to disabled)
agent max memory = 256M

; agent user - set user this agent should run as (requires root permissions)
agent user = nobody

; port - Port to use for the node exporter.
port = ${/settings/WEB/server/port}

Expand Down
15 changes: 15 additions & 0 deletions pkg/snclient/listen_managedexporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ type HandlerManagedExporter struct {
agentAddress string
agentMaxMem uint64
agentExtraArgs string
agentUser string
cmd *exec.Cmd
pid int
snc *Agent
Expand Down Expand Up @@ -127,6 +128,10 @@ func (l *HandlerManagedExporter) Init(snc *Agent, conf *ConfigSection, _ *Config
l.agentAddress = agentAddress
}

if agentUser, ok := conf.GetString("agent user"); ok {
l.agentUser = agentUser
}

uri, err := url.Parse("http://" + l.agentAddress + "/metrics")
if err != nil {
return fmt.Errorf("cannot parse agent url: %s", err.Error())
Expand Down Expand Up @@ -163,6 +168,16 @@ func (l *HandlerManagedExporter) procMainLoop() {
args = append(args, extra)
}
cmd := exec.Command(l.agentPath, args...) //nolint:gosec // input source is the config file

if l.agentUser != "" {
if err := setCmdUser(cmd, l.agentUser); err != nil {
err = fmt.Errorf("failed to drop privileges for %s agent: %s", l.Type(), err.Error())
log.Errorf("agent startup error: %s", err)

return
}
}

log.Debugf("starting %s agent: %s", l.Type(), cmd.Path)
l.snc.passthroughLogs("stdout", "["+l.Type()+"] ", log.Debugf, cmd.StdoutPipe)
l.snc.passthroughLogs("stderr", "["+l.Type()+"] ", l.logPass, cmd.StderrPipe)
Expand Down
1 change: 1 addition & 0 deletions pkg/snclient/listen_nodeexporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ func NewHandlerNodeExporter() Module {
name: "nodeexporter",
urlPrefix: "/node",
agentExtraArgs: "--web.listen-address=${agent address}",
agentUser: "nobody",
}

return mod
Expand Down
28 changes: 28 additions & 0 deletions pkg/snclient/snclient_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@ package snclient

import (
"context"
"fmt"
"os"
"os/exec"
"os/signal"
"os/user"
"runtime"
"runtime/pprof"
"strings"
"syscall"
"time"

"pkg/convert"
"pkg/utils"
)

Expand Down Expand Up @@ -120,3 +123,28 @@ func makeCmd(ctx context.Context, command string) (*exec.Cmd, error) {

return cmd, nil
}

func setCmdUser(cmd *exec.Cmd, username string) error {
usr, err := user.Lookup(username)
if err != nil {
return fmt.Errorf("user.lookup: %s: %s", username, err.Error())
}

if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}

uid, err := convert.Float64E(usr.Uid)
if err != nil {
return fmt.Errorf("cannot convert uid to number for user %s (uid:%s): %s", username, usr.Uid, err.Error())
}

gid, err := convert.Float64E(usr.Gid)
if err != nil {
return fmt.Errorf("cannot convert gid to number for user %s (gid:%s): %s", username, usr.Gid, err.Error())
}

cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uint32(uid), Gid: uint32(gid)}

return nil
}
4 changes: 4 additions & 0 deletions pkg/snclient/snclient_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,7 @@ func QuotePathWithSpaces(path string) string {

return strings.Join(quotedComponents, `/`)
}

func setCmdUser(_ *exec.Cmd, _ string) error {
return fmt.Errorf("droping privileges is not supported on windows")
}

0 comments on commit b77c3b4

Please sign in to comment.