def generate_code(args):
    """generate template code components from functions"""
    parser = AppArgumentParser(config_file=resilient.get_config_file())
    (opts, extra) = parser.parse_known_args()
    client = resilient.get_client(opts)

    if args.cmd == "extract" and args.output:
        extract_to_res(client, args.exportfile, args.messagedestination,
                       args.function, args.workflow, args.rule, args.field,
                       args.datatable, args.task, args.script,
                       args.artifacttype, args.output, args.zip)
    elif args.reload:
        codegen_reload_package(client, args)
    elif args.package:
        # codegen an installable package
        output_base = os.path.join(os.curdir, args.package)
        codegen_package(client, args.exportfile, args.package,
                        args.messagedestination, args.function, args.workflow,
                        args.rule, args.field, args.datatable, args.task,
                        args.script, args.artifacttype,
                        os.path.expanduser(output_base))
    elif args.function:
        # codegen a component for one or more functions
        if len(args.function) > 1:
            default_name = "functions.py"
        else:
            default_name = "{}.py".format(args.function[0])
        output_dir = os.path.expanduser(opts["componentsdir"] or os.curdir)
        output_file = args.output or default_name
        if not output_file.endswith(".py"):
            output_file = output_file + ".py"
        codegen_functions(client, args.exportfile, args.function,
                          args.workflow, args.rule, args.artifacttype,
                          output_dir, output_file)
Exemplo n.º 2
0
def test_global_integrations_options_commented_out(fx_clear_cmd_line_args):
    opts = AppArgumentParser(
        config_file=mock_paths.MOCK_COMMENTED_APP_CONFIG).parse_args().get(
            "integrations", {})
    assert opts.get("http_proxy") is None
    assert opts.get("https_proxy") is None
    assert opts.get("timeout") is None
Exemplo n.º 3
0
def test_global_integrations_options(fx_clear_cmd_line_args):
    opts = AppArgumentParser(
        config_file=mock_paths.MOCK_APP_CONFIG).parse_args().get(
            "integrations", {})
    assert opts.get("http_proxy") == "http://example.com:3000"
    assert opts.get("https_proxy") == "https://example.com:3000"
    assert opts.get("timeout") == "50"
Exemplo n.º 4
0
def customize_resilient(args):
    """import customizations to the resilient server"""
    parser = AppArgumentParser(config_file=resilient.get_config_file())
    (opts, extra) = parser.parse_known_args()
    client = resilient.get_client(opts)

    # Call each of the 'customize' entry points to get type definitions,
    # then apply them to the resilient server
    entry_points = pkg_resources.iter_entry_points('resilient.circuits.customize')
    do_customize_resilient(client, entry_points, args.yflag, args.install_list)
def selftest(args):
    """loop through every selftest for every eligible package, call and store returned state,
        print out package and their selftest states"""

    components = defaultdict(list)

    # custom entry_point only for selftest functions
    selftest_entry_points = [
        ep for ep in pkg_resources.iter_entry_points(
            'resilient.circuits.selftest')
    ]
    for ep in selftest_entry_points:
        components[ep.dist].append(ep)

    if len(selftest_entry_points) == 0:
        LOG.info("No selftest entry points found.")
        return None

    # Generate opts array necessary for ResilientComponent instantiation
    opts = AppArgumentParser(
        config_file=resilient.get_config_file()).parse_args("", None)

    # make a copy
    install_list = list(args.install_list) if args.install_list else []

    for dist, component_list in components.items():
        if args.install_list is None or dist.project_name in install_list:
            # remove name from list
            if dist.project_name in install_list:
                install_list.remove(dist.project_name)

            # add an entry for the package
            LOG.info("%s: ", dist.project_name)
            for ep in component_list:
                # load the entry point
                f_selftest = ep.load()

                try:
                    # f_selftest is the selftest function, we pass the selftest resilient options in case it wants to use it
                    start_time_milliseconds = int(round(time.time() * 1000))

                    status = f_selftest(opts)

                    end_time_milliseconds = int(round(time.time() * 1000))

                    delta_milliseconds = end_time_milliseconds - start_time_milliseconds
                    delta_seconds = delta_milliseconds / 1000

                    if status["state"] is not None:
                        LOG.info("\t%s: %s, Elapsed time: %f seconds", ep.name,
                                 status["state"], delta_seconds)
                except Exception as e:
                    LOG.error("Error while calling %s. Exception: %s", ep.name,
                              str(e))
                    continue

    # any missed packages?
    if len(install_list):
        LOG.warning("%s not found. Check package name(s)", install_list)
