From 83c9b8ad9ce1066b6a2ad74f5781bd55324450ae Mon Sep 17 00:00:00 2001 From: Benjamin Stromski Date: Wed, 9 Aug 2017 13:38:54 -0500 Subject: [PATCH] Add option to run varnish under sudo (#3097) --- plugins/inputs/varnish/README.md | 60 ++++++++++++++++++++++++++ plugins/inputs/varnish/varnish.go | 29 +++++++++---- plugins/inputs/varnish/varnish_test.go | 12 +++--- 3 files changed, 86 insertions(+), 15 deletions(-) diff --git a/plugins/inputs/varnish/README.md b/plugins/inputs/varnish/README.md index cba3506f5..1866ca188 100644 --- a/plugins/inputs/varnish/README.md +++ b/plugins/inputs/varnish/README.md @@ -7,6 +7,9 @@ This plugin gathers stats from [Varnish HTTP Cache](https://varnish-cache.org/) ```toml # A plugin to collect stats from Varnish HTTP Cache [[inputs.varnish]] + ## If running as a restricted user you can prepend sudo for additional access: + #use_sudo = false + ## The default location of the varnishstat binary can be overridden with: binary = "/usr/bin/varnishstat" @@ -330,6 +333,63 @@ the following values: - LCK + +### Permissions: + +It's important to note that this plugin references varnishstat, which may require additional permissions to execute successfully. +Depending on the user/group permissions of the telegraf user executing this plugin, you may need to alter the group membership, set facls, or use sudo. + +**Group membership (Recommended)**: +```bash +$ groups telegraf +telegraf : telegraf + +$ usermod -a -G varnish telegraf + +$ groups telegraf +telegraf : telegraf varnish +``` + +**Extended filesystem ACL's**: +```bash +$ getfacl /var/lib/varnish//_.vsm +# file: var/lib/varnish//_.vsm +# owner: root +# group: root +user::rw- +group::r-- +other::--- + +$ setfacl -m u:telegraf:r /var/lib/varnish//_.vsm + +$ getfacl /var/lib/varnish//_.vsm +# file: var/lib/varnish//_.vsm +# owner: root +# group: root +user::rw- +user:telegraf:r-- +group::r-- +mask::r-- +other::--- +``` + +**Sudo privileges**: +```bash +# If you use this method, you will need the following in your telegraf config: +[[inputs.varnish]] + use_sudo = true + +$ visudo + +# Add the following line: +telegraf ALL=(ALL) NOPASSWD: /usr/bin/varnishstat + +$ grep varnish /etc/sudoers +telegraf ALL = NOPASSWD: /usr/bin/varnishstat +``` + +Please use the solution you see as most appropriate. + ### Example Output: ``` diff --git a/plugins/inputs/varnish/varnish.go b/plugins/inputs/varnish/varnish.go index 896215aa0..08c885e61 100644 --- a/plugins/inputs/varnish/varnish.go +++ b/plugins/inputs/varnish/varnish.go @@ -17,12 +17,13 @@ import ( "github.com/influxdata/telegraf/plugins/inputs" ) -type runner func(cmdName string) (*bytes.Buffer, error) +type runner func(cmdName string, UseSudo bool) (*bytes.Buffer, error) // Varnish is used to store configuration values type Varnish struct { - Stats []string - Binary string + Stats []string + Binary string + UseSudo bool filter filter.Filter run runner @@ -32,6 +33,9 @@ var defaultStats = []string{"MAIN.cache_hit", "MAIN.cache_miss", "MAIN.uptime"} var defaultBinary = "/usr/bin/varnishstat" var sampleConfig = ` + ## If running as a restricted user you can prepend sudo for additional access: + #use_sudo = false + ## The default location of the varnishstat binary can be overridden with: binary = "/usr/bin/varnishstat" @@ -52,10 +56,16 @@ func (s *Varnish) SampleConfig() string { } // Shell out to varnish_stat and return the output -func varnishRunner(cmdName string) (*bytes.Buffer, error) { +func varnishRunner(cmdName string, UseSudo bool) (*bytes.Buffer, error) { cmdArgs := []string{"-1"} - cmd := exec.Command(cmdName, cmdArgs...) + + if UseSudo { + cmdArgs = append([]string{cmdName}, cmdArgs...) + cmdArgs = append([]string{"-n"}, cmdArgs...) + cmd = exec.Command("sudo", cmdArgs...) + } + var out bytes.Buffer cmd.Stdout = &out err := internal.RunTimeout(cmd, time.Millisecond*200) @@ -89,7 +99,7 @@ func (s *Varnish) Gather(acc telegraf.Accumulator) error { } } - out, err := s.run(s.Binary) + out, err := s.run(s.Binary, s.UseSudo) if err != nil { return fmt.Errorf("error gathering metrics: %s", err) } @@ -145,9 +155,10 @@ func (s *Varnish) Gather(acc telegraf.Accumulator) error { func init() { inputs.Add("varnish", func() telegraf.Input { return &Varnish{ - run: varnishRunner, - Stats: defaultStats, - Binary: defaultBinary, + run: varnishRunner, + Stats: defaultStats, + Binary: defaultBinary, + UseSudo: false, } }) } diff --git a/plugins/inputs/varnish/varnish_test.go b/plugins/inputs/varnish/varnish_test.go index e3f848093..a2b388a0b 100644 --- a/plugins/inputs/varnish/varnish_test.go +++ b/plugins/inputs/varnish/varnish_test.go @@ -11,8 +11,8 @@ import ( "testing" ) -func fakeVarnishStat(output string) func(string) (*bytes.Buffer, error) { - return func(string) (*bytes.Buffer, error) { +func fakeVarnishStat(output string, useSudo bool) func(string, bool) (*bytes.Buffer, error) { + return func(string, bool) (*bytes.Buffer, error) { return bytes.NewBuffer([]byte(output)), nil } } @@ -20,7 +20,7 @@ func fakeVarnishStat(output string) func(string) (*bytes.Buffer, error) { func TestGather(t *testing.T) { acc := &testutil.Accumulator{} v := &Varnish{ - run: fakeVarnishStat(smOutput), + run: fakeVarnishStat(smOutput, false), Stats: []string{"*"}, } v.Gather(acc) @@ -36,7 +36,7 @@ func TestGather(t *testing.T) { func TestParseFullOutput(t *testing.T) { acc := &testutil.Accumulator{} v := &Varnish{ - run: fakeVarnishStat(fullOutput), + run: fakeVarnishStat(fullOutput, true), Stats: []string{"*"}, } err := v.Gather(acc) @@ -51,7 +51,7 @@ func TestParseFullOutput(t *testing.T) { func TestFilterSomeStats(t *testing.T) { acc := &testutil.Accumulator{} v := &Varnish{ - run: fakeVarnishStat(fullOutput), + run: fakeVarnishStat(fullOutput, false), Stats: []string{"MGT.*", "VBE.*"}, } err := v.Gather(acc) @@ -74,7 +74,7 @@ func TestFieldConfig(t *testing.T) { for fieldCfg, expected := range expect { acc := &testutil.Accumulator{} v := &Varnish{ - run: fakeVarnishStat(fullOutput), + run: fakeVarnishStat(fullOutput, true), Stats: strings.Split(fieldCfg, ","), } err := v.Gather(acc)