Set up external validation

In your modular input script, it is a good idea to validate the configuration of your input. Specify <use_external_validation>true</use_external_validation> in your introspection scheme to enable external validation.

If you provide an external validation routine and enable external validation the following occurs when a user creates or edits the configuration for a script:

  1. Splunk software reads the configuration parameters from the user and creates an XML configuration of the parameters.

    The XML configuration looks something like this:

    <items>
        <server_host>myHost</server_host>
        <server_uri>https://127.0.0.1:8089</server_uri>
        <session_key>123102983109283019283</session_key>
        <checkpoint_dir>/opt/splunk/var/lib/splunk/modinputs</checkpoint_dir>
        <item name="myScheme">
            <param name="param1">value1</param>
            <param_list name="param2">
                <value>value2</value>
                <value>value3</value>
                <value>value4</value>
            </param_list>
        </item>
    </items>
    

    Notes: The <items> element can only contain one <item>. (This is because you can only operate on one item at a time.) The XML stream itself must be encoded in UTF-8.

    Refer to the Read XML configuration from splunkd section for a description of the XML configuration.

  2. Splunk software invokes your script with the --validate-arguments option, passing in the XML configuration.
  3. Your script validation routine determines if the configuration is valid.
    • If the configuration is valid, your script exits with return status of zero.
    • Otherwise the script exits with a non-zero status and a message indicating why configuration failed. Format the message in <error> tags so Splunk software can properly display the message in Splunk Web.
    <error>
        <message>Access is denied.</message>
    </error>
    

    The following snippets shows how the S3 example validates data returned from the Amazon S3 service. The snippet at the end shows how to provide the --validate-arguments option when invoking the script. This script has been made cross-compatible with Python 2 and Python 3 using python-future.

    Validation snippets

    . . .
    from builtins import str
    def get_validation_data():
        val_data = {}
    
        # read everything from stdin
        val_str = sys.stdin.read()
    
        # parse the validation XML
        doc = xml.dom.minidom.parseString(val_str)
        root = doc.documentElement
    
        logging.debug("XML: found items")
        item_node = root.getElementsByTagName("item")[0]
        if item_node:
            logging.debug("XML: found item")
    
            name = item_node.getAttribute("name")
            val_data["stanza"] = name
    
            params_node = item_node.getElementsByTagName("param")
            for param in params_node:
                name = param.getAttribute("name")
                logging.debug("Found param %s" % name)
                if name and param.firstChild and \
                   param.firstChild.nodeType == param.firstChild.TEXT_NODE:
                    val_data[name] = param.firstChild.data
    
        return val_data
    
    # make sure that the amazon credentials are good
    def validate_arguments():
        val_data = get_validation_data()
    
        try:
            url = "s3://" + val_data["stanza"]
            bucket, obj = read_from_s3_uri(url)
            conn = get_http_connection(val_data["key_id"], val_data["secret_key"], bucket, obj, method = "HEAD")
            resp = conn.getresponse()
            log_response(resp)
            if resp.status != 200:
                raise Exception("Amazon returned HTTP status code %d (%s): %s" % (resp.status, resp.reason, get_amazon_error(resp.read())))
    
        except Exception as e:
            print_error("Invalid configuration specified: %s" % str(e))
            sys.exit(1)
    . . .
    # Provide --validate-arguments arg on startup
    if __name__ == '__main__':
        if len(sys.argv) > 1:
            if sys.argv[1] == "--scheme":
                do_scheme()
            elif sys.argv[1] == "--validate-arguments":
                validate_arguments()
            elif sys.argv[1] == "--test":
                test()
            else:
                usage()
        else:
            # just request data from S3
            run()