예제 #1
0
def main():

    argspec = dict(name=dict(required=False, type="str"))

    module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)

    splunk_request = SplunkRequest(
        module, headers={"Content-Type": "application/json"})

    if module.params["name"]:
        try:
            query_dict = splunk_request.get_by_path(
                "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}"
                .format(quote_plus(module.params["name"])))
        except HTTPError as e:
            # the data monitor doesn't exist
            query_dict = {}
    else:
        query_dict = splunk_request.get_by_path(
            "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches")

    module.exit_json(changed=False, splunk_correlation_search_info=query_dict)
예제 #2
0
def main():

    argspec = dict(
        state=dict(
            required=False,
            choices=["present", "absent", "enabled", "disable"],
            default="present",
            type="str",
        ),
        connection_host=dict(required=False,
                             choices=["ip", "dns", "none"],
                             default="ip",
                             type="str"),
        host=dict(required=False, type="str", default=None),
        index=dict(required=False, type="str", default=None),
        name=dict(required=True, type="str"),
        protocol=dict(required=True, type="str", choices=["tcp", "udp"]),
        queue=dict(
            required=False,
            type="str",
            choices=["parsingQueue", "indexQueue"],
            default="parsingQueue",
        ),
        rawTcpDoneTimeout=dict(required=False, type="int", default=10),
        restrictToHost=dict(required=False, type="str", default=None),
        ssl=dict(required=False, type="bool", default=None),
        source=dict(required=False, type="str", default=None),
        sourcetype=dict(required=False, type="str", default=None),
        datatype=dict(required=False, choices=["cooked", "raw"],
                      default="raw"),
    )

    module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)

    splunk_request = SplunkRequest(
        module,
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        not_rest_data_keys=["state", "datatype", "protocol"],
    )
    # This is where the splunk_* args are processed
    request_data = splunk_request.get_data()

    query_dict = splunk_request.get_by_path(
        "servicesNS/nobody/search/data/inputs/{0}/{1}/{2}".format(
            quote_plus(module.params["protocol"]),
            quote_plus(module.params["datatype"]),
            quote_plus(module.params["name"]),
        ))

    if module.params["state"] in ["present", "enabled", "disabled"]:
        _data = splunk_request.get_data()
        if module.params["state"] in ["present", "enabled"]:
            _data["disabled"] = False
        else:
            _data["disabled"] = True
        if query_dict:
            needs_change = False
            for arg in request_data:
                if arg in query_dict["entry"][0]["content"]:
                    if to_text(
                            query_dict["entry"][0]["content"][arg]) != to_text(
                                request_data[arg]):
                        needs_change = True
            if not needs_change:
                module.exit_json(changed=False,
                                 msg="Nothing to do.",
                                 splunk_data=query_dict)
            if module.check_mode and needs_change:
                module.exit_json(
                    changed=True,
                    msg="A change would have been made if not in check mode.",
                    splunk_data=query_dict,
                )
            if needs_change:
                splunk_data = splunk_request.create_update(
                    "servicesNS/nobody/search/data/inputs/{0}/{1}/{2}".format(
                        quote_plus(module.params["protocol"]),
                        quote_plus(module.params["datatype"]),
                        quote_plus(module.params["name"]),
                        data=urlencode(_data),
                    ))
            if module.params["state"] in ["present", "enabled"]:
                module.exit_json(changed=True,
                                 msg="{0} updated.",
                                 splunk_data=splunk_data)
            else:
                module.exit_json(changed=True,
                                 msg="{0} disabled.",
                                 splunk_data=splunk_data)
        else:
            # Create it
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/search/data/inputs/{0}/{1}".format(
                    quote_plus(module.params["protocol"]),
                    quote_plus(module.params["datatype"]),
                ),
                data=urlencode(_data),
            )
            module.exit_json(changed=True,
                             msg="{0} created.",
                             splunk_data=splunk_data)
    elif module.params["state"] == "absent":
        if query_dict:
            splunk_data = splunk_request.delete_by_path(
                "servicesNS/nobody/search/data/inputs/{0}/{1}/{2}".format(
                    quote_plus(module.params["protocol"]),
                    quote_plus(module.params["datatype"]),
                    quote_plus(module.params["name"]),
                ))
            module.exit_json(
                changed=True,
                msg="Deleted {0}.".format(module.params["name"]),
                splunk_data=splunk_data,
            )

    module.exit_json(changed=False, msg="Nothing to do.", splunk_data={})