Exemplo n.º 6
0
    def do_function(self, arg):
        """Execute a function"""
        if not arg:
            print("function command requires a function-name")
            return

        parser = AppArgumentParser(config_file=resilient.get_config_file())
        (opts, more) = parser.parse_known_args()
        client = resilient.get_client(opts)

        args = iter(shlex.split(arg))
        try:
            function_name = next(args)
            function_def = client.get("/functions/{}?handle_format=names".format(function_name))
            param_defs = dict({fld["uuid"]: fld for fld in client.get("/types/__function/fields?handle_format=names")})
            function_params = {}
            for param in function_def["view_items"]:
                param_uuid = param["content"]
                param_def = param_defs[param_uuid]
                prompt = "{} ({}, {}): ".format(param_def["name"], param_def["input_type"], param_def["tooltip"])
                try:
                    arg = next(args)
                except StopIteration:
                    arg = None
                function_params[param_def["name"]] = get_input(param_def["input_type"], prompt, arg)

            action_message = {
                "function": {
                    "name": function_name
                },
                "inputs": function_params
            }
            message = json.dumps(action_message, indent=2)
            print(message)
            self._submit_action("function", message)
        except Exception as e:
            print(e)
    def on_modified(self, event):
        """ reload data from config file and restart components """
        if self.app.reloading:
            LOG.warning(
                "Configuration file change ignored because reload already in progress"
            )
            return

        LOG.info("Configuration file has changed! Notify components to reload")
        self.app.reloading = True
        opts = AppArgumentParser().parse_args()
        reload_event = reload(opts=opts)
        self.app.reload_timer = Timer(self.max_reload_time,
                                      Event.create("reload_timeout"))
        self.app.fire(reload_event)
        self.app.reload_timer.register(self.app)
