Secure Arguments

Overview Copied

Secure Arguments (also known as secure args) is a mechanism in Opsview that enhances the security of plugins, notification scripts, and event handlers by passing their arguments through standard input (stdin) instead of the command line.

When Opsview calls plugins, notification scripts, and event handlers, it requires providing arguments to the script. Traditionally, these executable files accept parameters via command line arguments and in some cases, environment variables. This provides flexibility and interoperability between different platforms and compatibility with Nagios plugins. However, these traditional command line argument scripts can be a potential security risk as these are visible to all local operating system users on the collectors.

To address this, Opsview supports secure args scripts to protect sensitive information in arguments. When secure args are used, the arguments will not be visible in the process list on the collectors and cannot be intercepted by local users on the same host where they are executed. This enhances security while providing a simple and flexible execution pattern for plugins, notification scripts, and event handlers.

Note

Not all of Opsview’s built-in plugins support secure args. Custom plugins, notification scripts, and event handlers will need to be modified and re-imported.

To determine how plugins or scripts are executed, Opsview tracks an execution style for each. Uploaded plugins or scripts can be executed in the following ways:

The Execution Style column on the Configuration > Monitoring Plugins page lists the value for each plugin. The execution style of built-in plugins or scripts cannot be modified and is controlled by the system (displayed as Auto).

Use secure args scripts Copied

For a script to accept secure args, it must read a line from stdin, decode it as a JSON dictionary, and extract the array of strings from the cmd key within that dictionary. This array of strings can then replace the command line arguments in the existing argv variable. The script can then continue its execution as normal.

To test a script, you can manually pass the JSON string via stdin after constructing the argv array:

echo '{"cmd": ["arg1", "arg2", "arg3", "-a", "arg4", "--example", "arg5"]}' | ./my_secure_args_script.py

Alternatively, you can use the following helper script on an Opsview system when running commands manually, which accepts command line arguments without any need for further changes.

./my_secure_args_script.py <<< $(/opt/opsview/monitoringscripts/commands/ov_cmd_split arg1 arg2 arg3 -a arg4 --example arg5)

The /opt/opsview/monitoringscripts/commands/ov_cmd_split script is available for the opsview user with the ov_cmd_split alias.

Import secure args scripts Copied

For plugins, you can import the secure args scripts using the UI.

  1. Go to the Configuration > Monitoring Plugins and click Import.
  2. Select the Compatible with Secure Args execution style checkbox.

For more details, see User Interface.

Import Monitoring Plugins window

Note

Import Monitoring Plugins functionality is disabled by default on new installations. For more information, see documentation on Active Checks and Monitoring plugins.

Note

To import a notification script or event handler, please contact ITRS Support for assistance.

Import an Opspack with secure args plugins Copied

To upload plugins in an Opspack, the config.json file allows an optional section of the following format:

"plugin_execution_style": {
  "<plugin name>": "<COMMAND_LINE_ARGS|STDIN_ARGS>"
}

This will be used to set the execution style on a per-plugin basis. For example, the following config.json sets the check_mssql_database.py plugin to use secure args instead of command line args.

{
   "plugin_execution_style": {
      "check_mssql_database.py": "STDIN_ARGS"
   },
   ...
}

If plugin_execution_style is not specified, the default style is COMMAND_LINE_ARGS. This can be imported as a normal Opspack on the Configuration > Host Templates page.

Note

Import Opspack functionality is disabled by default on new installations. For more information, see documentation on Importing Opspacks.

Code samples Copied

The following code examples show how to implement secure args scripts in several common programming languages.

Python with plugnpy Copied

Using the Opsview plugnpy Python library (included with /opt/opsview/python3/bin/python on Opsview systems):

#!/opt/opsview/python3/bin/python

import sys
from plugnpy import Parser as PnPParser, ExecutionStyle, Check


def get_args():
    parser = PnPParser(
        execution_style=ExecutionStyle.STDIN_ARGS,  # switches PnP parser to use STDIN-only for args
    )
    # Add arguments here:
    # e.g.
    parser.add_argument('-a', '--arg1', help="An example argument")
    return parser.parse_args(sys.argv[1:])