def main():

    argspec = dict(
        name=dict(required=True, type="str"),
        correlation_search_name=dict(required=True, type="str"),
        description=dict(required=True, type="str"),
        state=dict(choices=["present", "absent"], required=True),
        security_domain=dict(
            choices=["access", "endpoint", "network", "threat", "identity", "audit"],
            required=False,
            default="threat",
        ),
        severity=dict(
            choices=["informational", "low", "medium", "high", "critical", "unknown"],
            required=False,
            default="high",
        ),
        default_owner=dict(required=False, type="str"),
        default_status=dict(
            choices=[
                "unassigned",
                "new",
                "in progress",
                "pending",
                "resolved",
                "closed",
            ],
            required=False,
            default="",
        ),
        drill_down_name=dict(required=False, type="str"),
        drill_down_search=dict(required=False, type="str"),
        drill_down_earliest_offset=dict(
            required=False, type="str", default="$info_min_time$"
        ),
        drill_down_latest_offset=dict(
            required=False, type="str", default="$info_max_time$"
        ),
        investigation_profiles=dict(required=False, type="str"),
        next_steps=dict(required=False, type="list", default=[]),
        recommended_actions=dict(required=False, type="list", default=[]),
        asset_extraction=dict(
            required=False,
            type="list",
            default=["src", "dest", "dvc", "orig_host"],
            choices=["src", "dest", "dvc", "orig_host"],
        ),
        identity_extraction=dict(
            required=False,
            type="list",
            default=["user", "src_user"],
            choices=["user", "src_user"],
        ),
    )

    module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)

    splunk_request = SplunkRequest(
        module,
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        not_rest_data_keys=["state"],
    )

    query_dict = splunk_request.get_by_path(
        "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}".format(
            quote_plus(module.params["correlation_search_name"])
        )
    )

    # Have to custom craft the data here because they overload the saved searches
    # endpoint in the rest api and we want to hide the nuance from the user
    request_post_data = {}

    # FIXME  need to figure out how to properly support these, the possible values appear to
    #       be dynamically created based on what the search is indexing
    # request_post_data['action.notable.param.extract_assets'] = '[\"src\",\"dest\",\"dvc\",\"orig_host\"]'
    # request_post_data['action.notable.param.extract_identities'] = [\"src_user\",\"user\"]
    if module.params["next_steps"]:
        if len(module.params["next_steps"]) == 1:
            next_steps = "[[action|{0}]]".format(module.params["next_steps"][0])
        else:
            next_steps = ""
            for next_step in module.params["next_steps"]:
                if next_steps:
                    next_steps += "\n[[action|{0}]]".format(next_step)
                else:
                    next_steps = "[[action|{0}]]".format(next_step)

        # NOTE: version:1 appears to be hard coded when you create this via the splunk web UI
        #       but I don't know what it is/means because there's no docs on it
        next_steps_dict = {"version": 1, "data": next_steps}
        request_post_data["action.notable.param.next_steps"] = json.dumps(
            next_steps_dict
        )

    if module.params["recommended_actions"]:
        if len(module.params["recommended_actions"]) == 1:
            request_post_data[
                "action.notable.param.recommended_actions"
            ] = module.params["recommended_actions"][0]
        else:
            request_post_data["action.notable.param.recommended_actions"] = ",".join(
                module.params["recommended_actions"]
            )

    request_post_data["action.notable.param.rule_description"] = module.params[
        "description"
    ]
    request_post_data["action.notable.param.rule_title"] = module.params["name"]
    request_post_data["action.notable.param.security_domain"] = module.params[
        "security_domain"
    ]
    request_post_data["action.notable.param.severity"] = module.params["severity"]
    request_post_data["action.notable.param.asset_extraction"] = module.params[
        "asset_extraction"
    ]
    request_post_data["action.notable.param.identity_extraction"] = module.params[
        "identity_extraction"
    ]

    # NOTE: this field appears to be hard coded when you create this via the splunk web UI
    #       but I don't know what it is/means because there's no docs on it
    request_post_data["action.notable.param.verbose"] = "0"

    if module.params["default_owner"]:
        request_post_data["action.notable.param.default_owner"] = module.params[
            "default_owner"
        ]

    if module.params["default_status"]:
        request_post_data["action.notable.param.default_status"] = module.params[
            "default_status"
        ]

    if query_dict:
        request_post_data["search"] = query_dict["entry"][0]["content"]["search"]
        if "actions" in query_dict["entry"][0]["content"]:
            if query_dict["entry"][0]["content"]["actions"] == "notable":
                pass
            elif (
                len(query_dict["entry"][0]["content"]["actions"].split(",")) > 0
                and "notable" not in query_dict["entry"][0]["content"]["actions"]
            ):
                request_post_data["actions"] = (
                    query_dict["entry"][0]["content"]["actions"] + ", notable"
                )
            else:
                request_post_data["actions"] = "notable"
    else:
        module.fail_json(
            msg="Unable to find correlation search: {0}", splunk_data=splunk_data
        )

    if module.params["state"] == "present":
        needs_change = False
        for arg in request_post_data:
            if arg in query_dict["entry"][0]["content"]:
                if to_text(query_dict["entry"][0]["content"][arg]) != to_text(
                    request_post_data[arg]
                ):
                    needs_change = True
        if not needs_change:
            module.exit_json(
                changed=False, msg="Nothing to do.", splunk_data=query_dict
            )
        if module.check_mode and needs_change:
            module.exit_json(
                changed=True,
                msg="A change would have been made if not in check mode.",
                splunk_data=query_dict,
            )
        if needs_change:
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}".format(
                    quote_plus(module.params["correlation_search_name"])
                ),
                data=urlencode(request_post_data),
            )
            module.exit_json(
                changed=True,
                msg="{0} updated.".format(module.params["correlation_search_name"]),
                splunk_data=splunk_data,
            )

    if module.params["state"] == "absent":
        # FIXME - need to figure out how to clear the action.notable.param fields from the api endpoint
        module.exit_json(
            changed=True,
            msg="Deleted {0}.".format(module.params["name"]),
            splunk_data=splunk_data,
        )
        for arg in request_post_data:
            if arg in query_dict["entry"][0]["content"]:
                needs_change = True
                del query_dict["entry"][0]["content"][arg]
        if not needs_change:
            module.exit_json(
                changed=False, msg="Nothing to do.", splunk_data=query_dict
            )
        if module.check_mode and needs_change:
            module.exit_json(
                changed=True,
                msg="A change would have been made if not in check mode.",
                splunk_data=query_dict,
            )
        if needs_change:
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}".format(
                    quote_plus(module.params["correlation_search_name"])
                ),
                data=urlencode(request_post_data),
            )
            module.exit_json(
                changed=True,
                msg="{0} updated.".format(module.params["correlation_search_name"]),
                splunk_data=splunk_data,
            )

    module.exit_json(changed=False, msg="Nothing to do.", splunk_data=query_dict)