def clone(args):
    parser = AppArgumentParser(config_file=resilient.get_config_file())
    (opts, extra) = parser.parse_known_args()
    client = resilient.get_client(opts)

    export_uri = "/configurations/exports/history"
    export_list = client.get(export_uri)["histories"]
    last_date = 0
    last_id = 0
    for export in export_list:
        if export["options"]["actions"] and export["options"][
                "phases_and_tasks"]:
            if export["date"] > last_date:
                last_date = export["date"]
                last_id = export["id"]
    if last_date == 0:
        LOG.error(
            u"ERROR: No suitable export is available.  "
            u"Create an export for code generation. (Administrator Settings -> Organization -> Export)."
        )
        return

    dt = datetime.datetime.utcfromtimestamp(last_date / 1000.0)
    LOG.info(
        u"Codegen is based on the organization export from {}.".format(dt))
    export_uri = "/configurations/exports/{}".format(last_id)
    export_data = client.get(export_uri)  # Get latest export

    new_export_data = export_data.copy()
    whitelist_dict_keys = ["incident_types", "fields"]  # Mandatory keys
    for dict_key in new_export_data:
        if dict_key not in whitelist_dict_keys and type(
                new_export_data[dict_key]) is list:
            new_export_data[dict_key] = [
            ]  # clear the new export data, the stuff we clear isn't necessary for cloning

    workflow_names = args.workflow  # names of workflow a (target) and b (new workflow)
    if workflow_names:  # if we're importing workflows
        if len(workflow_names) != 2:
            raise Exception(
                "Only specify the original workflow api name and a new workflow api name"
            )

        # Check that 'workflows' are available (v28 onward)
        workflow_defs = export_data.get("workflows")
        if workflow_defs is None:
            raise Exception("Export does not contain workflows")

        original_workflow_api_name = workflow_names[0]
        new_workflow_api_name = workflow_names[1]

        duplicate_check = find_workflow_by_programmatic_name(
            workflow_defs, new_workflow_api_name)
        if duplicate_check is not None:
            raise Exception(
                "Workflow with the api name {} already exists".format(
                    new_workflow_api_name))

        original_workflow = find_workflow_by_programmatic_name(
            workflow_defs, original_workflow_api_name)
        if original_workflow is None:
            raise Exception("Could not find original workflow {}".format(
                original_workflow_api_name))

        # This section just fills out the stuff we need to replace to duplicate
        new_workflow = original_workflow.copy()
        # Random UUID, not guaranteed to not collide but is extremely extremely extremely unlikely to collide
        new_workflow["uuid"] = str(uuid.uuid4())
        new_workflow["programmatic_name"] = new_workflow_api_name
        new_workflow["export_key"] = new_workflow_api_name
        old_workflow_name = new_workflow["name"]
        new_workflow["name"] = new_workflow_api_name
        new_workflow["content"]["workflow_id"] = new_workflow_api_name
        new_workflow["content"]["xml"] = new_workflow["content"][
            "xml"].replace(original_workflow_api_name, new_workflow_api_name)
        new_workflow["content"]["xml"] = new_workflow["content"][
            "xml"].replace(old_workflow_name, new_workflow_api_name)

        new_export_data["workflows"] = [new_workflow]

    uri = "/configurations/imports"
    result = client.post(uri, new_export_data)
    import_id = result[
        "id"]  # if this isn't here and the response code is 200 OK, something went really wrong

    if result["status"] == "PENDING":
        result["status"] = "ACCEPTED"  # Have to confirm changes
        uri = "/configurations/imports/{}".format(import_id)
        client.put(uri, result)
        LOG.info("Imported successfully")
    else:
        raise Exception(
            "Could not import because the server did not return an import ID")
def test_num_workers(fx_clear_cmd_line_args):

    # Test reading from app.config
    opts = AppArgumentParser(
        config_file=mock_paths.MOCK_APP_CONFIG).parse_args()
    assert isinstance(opts.get("num_workers"), int)
    assert opts.get("num_workers") == 5

    # Test default value - commented out in app.config
    opts = AppArgumentParser(
        config_file=mock_paths.MOCK_COMMENTED_APP_CONFIG).parse_args()
    assert isinstance(opts.get("num_workers"), int)
    assert opts.get("num_workers") == 10

    # Test overwriting
    sys.argv.extend(["--num-workers", "30"])
    opts = AppArgumentParser(
        config_file=mock_paths.MOCK_APP_CONFIG).parse_args()
    assert isinstance(opts.get("num_workers"), int)
    assert opts.get("num_workers") == 30