def main():
    args = get_args()
    check = Check()
    # Implement check logic and add metrics here
    # e.g.
    check.add_metric(
        name="metric_name",
        value=0,
        unit="",
        warning_threshold=0,
        critical_threshold=0,
        display_format=None,
        display_in_perf=True,
        display_in_summary=True,
        display_name=None,
        convert_metric=None,
        si_bytes_conversion=False,
        summary_precision=2,
        perf_data_precision=2,
        message="All OK",
    )
    check.final()


if __name__ == "__main__":
    main()

Python without plugnpy Copied

#!/opt/opsview/python3/bin/python

import sys
import argparse
import json
import select


def get_args():
    no_stdin = True
    data = select.select([sys.stdin], [], [], 0.0)[0]
    if data:
        data = data[0].readlines()
        if data:
            first_line = data[0].strip()
            if first_line:
                try:
                    args = json.loads(first_line)['cmd']
                    no_stdin = False
                except (json.JSONDecodeError, KeyError):
                    print(
                        f"ERROR: Failed to parse secure args JSON from STDIN and extract 'cmd' key"
                    )
                    sys.exit(3)

    if no_stdin:
        args = sys.argv[1:]
        if len(args) > 0 and not '--help' in args and not '-h' in args:
            print(
                "WARNING: This script supports secure args passing via STDIN. "
                "You have passed arguments on the command line. "
                "Please update your configuration to pass secure args via STDIN."
            )

    parser = argparse.ArgumentParser()
    # Add arguments here:
    # e.g.
    parser.add_argument('-a', '--arg1', help="An example argument")
    return parser.parse_args(args=args)


def main():
    args = get_args()
    # Implement check logic and add metrics here
    # e.g.
    status = 0
    return status


if __name__ == "__main__":
    sys.exit(main())

Perl Copied

#!/bin/perl
use warnings; 
use strict;
use IO::Select;
use JSON qw( decode_json );

# Support for optional arguments over STDIN
my $no_stdin = 1;
my $select = IO::Select->new();
$select->add( \*STDIN );
my $json = "";
if ( $select->can_read(0) ) {
    $json = <STDIN>;
    if ( defined $json && $json ne "" ) {
        my $args_hash;
        eval {
          $args_hash = decode_json( $json );
          1;
        } or do {
            print "ERROR: Failed to decode JSON from STDIN.\n";
            exit 3;
        };
        if ( exists $args_hash->{cmd} ) {
            my $argv = $args_hash->{cmd};
            if ( ref($argv) eq "ARRAY" ) {
                @ARGV = @$argv;
                $no_stdin = 0;
            }
        } else {
            print "ERROR: Missing 'cmd' key in JSON from STDIN.\n";
            exit 3;
        }
    }
}

if ( $no_stdin ) {
    if ( $#ARGV >= 0 && !grep( /^--help$/, @ARGV ) && !grep( /^-h$/, @ARGV ) ) {
        print "WARNING: This script supports secure args passing via STDIN. ",
            "You have passed arguments on the command line. ",
            "Please update your configuration to pass secure args via STDIN.\n";
    }
}

# Implement script using @ARGV as normal
print "Args: @ARGV\n";

exit 0;

BASH Copied

#!/bin/bash
# Requires jq and bash 4

if [ $# -eq 0 ]; then
  read -r json;
  readarray -t args < <(echo $json | jq -rc '.cmd[]')
else
  args=("$@")
  if [[ " ${args[*]} " =~ [[:space:]]--help[[:space:]] || " ${args[*]} " =~ [[:space:]]-h[[:space:]] ]]; then
    echo "Usage: help text goes here..."
  else
    echo "WARNING: This script supports secure args passing via STDIN."
    echo "You have passed arguments on the command line."
    echo "Please update your configuration to pass secure args via STDIN."
  fi 
fi

set -- "${args[@]}"

# Implement script as usual using $@
echo "Args: $@"

exit 0
["Opsview Cloud"] ["User Guide"]

Was this topic helpful?