예제 #4
0
def main():

    argspec = dict(
        name=dict(required=True, type="str"),
        state=dict(choices=["present", "absent"], required=True),
        blacklist=dict(required=False, type="str", default=None),
        check_index=dict(required=False, type="bool", default=False),
        check_path=dict(required=False, type="bool", default=None),
        crc_salt=dict(required=False, type="str", default=None),
        disabled=dict(required=False, type="bool", default=False),
        followTail=dict(required=False, type="bool", default=False),
        host=dict(required=False, type="str", default=None),
        host_segment=dict(required=False, type="int", default=None),
        host_regex=dict(required=False, type="str", default=None),
        ignore_older_than=dict(required=False, type="str", default=None),
        index=dict(required=False, type="str", default=None),
        recursive=dict(required=False, type="bool", default=False),
        rename_source=dict(required=False, type="str", default=None),
        sourcetype=dict(required=False, type="str", default=None),
        time_before_close=dict(required=False, type="int", default=None),
        whitelist=dict(required=False, type="str", default=None),
    )

    module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)

    # map of keys for the splunk REST API that aren't pythonic so we have to
    # handle the substitutes
    keymap = {
        "check_index": "check-index",
        "check_path": "check-path",
        "crc_salt": "crc-salt",
        "ignore_older_than": "ignore-older-than",
        "rename_source": "rename-source",
        "time_before_close": "time-before-close",
    }

    splunk_request = SplunkRequest(
        module,
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        keymap=keymap,
        not_rest_data_keys=["state"],
    )
    # This is where the splunk_* args are processed
    request_data = splunk_request.get_data()

    query_dict = splunk_request.get_by_path(
        "servicesNS/nobody/search/data/inputs/monitor/{0}".format(
            quote_plus(module.params["name"])))

    if module.params["state"] == "present":
        if query_dict:
            needs_change = False
            for arg in request_data:
                if arg in query_dict["entry"][0]["content"]:
                    if to_text(
                            query_dict["entry"][0]["content"][arg]) != to_text(
                                request_data[arg]):
                        needs_change = True
            if not needs_change:
                module.exit_json(changed=False,
                                 msg="Nothing to do.",
                                 splunk_data=query_dict)
            if module.check_mode and needs_change:
                module.exit_json(
                    changed=True,
                    msg="A change would have been made if not in check mode.",
                    splunk_data=query_dict,
                )
            if needs_change:
                splunk_data = splunk_request.create_update(
                    "servicesNS/nobody/search/data/inputs/monitor/{0}".format(
                        quote_plus(module.params["name"])))
                module.exit_json(changed=True,
                                 msg="{0} updated.",
                                 splunk_data=splunk_data)
        else:
            # Create it
            _data = splunk_request.get_data()
            _data["name"] = module.params["name"]
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/search/data/inputs/monitor",
                data=urlencode(_data))
            module.exit_json(changed=True,
                             msg="{0} created.",
                             splunk_data=splunk_data)

    if module.params["state"] == "absent":
        if query_dict:
            splunk_data = splunk_request.delete_by_path(
                "servicesNS/nobody/search/data/inputs/monitor/{0}".format(
                    quote_plus(module.params["name"])))
            module.exit_json(
                changed=True,
                msg="Deleted {0}.".format(module.params["name"]),
                splunk_data=splunk_data,
            )

    module.exit_json(changed=False,
                     msg="Nothing to do.",
                     splunk_data=query_dict)