Exemplo n.º 10
0
def selftest(args):
    """loop through every selftest for every eligible package, call and store returned state,
        print out package and their selftest states"""

    components = defaultdict(list)

    # custom entry_point only for selftest functions
    selftest_entry_points = [ep for ep in pkg_resources.iter_entry_points('resilient.circuits.selftest')]
    for ep in selftest_entry_points:
        components[ep.dist].append(ep)

    if len(selftest_entry_points) == 0:
        LOG.info("No selftest entry points found.")
        return None

    # Generate opts array necessary for ResilientComponent instantiation
    opts = AppArgumentParser(config_file=resilient.get_config_file()).parse_args("", None);

    # make a copy
    install_list = list(args.install_list) if args.install_list else []

    # Prepare a count of exceptions found with selftests.
    selftest_failure_count = 0

    for dist, component_list in components.items():
        if args.install_list is None or dist.project_name in install_list:
            # remove name from list
            if dist.project_name in install_list:
                install_list.remove(dist.project_name)

            # add an entry for the package
            LOG.info("%s: ", dist.project_name)
            for ep in component_list:
                # load the entry point
                f_selftest = ep.load()

                try:
                    # f_selftest is the selftest function, we pass the selftest resilient options in case it wants to use it
                    start_time_milliseconds = int(round(time.time() * 1000))

                    status = f_selftest(opts)

                    end_time_milliseconds = int(round(time.time() * 1000))

                    delta_milliseconds = end_time_milliseconds - start_time_milliseconds
                    delta_seconds = delta_milliseconds / 1000

                    state = status.get("state")

                    if isinstance(state, str):
                        LOG.info("\t%s: %s\n\tselftest output:\n\t%s\n\tElapsed time: %f seconds", ep.name, state, status, delta_seconds)

                        if state.lower() == "failure":
                            selftest_failure_count += 1

                    else:
                        LOG.info("\t%s:\n\tUnsupported dictionary returned:\n\t%s\n\tElapsed time: %f seconds", ep.name, status, delta_seconds)

                except Exception as e:
                    LOG.error("Error while calling %s. Exception: %s", ep.name, str(e))
                    selftest_failure_count += 1
                    continue

    # any missed packages?
    if len(install_list):
        LOG.warning("%s not found. Check package name(s)", install_list)

    # Check if any failures were found and printed to the console
    if selftest_failure_count:
        sys.exit(SELFTEST_FAILURE_EXIT_CODE)
Exemplo n.º 11
0
def _get_opts():
    """
    Gets options from AppArgumentParser in the same manner as circuits does.
    """
    return AppArgumentParser().parse_args()
Exemplo n.º 12
0
def test_num_workers(fx_clear_cmd_line_args):

    # Test reading from app.config
    opts = AppArgumentParser(
        config_file=mock_paths.MOCK_APP_CONFIG).parse_args()
    assert isinstance(opts.get("num_workers"), int)
    assert opts.get("num_workers") == 5

    # Test default value - commented out in app.config
    opts = AppArgumentParser(
        config_file=mock_paths.MOCK_COMMENTED_APP_CONFIG).parse_args()
    assert isinstance(opts.get("num_workers"), int)
    assert opts.get("num_workers") == 10

    # Test overwriting
    sys.argv.extend(["--num-workers", "30"])
    opts = AppArgumentParser(
        config_file=mock_paths.MOCK_APP_CONFIG).parse_args()
    assert isinstance(opts.get("num_workers"), int)
    assert opts.get("num_workers") == 30

    # Test if over limit
    sys.argv.extend(["--num-workers", str(MAX_NUM_WORKERS + 1)])
    with pytest.raises(ValueError,
                       match=r"num_workers must be in the range .*"):
        AppArgumentParser(config_file=mock_paths.MOCK_APP_CONFIG).parse_args()
    NAME = "QRadar Offense Details"

    UUID = "d1ca8936-897b-4a83-8225-01c58db0470b"
    CONTAINS = [
        Field("qradar_id"),
        Field("qr_offense_index_type"),
        Field("qr_offense_index_value"),
        Field("qr_offense_source"),
        Field("qr_source_ip_count"),
        Field("qr_destination_ip_count"),
        Field("qr_event_count"),
        Field("qr_flow_count"),
        Field("qr_assigned"),
        Field("qr_magnitude"),
        Field("qr_credibility"),
        Field("qr_relevance"),
        Field("qr_severity"),
        Datatable("qr_offense_top_events"),
        Datatable("qr_flows"),
        Datatable("qr_triggered_rules"),
        Datatable("qr_top_destination_ips"),
        Datatable("qr_top_source_ips"),
        Datatable("qr_categories"),
        Datatable("qr_assets")
    ]

    SHOW_IF = [Field("qradar_id").conditions.has_value()]


create_tab(QRadarTab, AppArgumentParser().parse_args(), update_existing=True)
Exemplo n.º 14
0
 def setup_live_dlp_client(self):
     opts = AppArgumentParser(
         config_file=resilient.get_config_file()).parse_args("", None)
     return DLPSoapClient(
         app_configs=opts.get("fn_symantec_dlp", {}))