From f3cba4f6bb613654b74c63be4ef49a8ba675647a Mon Sep 17 00:00:00 2001 From: Casey Ransom Date: Tue, 17 Oct 2017 19:51:41 -0400 Subject: [PATCH] netdata service: fix permissions for apps.plugin apps.plugin requires capabilities for full process monitoring. with 1.9.0, netdata allows multiple directories to search for plugins and the setuid directory can be specified here. the module is backwards compatible with older configs. a test is included that verifies data gathering for the elevated privileges. one additional attribute is added to make configuration more generic than including configuration in string form. --- nixos/modules/services/monitoring/netdata.nix | 54 +++++++++++++++---- nixos/release.nix | 1 + nixos/tests/netdata.nix | 31 +++++++++++ 3 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 nixos/tests/netdata.nix diff --git a/nixos/modules/services/monitoring/netdata.nix b/nixos/modules/services/monitoring/netdata.nix index e1fde4fc9500..d23b329eeb25 100644 --- a/nixos/modules/services/monitoring/netdata.nix +++ b/nixos/modules/services/monitoring/netdata.nix @@ -5,18 +5,25 @@ with lib; let cfg = config.services.netdata; - configFile = pkgs.writeText "netdata.conf" cfg.configText; + wrappedPlugins = pkgs.runCommand "wrapped-plugins" {} '' + mkdir -p $out/libexec/netdata/plugins.d + ln -s /run/wrappers/bin/apps.plugin $out/libexec/netdata/plugins.d/apps.plugin + ''; + + localConfig = { + global = { + "plugins directory" = "${wrappedPlugins}/libexec/netdata/plugins.d ${pkgs.netdata}/libexec/netdata/plugins.d"; + }; + }; + mkConfig = generators.toINI {} (recursiveUpdate localConfig cfg.config); + configFile = pkgs.writeText "netdata.conf" (if cfg.configText != null then cfg.configText else mkConfig); defaultUser = "netdata"; in { options = { services.netdata = { - enable = mkOption { - default = false; - type = types.bool; - description = "Whether to enable netdata monitoring."; - }; + enable = mkEnableOption "netdata"; user = mkOption { type = types.str; @@ -31,9 +38,9 @@ in { }; configText = mkOption { - type = types.lines; - default = ""; - description = "netdata.conf configuration."; + type = types.nullOr types.lines; + description = "Verbatim netdata.conf, cannot be combined with config."; + default = null; example = '' [global] debug log = syslog @@ -42,11 +49,29 @@ in { ''; }; + config = mkOption { + type = types.attrsOf types.attrs; + default = {}; + description = "netdata.conf configuration as nix attributes. cannot be combined with configText."; + example = literalExample '' + global = { + "debug log" = "syslog"; + "access log" = "syslog"; + "error log" = "syslog"; + }; + ''; + }; + }; }; - }; config = mkIf cfg.enable { + assertions = + [ { assertion = cfg.config != {} -> cfg.configText == null ; + message = "Cannot specify both config and configText"; + } + ]; systemd.services.netdata = { + path = with pkgs; [ gawk curl ]; description = "Real time performance monitoring"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; @@ -66,6 +91,15 @@ in { }; }; + security.wrappers."apps.plugin" = { + source = "${pkgs.netdata}/libexec/netdata/plugins.d/apps.plugin"; + capabilities = "cap_dac_read_search,cap_sys_ptrace+ep"; + owner = cfg.user; + group = cfg.group; + permissions = "u+rx,g+rx,o-rwx"; + }; + + users.extraUsers = optional (cfg.user == defaultUser) { name = defaultUser; }; diff --git a/nixos/release.nix b/nixos/release.nix index cf3fe6abd48c..e5f9a3aeff30 100644 --- a/nixos/release.nix +++ b/nixos/release.nix @@ -312,6 +312,7 @@ in rec { tests.nat.firewall = callTest tests/nat.nix { withFirewall = true; }; tests.nat.firewall-conntrack = callTest tests/nat.nix { withFirewall = true; withConntrackHelpers = true; }; tests.nat.standalone = callTest tests/nat.nix { withFirewall = false; }; + tests.netdata = callTest tests/netdata.nix { }; tests.networking.networkd = callSubTests tests/networking.nix { networkd = true; }; tests.networking.scripted = callSubTests tests/networking.nix { networkd = false; }; # TODO: put in networking.nix after the test becomes more complete diff --git a/nixos/tests/netdata.nix b/nixos/tests/netdata.nix new file mode 100644 index 000000000000..58733c1b3379 --- /dev/null +++ b/nixos/tests/netdata.nix @@ -0,0 +1,31 @@ +# This test runs netdata and checks for data via apps.plugin + +import ./make-test.nix ({ pkgs, ...} : { + name = "netdata"; + meta = with pkgs.stdenv.lib.maintainers; { + maintainers = [ cransom ]; + }; + + nodes = { + netdata = + { config, pkgs, ... }: + { + environment.systemPackages = with pkgs; [ curl jq ]; + services.netdata.enable = true; + }; + }; + + testScript = '' + startAll; + + $netdata->waitForUnit("netdata.service"); + # check if netdata can read disk ops for root owned processes. + # if > 0, successful. verifies both netdata working and + # apps.plugin has elevated capabilities. + my $cmd = <<'CMD'; + curl -s http://localhost:19999/api/v1/data\?chart=users.pwrites | \ + jq -e '[.data[range(10)][.labels | indices("root")[0]]] | add | . > 0' + CMD + $netdata->waitUntilSucceeds($cmd); + ''; +})