예제 #5
0
def main():

    argspec = dict(
        name=dict(required=True, type="str"),
        description=dict(required=True, type="str"),
        state=dict(choices=["present", "absent", "enabled", "disabled"], required=True),
        search=dict(required=True, type="str"),
        app=dict(type="str", required=False, default="SplunkEnterpriseSecuritySuite"),
        ui_dispatch_context=dict(type="str", required=False),
        time_earliest=dict(type="str", required=False, default="-24h"),
        time_latest=dict(type="str", required=False, default="now"),
        cron_schedule=dict(type="str", required=False, default="*/5 * * * *"),
        scheduling=dict(
            type="str",
            required=False,
            default="real-time",
            choices=["real-time", "continuous"],
        ),
        schedule_window=dict(type="str", required=False, default="0"),
        schedule_priority=dict(
            type="str",
            required=False,
            default="Default",
            choices=["Default", "Higher", "Highest"],
        ),
        trigger_alert_when=dict(
            type="str",
            required=False,
            default="number of events",
            choices=[
                "number of events",
                "number of results",
                "number of hosts",
                "number of sources",
            ],
        ),
        trigger_alert_when_condition=dict(
            type="str",
            required=False,
            default="greater than",
            choices=[
                "greater than",
                "less than",
                "equal to",
                "not equal to",
                "drops by",
                "rises by",
            ],
        ),
        trigger_alert_when_value=dict(type="str", required=False, default="10"),
        throttle_window_duration=dict(type="str", required=False),
        throttle_fields_to_group_by=dict(type="str", required=False),
        suppress_alerts=dict(type="bool", required=False, default=False),
    )

    module = AnsibleModule(argument_spec=argspec, supports_check_mode=True)
    if module.params["state"] in ["present", "enabled"]:
        module_disabled_state = False
    else:
        module_disabled_state = True
    splunk_request = SplunkRequest(
        module,
        headers={"Content-Type": "application/x-www-form-urlencoded"},
        not_rest_data_keys=["state"],
    )

    try:
        query_dict = splunk_request.get_by_path(
            "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}".format(
                quote_plus(module.params["name"])
            )
        )
    except HTTPError as e:
        # the data monitor doesn't exist
        query_dict = {}

    # Have to custom craft the data here because they overload the saved searches
    # endpoint in the rest api and we want to hide the nuance from the user
    request_post_data = {}
    request_post_data["name"] = module.params["name"]
    request_post_data["action.correlationsearch.enabled"] = "1"
    request_post_data["is_scheduled"] = True
    request_post_data["dispatch.rt_backfill"] = True
    request_post_data["action.correlationsearch.label"] = module.params["name"]
    request_post_data["description"] = module.params["description"]
    request_post_data["search"] = module.params["search"]
    request_post_data["request.ui_dispatch_app"] = module.params["app"]
    if module.params["ui_dispatch_context"]:
        request_post_data["request.ui_dispatch_context"] = module.params[
            "ui_dispatch_context"
        ]
    request_post_data["dispatch.earliest_time"] = module.params["time_earliest"]
    request_post_data["dispatch.latest_time"] = module.params["time_latest"]
    request_post_data["cron_schedule"] = module.params["cron_schedule"]
    if module.params["scheduling"] == "real-time":
        request_post_data["realtime_schedule"] = True
    else:
        request_post_data["realtime_schedule"] = False
    request_post_data["schedule_window"] = module.params["schedule_window"]
    request_post_data["schedule_priority"] = module.params["schedule_priority"].lower()
    request_post_data["alert_type"] = module.params["trigger_alert_when"]
    request_post_data["alert_comparator"] = module.params[
        "trigger_alert_when_condition"
    ]
    request_post_data["alert_threshold"] = module.params["trigger_alert_when_value"]
    request_post_data["alert.suppress"] = module.params["suppress_alerts"]
    request_post_data["disabled"] = module_disabled_state

    if module.params["state"] in ["present", "enabled", "disabled"]:
        if query_dict:
            needs_change = False
            for arg in request_post_data:
                if arg in query_dict["entry"][0]["content"]:
                    if to_text(query_dict["entry"][0]["content"][arg]) != to_text(
                        request_post_data[arg]
                    ):
                        needs_change = True
            if not needs_change:
                module.exit_json(
                    changed=False, msg="Nothing to do.", splunk_data=query_dict
                )
            if module.check_mode and needs_change:
                module.exit_json(
                    changed=True,
                    msg="A change would have been made if not in check mode.",
                    splunk_data=query_dict,
                )
            if needs_change:
                # FIXME - need to find a reasonable way to deal with action.correlationsearch.enabled
                del request_post_data[
                    "name"
                ]  # If this is present, splunk assumes we're trying to create a new one wit the same name
                splunk_data = splunk_request.create_update(
                    "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches/{0}".format(
                        quote_plus(module.params["name"])
                    ),
                    data=urlencode(request_post_data),
                )
                module.exit_json(
                    changed=True, msg="{0} updated.", splunk_data=splunk_data
                )
        else:
            # Create it
            splunk_data = splunk_request.create_update(
                "servicesNS/nobody/SplunkEnterpriseSecuritySuite/saved/searches",
                data=urlencode(request_post_data),
            )
            module.exit_json(changed=True, msg="{0} created.", splunk_data=splunk_data)

    elif module.params["state"] == "absent":
        if query_dict:
            splunk_data = splunk_request.delete_by_path(
                "services/saved/searches/{0}".format(quote_plus(module.params["name"]))
            )
            module.exit_json(
                changed=True,
                msg="Deleted {0}.".format(module.params["name"]),
                splunk_data=splunk_data,
            )

    module.exit_json(changed=False, msg="Nothing to do.", splunk_data=query_dict)