diff --git a/check_with_thresholds_as_perfdata.py b/check_with_thresholds_as_perfdata.py index 8a897a4..6760740 100755 --- a/check_with_thresholds_as_perfdata.py +++ b/check_with_thresholds_as_perfdata.py @@ -155,6 +155,16 @@ def append_thresholds_to_perfdata(perfdata, parsed_perfdata, warning, critical): return " ".join(sorted(perfdata_strings)) +def exit_if_command_does_not_start_with_an_opsview_path(command): + """Validate that the command is a valid path to a plugin.""" + command = command.strip("'\"") + if not command.startswith("/opt/opsview/monitoringscripts/"): + sys.stderr.write( + "Error: Command MUST start with a path in the /opt/opsview/monitoringscripts directory\n" + ) + sys.exit(3) + + def main(): """Run the plugin command and append warning and critical thresholds as perfdata.""" args = parse_arguments() @@ -163,6 +173,8 @@ def main(): sys.stderr.write("Error: --warning and/or --critical must be provided\n") sys.exit(3) + exit_if_command_does_not_start_with_an_opsview_path(args.command) + result = execute_command(args.command) stdout, stderr, return_code = process_command_output(result) output, perfdata = extract_perfdata(stdout) diff --git a/tests/test_check_with_thresholds_as_perfdata.py b/tests/test_check_with_thresholds_as_perfdata.py index 8b176a6..6779e9a 100644 --- a/tests/test_check_with_thresholds_as_perfdata.py +++ b/tests/test_check_with_thresholds_as_perfdata.py @@ -107,7 +107,10 @@ def test_append_multiple_thresholds_to_perfdata(self): def test_command_not_found(self, mock_subprocess_run, _mock_stderr): mock_result = MagicMock() mock_result.stdout = "" - mock_result.stderr = "Error: Command not found: /bin/foo\n" + mock_result.stderr = ( + "Error: Command not found: " + "/opt/opsview/monitoringscripts/plugins/check_non_existing_plugin\n" + ) mock_result.returncode = 127 mock_subprocess_run.return_value = mock_result @@ -121,7 +124,7 @@ def test_command_not_found(self, mock_subprocess_run, _mock_stderr): "-c", "90", "-C", - "/bin/foo -H localhost", + '"/opt/opsview/monitoringscripts/plugins/check_non_existing_plugin -H localhost"', ] with patch.object(sys, "argv", test_args): try: @@ -129,7 +132,10 @@ def test_command_not_found(self, mock_subprocess_run, _mock_stderr): except SystemExit as e: self.assertEqual(e.code, 127) - expected_output = "Error: Command not found: /bin/foo\n" + expected_output = ( + "Error: Command not found: " + "/opt/opsview/monitoringscripts/plugins/check_non_existing_plugin\n" + ) self.assertEqual(expected_output, mock_stderr.getvalue()) @patch("sys.stderr", new_callable=StringIO) @@ -558,6 +564,27 @@ def test_valid_critical_command_output_with_both_warning_and_critical_and_three_ self.maxDiff = None self.assertEqual(expected_output, mock_stdout.getvalue()) + @patch("sys.stderr", new_callable=StringIO) + def test_invalid_path_of_command_results_in_error(self, mock_stderr): + mock_result = MagicMock() + + with patch("sys.stdout", new_callable=lambda: sys.stdout) as _mock_stdout, patch( + "sys.stderr", new_callable=lambda: sys.stderr + ) as mock_stderr: + test_args = ["script_name", "-w", "80", "-c", "90", "-C", '"/bin/echo foo"'] + with patch.object(sys, "argv", test_args): + try: + main() + except SystemExit as e: + self.assertEqual(e.code, 3) + + expected_output = ( + "Error: Command MUST start with a path in the " + "/opt/opsview/monitoringscripts directory\n" + ) + self.maxDiff = None + self.assertEqual(expected_output, mock_stderr.getvalue()) + if __name__ == "__main__": unittest.main() # pragma: no cover