diff --git a/Packs/Automox/.pack-ignore b/Packs/Automox/.pack-ignore new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Packs/Automox/.secrets-ignore b/Packs/Automox/.secrets-ignore new file mode 100644 index 000000000000..cd1f2c5b1ecf --- /dev/null +++ b/Packs/Automox/.secrets-ignore @@ -0,0 +1,3 @@ +https://console.automox.com +https://developer.automox.com +http://fake-api.com diff --git a/Packs/Automox/Author_image.png b/Packs/Automox/Author_image.png new file mode 100644 index 000000000000..7bb79749ab69 Binary files /dev/null and b/Packs/Automox/Author_image.png differ diff --git a/Packs/Automox/Integrations/Automox/Automox.py b/Packs/Automox/Integrations/Automox/Automox.py new file mode 100644 index 000000000000..c53102ec0e16 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/Automox.py @@ -0,0 +1,966 @@ +"""Automox Integration for Cortex XSOAR (aka Demisto) + +This integration empowers users of Cortex XSOAR with the +capabilities provided by the Automox API. + +Organization, group, device, policy, and patch management all at your fingertips. + +For API reference, visit: https://developer.automox.com/ +""" + +import time +import traceback +from typing import Any, Dict, List + +import demistomock as demisto +import requests +from CommonServerPython import * # noqa # pylint: disable=unused-wildcard-import +from CommonServerUserPython import * # noqa + +# Disable insecure warnings +requests.packages.urllib3.disable_warnings() # pylint: disable=no-member + +''' CONSTANTS ''' +VERSION = "1.0.0" +USER_AGENT = f'ax:PaloAltoNetworks-XSOAR-plugin/{VERSION}' +DATE_FORMAT = '%Y-%m-%dT%H:%M:%SZ' # ISO8601 format with UTC, default in XSOAR + +# Common keys used in command arguments +ORG_IDENTIFIER = 'org_id' +DEVICE_IDENTIFIER = 'device_id' +GROUP_IDENTIFIER = 'group_id' +LIMIT_IDENTIFIER = 'limit' +PAGE_IDENTIFIER = 'page' + +OUTCOME_FAIL = "failure" +OUTCOME_SUCCESS = "success" + +DEFAULT_ORG_ID = demisto.params().get(ORG_IDENTIFIER, None) + +''' CLIENT CLASS ''' + + +class Client(BaseClient): + + """Client class to interact with the service API + + This Client implements API calls, and does not contain any XSOAR logic. + Should only do requests and return data. + It inherits from BaseClient defined in CommonServer Python. + Most calls use _http_request() that handles proxy, SSL verification, etc. + For this implementation, no special attributes defined + """ + + def _get_list_results(self, method: str, url_suffix: str, params: dict) -> List[Dict]: + results = [] + + result_limit = int(params['limit']) + page_limit = 250 if int(params['limit']) > 250 else int(params['limit']) + + params['limit'] = page_limit + + while result_limit > 0: + response = self._http_request( + method=method, + url_suffix=url_suffix, + params=params + ) + + # This is necessary for vuln sync, since those responses have metadata & data keys. + if isinstance(response, dict) and isinstance(response['data'], list): + response = response['data'] + + if (result_limit < page_limit): + results += response[:result_limit] + else: + results += response + + if len(response) < page_limit: + break + + result_limit -= len(response) + + params['page'] += 1 + + return results + + def report_api_outcome(self, outcome: str, function: str, elapsed_time: int, fail_reason: str = ""): + try: + url_suffix = "/integration-health" + + data = { + "name": "cortex-xsoar", + "version": VERSION, + "function": function, + "outcome": outcome, + "elapsed_time": elapsed_time + } + + if outcome == OUTCOME_FAIL: + data['reason_for_failure'] = fail_reason + + self._http_request( + method="POST", + url_suffix=url_suffix, + data=data, + resp_type='response' + ) + except DemistoException: + # Do nothing + return + + def action_on_vulnerability_sync_batch(self, org_id: int, batch_id: int, action: str): + url_suffix = f"/orgs/{org_id}/tasks/batches/{batch_id}/" + + if action in ["accept", "reject"]: + url_suffix += f"{action}" + else: + raise ValueError("Action argument must be a string equal to either 'accept' or 'reject'") + + return self._http_request( + method='POST', + url_suffix=url_suffix, + resp_type="response", + ) + + def action_on_vulnerability_sync_task(self, org_id: int, task_id: int, action: str): + payload = { + "action": action, + } + + return self._http_request( + method="PATCH", + url_suffix=f"/orgs/{org_id}/tasks/{task_id}", + data=payload, + resp_type="response", + ) + + def delete_device(self, org_id: int, device_id: int) -> List[Dict]: + params = { + "o": org_id, + } + + return self._http_request( + method="DELETE", + url_suffix=f"/servers/{device_id}", + params=params, + resp_type="response", + ) + + def delete_group(self, org_id: int, group_id: int) -> List[Dict]: + params = { + "o": org_id, + } + + return self._http_request( + method="DELETE", + url_suffix=f"/servergroups/{group_id}", + params=params, + resp_type="response", + ) + + def get_vulnerability_sync_batch(self, org_id: int, batch_id: int) -> List[Dict]: + return self._http_request( + method="GET", + url_suffix=f"/orgs/{org_id}/tasks/batches/{batch_id}", + ) + + def list_devices(self, org_id: int, group_id: int, limit: int, page: int) -> List[Dict]: + params = { + "o": org_id, + "groupId": group_id, + "limit": limit, + "page": page, + } + + results = self._get_list_results( + method="GET", + url_suffix="/servers", + params=params + ) + + return results + + def list_groups(self, org_id: int, limit: int, page: int) -> List[Dict]: + params = { + "o": org_id, + "limit": limit, + "page": page, + } + + results = self._get_list_results( + method="GET", + url_suffix="/servergroups", + params=params + ) + + return results + + def list_organization_users(self, org_id: int, limit: int, page: int) -> List[Dict]: + params = { + "o": org_id, + "limit": limit, + "page": page, + } + + results = self._get_list_results( + method="GET", + url_suffix="/users", + params=params + ) + + return results + + def list_organizations(self, limit: int, page: int) -> List[Dict]: + params = { + "limit": limit, + "page": page, + } + + results = self._get_list_results( + method="GET", + url_suffix="/orgs", + params=params + ) + + return results + + def list_policies(self, org_id, limit, page) -> List[Dict]: + params = { + "limit": limit, + "page": page, + "o": org_id, + } + + results = self._get_list_results( + method="GET", + url_suffix="/policies", + params=params, + ) + + return results + + def list_vulnerability_sync_batches(self, org_id, limit, page) -> List[Dict]: + params = { + "limit": limit, + "page": page, + } + + results = self._get_list_results( + method="GET", + url_suffix=f"/orgs/{org_id}/tasks/batches", + params=params, + ) + + return results + + def list_vulnerability_sync_tasks(self, org_id, batch_id, status, limit, page) -> List[Dict]: + params = { + "limit": limit, + "page": page, + "batch_id": batch_id, + "status": status + } + + results = self._get_list_results( + method="GET", + url_suffix=f"/orgs/{org_id}/tasks", + params=params, + ) + + return results + + def run_command(self, org_id, device_id, payload) -> List[Dict]: + params = { + "o": org_id, + } + + return self._http_request( + method="POST", + url_suffix=f"/servers/{device_id}/queues", + params=params, + data=payload, + ) + + def update_device(self, org_id, device_id, payload) -> List[Dict]: + params = { + "o": org_id, + } + + return self._http_request( + method="PUT", + url_suffix=f"/servers/{device_id}", + params=params, + json_data=payload, + resp_type="response", + ) + + def update_group(self, org_id, group_id, payload) -> List[Dict]: + params = { + "o": org_id, + } + + return self._http_request( + method="PUT", + url_suffix=f"/servergroups/{group_id}", + params=params, + json_data=payload, + resp_type="response", + ) + + def upload_vulnerability_sync_file(self, org_id, type, payload, files) -> Dict[str, Any]: + return self._http_request( + method="POST", + url_suffix=f"/orgs/{org_id}/tasks/{type}/batches/upload", + data=payload, + files=files, + ) + + def get_group(self, org_id, group_id) -> Dict[str, Any]: + params = { + "o": org_id, + } + + return self._http_request( + method="GET", + url_suffix=f"/servergroups/{group_id}", + params=params + ) + + def get_device(self, org_id, device_id) -> Dict[str, Any]: + params = { + "o": org_id, + } + + return self._http_request( + method="GET", + url_suffix=f"/servers/{device_id}", + params=params + ) + + def create_group(self, org_id, payload) -> List[Dict]: + params = { + "o": org_id, + } + + return self._http_request( + method="POST", + url_suffix="/servergroups", + params=params, + data=payload, + ) + + +''' HELPER FUNCTIONS ''' + + +def remove_keys(excluded_keys_list: List[str], data: Dict[str, Any]) -> Dict[str, Any]: + for key_string in excluded_keys_list: + keys = key_string.split(".") + data = remove_key(keys, data) + + return data + + +def remove_key(keys_to_traverse: List[str], data: Dict[str, Any]) -> Dict[str, Any]: + try: + key = keys_to_traverse[0] + + # If we've reached the last key in the list to traverse we can just drop it. + if len(keys_to_traverse) == 1: + del data[key] + return data + + # Lists and dicts require us to move on with traversal. + if isinstance(data[key], dict): + data[key] = remove_key(keys_to_traverse[1:], data[key]) + elif isinstance(data[key], list): + for i in range(len(data[key])): + data[key][i] = remove_key(keys_to_traverse[1:], data[key][i]) + else: + del data[key] + + except Exception: + demisto.error(f"Key '{key}' not found in Automox response.") + + return data + + +def get_default_server_group_id(client: Client, org_id): + default_server_group_id = None + page = 0 + + while default_server_group_id is None: + groups = client.list_groups(org_id, 250, page) + + for group in groups: + if not group.get("name"): + default_server_group_id = group.get("id") + break + + page += 1 + + return default_server_group_id + + +''' COMMAND FUNCTIONS ''' + + +def test_module(client: Client) -> str: + """Tests API connectivity and authentication' + + Returning 'ok' indicates that the integration works like it is supposed to. + Connection to the service is successful. + Raises exceptions if something goes wrong. + + :type client: ``Client`` + :param Client: client to use + + :return: 'ok' if test passed, anything else will fail the test. + :rtype: ``str`` + """ + + message: str = '' + try: + start_time = time.time() + + client.list_organizations(limit=1, page=0) + message = 'ok' + + end_time = time.time() + elapsed_time = int(end_time - start_time) + + client.report_api_outcome(OUTCOME_SUCCESS, "connection_test", elapsed_time) + except DemistoException as e: + if 'Forbidden' in str(e) or 'Authorization' in str(e): + message = 'Authorization Error: make sure API Key is correctly set' + else: + end_time = time.time() + elapsed_time = int(end_time - start_time) + failure_message = "Unable to list orgs during api test." + + client.report_api_outcome(OUTCOME_FAIL, "connection_test", elapsed_time, failure_message) + + raise e + return message + + +def action_on_vulnerability_sync_batch(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + batch_id = args.get('batch_id', None) + action = args.get('action', None) + + client.action_on_vulnerability_sync_batch(org_id, batch_id, action) + + return CommandResults( + mark_as_note=True, + readable_output=f"Action: {action} successfully performed on Automox batch ID: {batch_id}" + ) + + +def action_on_vulnerability_sync_task(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + task_id = args.get('task_id', None) + action = args.get('action', None) + + client.action_on_vulnerability_sync_task(org_id, task_id, action) + + return CommandResults( + mark_as_note=True, + readable_output=f"Action: {action} successfully performed on Automox task ID: {task_id}" + ) + + +def create_group(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + + color = args.get('color', None) + name = args.get('name', None) + notes = args.get('notes', None) + refresh_interval = args.get('refresh_interval', None) + parent_server_group_id = args.get('parent_server_group_id', None) or get_default_server_group_id(client, org_id) + + policy_list = args.get('policies', "").split(",") + map(str.strip, policy_list) + + payload = { + "color": color, + "name": name, + "notes": notes, + "parent_server_group_id": parent_server_group_id, + "policies": policy_list, + "refresh_interval": refresh_interval, + } + + result = client.create_group(org_id, payload) + + return CommandResults( + outputs_prefix="Automox.CreatedGroups", + outputs_key_field='id', + outputs=result, + ) + + +def delete_device(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + device_id = args.get(DEVICE_IDENTIFIER, None) + + client.delete_device(org_id, device_id) + + result = { + "id": device_id, + "deleted": True, + } + + return CommandResults( + outputs_prefix="Automox.Devices", + outputs_key_field="id", + outputs=result, + mark_as_note=True, + readable_output=f"Device: {device_id} successfully deleted from Automox" + ) + + +def delete_group(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + group_id = args.get(GROUP_IDENTIFIER, None) + + client.delete_group(org_id, group_id) + + result = { + "id": group_id, + "deleted": True, + } + + return CommandResults( + outputs_prefix="Automox.Groups", + outputs_key_field="id", + outputs=result, + mark_as_note=True, + readable_output=f"Group: {group_id} successfully deleted from Automox" + ) + + +def get_vulnerability_sync_batch(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + batch_id = args.get('batch_id', None) + + result = client.get_vulnerability_sync_batch(org_id, batch_id) + + return CommandResults( + outputs_prefix="Automox.VulnSyncBatch", + outputs_key_field='id', + outputs=result, + ) + + +def list_devices(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + group_id = args.get(GROUP_IDENTIFIER, None) + limit = int(args.get(LIMIT_IDENTIFIER, None)) + page = int(args.get(PAGE_IDENTIFIER, None)) + + result = client.list_devices(org_id, group_id, limit, page) + + excluded_keys = [ + 'compatibility_checks', + 'os_version_id', + 'instance_id', + 'detail', + 'total_count', + ] + + for i in range(len(result)): + result[i] = remove_keys(excluded_keys, result[i]) + + return CommandResults( + outputs_prefix="Automox.Devices", + outputs_key_field='id', + outputs=result, + ) + + +def list_groups(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + limit = int(args.get(LIMIT_IDENTIFIER, None)) + page = int(args.get(PAGE_IDENTIFIER, None)) + + result = client.list_groups(org_id, limit, page) + + excluded_keys = [ + "wsus_config", + ] + + for i in range(len(result)): + result[i] = remove_keys(excluded_keys, result[i]) + result[i]['deleted'] = False + + return CommandResults( + outputs_prefix="Automox.Groups", + outputs_key_field='id', + outputs=result, + ) + + +def list_organization_users(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + limit = int(args.get(LIMIT_IDENTIFIER, None)) + page = int(args.get(PAGE_IDENTIFIER, None)) + + result = client.list_organization_users(org_id, limit, page) + + excluded_keys = [ + 'features', + 'prefs', + 'orgs.trial_end_time', + 'orgs.trial_expired', + 'orgs.access_key', + ] + + for i in range(len(result)): + result[i] = remove_keys(excluded_keys, result[i]) + + return CommandResults( + outputs_prefix="Automox.Users", + outputs_key_field='id', + outputs=result, + ) + + +def list_organizations(client: Client, args: Dict[str, Any]) -> CommandResults: + limit = int(args.get(LIMIT_IDENTIFIER, None)) + page = int(args.get(PAGE_IDENTIFIER, None)) + result = client.list_organizations(limit, page) + + excluded_keys = [ + 'addr1', + 'bill_overages', + 'addr2', + 'access_key', + 'legacy_billing', + 'sub_systems', + 'stripe_cust', + 'sub_plan', + 'cc_brand', + 'billing_interval', + 'billing_phone', + 'cc_name', + 'city', + 'zipcode', + 'billing_name', + 'metadata', + 'sub_end_time', + 'state', + 'sub_create_time', + 'cc_last', + 'country', + 'billing_email', + 'next_bill_time', + 'billing_interval_count', + 'rate_id', + 'trial_end_time', + 'trial_expired', + 'cc_exp', + ] + + for i in range(len(result)): + result[i] = remove_keys(excluded_keys, result[i]) + + return CommandResults( + outputs_prefix="Automox.Organizations", + outputs_key_field='id', + outputs=result, + ) + + +def list_policies(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + limit = int(args.get(LIMIT_IDENTIFIER, None)) + page = int(args.get(PAGE_IDENTIFIER, None)) + + excluded_keys = [ + "configuration", + "schedule_days", + "schedule_weeks_of_month", + "schedule_months", + "schedule_time", + ] + + result = client.list_policies(org_id, limit, page) + + for i in range(len(result)): + result[i] = remove_keys(excluded_keys, result[i]) + + return CommandResults( + outputs_prefix="Automox.Policies", + outputs_key_field='id', + outputs=result, + ) + + +def list_vulnerability_sync_batches(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + limit = int(args.get(LIMIT_IDENTIFIER, None)) + page = int(args.get(PAGE_IDENTIFIER, None)) + + result = client.list_vulnerability_sync_batches(org_id, limit, page) + + return CommandResults( + outputs_prefix="Automox.VulnSyncBatches", + outputs_key_field='id', + outputs=result, + ) + + +def list_vulnerability_sync_tasks(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + batch_id = args.get('batch_id', None) + status = args.get('status', None) + limit = int(args.get(LIMIT_IDENTIFIER, None)) + page = int(args.get(PAGE_IDENTIFIER, None)) + + result = client.list_vulnerability_sync_tasks(org_id, batch_id, status, limit, page) + + excluded_keys = [ + 'partner_user_id', + ] + + for i in range(len(result)): + result[i] = remove_keys(excluded_keys, result[i]) + + return CommandResults( + outputs_prefix="Automox.VulnSyncTasks", + outputs_key_field='id', + outputs=result, + ) + + +def run_command(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + device_id = args.get(DEVICE_IDENTIFIER, None) + command_type_name = args.get('command', None) + patches = args.get('patches', None) + + payload = { + 'command_type_name': command_type_name, + 'args': patches + } + + client.run_command(org_id, device_id, payload) + + return CommandResults( + mark_as_note=True, + readable_output=f"Command: {command_type_name} successfully sent to Automox device ID: {device_id}" + ) + + +def update_device(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + device_id = args.get(DEVICE_IDENTIFIER, None) + + # Get original group to coalesce updated values to + original_device = client.get_device(org_id, device_id) + + tag_list = args.get('tags', None) + if tag_list is not None: + tag_list = tag_list.split(",") + map(str.strip, tag_list) + + ip_list = args.get('ip_addrs', None) + if ip_list is not None: + ip_list = ip_list.split(",") + map(str.strip, ip_list) + + server_group_id = args.get('server_group_id', None) or original_device['server_group_id'] + custom_name = args.get('custom_name', None) or original_device['custom_name'] + tags = tag_list or original_device['tags'] + ip_addrs = ip_list or original_device['ip_addrs'] + exception = args.get('exception', None) or original_device['exception'] + + payload = { + "server_group_id": server_group_id, + "ip_addrs": ip_addrs, + "exception": bool(exception), + "tags": tags, + "custom_name": custom_name, + } + + client.update_device(org_id, device_id, payload) + + return CommandResults( + mark_as_note=True, + readable_output=f"Device: {device_id} successfully updated in Automox" + ) + + +def update_group(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + group_id = args.get(GROUP_IDENTIFIER, None) + + # Get original group to coalesce updated values to + original_group = client.get_group(org_id, group_id) + + color = args.get('color', None) or original_group['ui_color'] + name = args.get('name', None) or original_group['name'] + notes = args.get('notes', None) or original_group['notes'] + parent_server_group_id = args.get('parent_server_group_id', None) or original_group['parent_server_group_id'] + refresh_interval = args.get('refresh_interval', None) or original_group['refresh_interval'] + + policies = args.get('policies', None) + if policies is not None: + policies = policies.split(",") + + map(str.strip, policies) if policies else original_group['policies'] + + payload = { + "color": color, + "name": name, + "notes": notes, + "parent_server_group_id": parent_server_group_id, + "policies": policies, + "refresh_interval": refresh_interval, + } + + client.update_group(org_id, group_id, payload) + + return CommandResults( + mark_as_note=True, + readable_output=f"Group: {group_id} ({name}) successfully updated in Automox." + ) + + +def upload_vulnerability_sync_file(client: Client, args: Dict[str, Any]) -> CommandResults: + org_id = args.get(ORG_IDENTIFIER, None) or DEFAULT_ORG_ID + report_source = args.get('report_source', None) + entry_id = args.get('entry_id', None) + csv_file_name = args.get('csv_file_name', None) + task_type = args.get('type', None) or "patch" + + res = demisto.getFilePath(entry_id) + + if not res: + demisto.error(f"File entry: {entry_id} not found") + + with open(res['path'], 'rb') as csv_file: + payload = { + "report_source": report_source, + } + + files = [ + ('file', (csv_file_name, csv_file, 'text/csv')) + ] + + result = client.upload_vulnerability_sync_file(org_id, task_type, payload, files) + + result = { + 'batch_id': result['id'] + } + + return CommandResults( + outputs_prefix="Automox.VulnUpload", + outputs_key_field='batch_id', + outputs=result, + ) + + +''' MAIN FUNCTION ''' + + +def main() -> None: + """main function, parses params and runs command functions + + :return: + :rtype: + """ + + api_key = demisto.params().get('credentials', {}).get('password') + + # get the service API url + base_url = "https://console.automox.com/api" + + # if your Client class inherits from BaseClient, SSL verification is + # handled out of the box by it, just pass ``verify_certificate`` to + # the Client constructor + verify_certificate = not demisto.params().get('insecure', False) + + # if your Client class inherits from BaseClient, system proxy is handled + # out of the box by it, just pass ``proxy`` to the Client constructor + proxy = demisto.params().get('proxy', False) + + demisto.debug(f'Command being called is {demisto.command()}') + try: + headers: Dict = { + "Authorization": f"Bearer {api_key}", + "User-Agent": USER_AGENT + } + + client = Client( + base_url=base_url, + verify=verify_certificate, + headers=headers, + proxy=proxy) + + if demisto.command() == 'test-module': + # This is the call made when pressing the integration Test button. + result = test_module(client) + return_results(result) + elif demisto.command() == 'automox-vulnerability-sync-batch-action': + return_results(action_on_vulnerability_sync_batch(client, demisto.args())) + elif demisto.command() == 'automox-vulnerability-sync-task-action': + return_results(action_on_vulnerability_sync_task(client, demisto.args())) + elif demisto.command() == 'automox-group-create': + return_results(create_group(client, demisto.args())) + elif demisto.command() == 'automox-device-delete': + return_results(delete_device(client, demisto.args())) + elif demisto.command() == 'automox-group-delete': + return_results(delete_group(client, demisto.args())) + elif demisto.command() == 'automox-vulnerability-sync-batch-get': + return_results(get_vulnerability_sync_batch(client, demisto.args())) + elif demisto.command() == 'automox-devices-list': + return_results(list_devices(client, demisto.args())) + elif demisto.command() == 'automox-groups-list': + return_results(list_groups(client, demisto.args())) + elif demisto.command() == 'automox-organization-users-list': + return_results(list_organization_users(client, demisto.args())) + elif demisto.command() == 'automox-organizations-list': + return_results(list_organizations(client, demisto.args())) + elif demisto.command() == 'automox-policies-list': + return_results(list_policies(client, demisto.args())) + elif demisto.command() == 'automox-vulnerability-sync-batches-list': + return_results(list_vulnerability_sync_batches(client, demisto.args())) + elif demisto.command() == 'automox-vulnerability-sync-tasks-list': + return_results(list_vulnerability_sync_tasks(client, demisto.args())) + elif demisto.command() == 'automox-command-run': + return_results(run_command(client, demisto.args())) + elif demisto.command() == 'automox-device-update': + return_results(update_device(client, demisto.args())) + elif demisto.command() == 'automox-group-update': + return_results(update_group(client, demisto.args())) + elif demisto.command() == 'automox-vulnerability-sync-file-upload': + return_results(upload_vulnerability_sync_file(client, demisto.args())) + + # Log exceptions and return errors + except DemistoException as err: + res = err.res + + if res.status_code == 404: + message = "The requested Automox resource could not be found." + elif res.status_code == 403: + message = "You do not have access to this Automox resource." + else: + message = "Something went wrong. Your command could not be executed." + + results = CommandResults( + mark_as_note=True, + readable_output=message + ) + + return_results(results) + except Exception as err: + demisto.error(traceback.format_exc()) # print the traceback + return_error(f'Failed to execute {demisto.command()} command.\nError:\n{str(err)}') + + +''' ENTRY POINT ''' +if __name__ in ('__main__', '__builtin__', 'builtins'): + main() diff --git a/Packs/Automox/Integrations/Automox/Automox.yml b/Packs/Automox/Integrations/Automox/Automox.yml new file mode 100644 index 000000000000..9774642061f4 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/Automox.yml @@ -0,0 +1,1110 @@ +category: Endpoint +commonfields: + id: Automox + version: -1 +configuration: +- display: Organization ID + additionalinfo: When specified, data pulled from Automox will only belong to this organization; otherwise, the default permissions for this API key will be used. + name: org_id + required: false + type: 0 +- displaypassword: API Key + additionalinfo: The API Key to use for connection + name: credentials + required: true + hiddenusername: true + type: 9 +- display: Trust any certificate (not secure) + name: insecure + required: false + type: 8 +- display: Use system proxy settings + name: proxy + required: false + type: 8 +description: 'Administrate your IT organization from XSOAR with comprehensive commands for the Automox platform.' +display: Automox +name: Automox +script: + commands: + - name: automox-devices-list + description: 'List all devices in Automox based on group and organization permissions.' + arguments: + - name: org_id + description: 'Organization ID' + default: false + isArray: false + required: false + secret: false + - name: group_id + description: 'Group ID' + default: false + isArray: false + required: false + secret: false + - name: limit + description: 'The maximum number of results to return per page.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 50 + secret: false + - name: page + description: 'The page of results to return.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 0 + secret: false + deprecated: false + execution: false + outputs: + - contextPath: Automox.Devices.id + description: 'Identifier of device' + type: Number + - contextPath: Automox.Devices.server_group_id + description: 'Identifier of server group' + type: Number + - contextPath: Automox.Devices.organization_id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.Devices.uuid + description: 'The Automox UUID of a device' + type: String + - contextPath: Automox.Devices.name + description: 'The name of a device' + type: String + - contextPath: Automox.Devices.refresh_interval + description: 'Frequency of device refreshes in minutes' + type: Number + - contextPath: Automox.Devices.last_update_time + description: 'The last time a device was updated in Automox' + type: String + - contextPath: Automox.Devices.last_refresh_time + description: 'The last time a device was refreshed in Automox' + type: String + - contextPath: Automox.Devices.uptime + description: 'The device uptime in minutes' + type: Number + - contextPath: Automox.Devices.needs_reboot + description: 'Whether a device needs to be rebooted' + type: Boolean + - contextPath: Automox.Devices.timezone + description: 'The device timezone' + type: String + - contextPath: Automox.Devices.tags + description: 'List of tags for the device' + type: String + - contextPath: Automox.Devices.deleted + description: 'Whether a device is deleted' + type: Boolean + - contextPath: Automox.Devices.create_time + description: 'The time a device was created in Automox' + type: Date + - contextPath: Automox.Devices.os_version + description: 'The operating system version of a device' + type: String + - contextPath: Automox.Devices.os_name + description: 'The operating system name of a device' + type: String + - contextPath: Automox.Devices.os_family + description: 'the operating system family of a device' + type: String + - contextPath: Automox.Devices.ip_addrs + description: 'List of IP addresses for a device' + type: String + - contextPath: Automox.Devices.ip_addrs_private + description: 'List of private IP addresses for a device' + type: String + - contextPath: Automox.Devices.patches + description: 'The number of patches currently identified for a device' + type: Number + - contextPath: Automox.Devices.agent_version + description: 'The version of the Automox agent on the device' + type: String + - contextPath: Automox.Devices.custom_name + description: 'The Automox specific custom name for the device' + type: String + - contextPath: Automox.Devices.is_compatible + description: 'Whether a device is compatible with Automox' + type: Boolean + - contextPath: Automox.Devices.policy_status.id + description: 'Identifier of policy' + type: Number + - contextPath: Automox.Devices.policy_status.organization_id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.Devices.policy_status.policy_name + description: 'Name of the policy' + type: String + - contextPath: Automox.Devices.policy_status.policy_type_name + description: 'Type of the policy' + type: String + - contextPath: Automox.Devices.policy_status.status + description: 'Current status of the policy' + type: Number + - contextPath: Automox.Devices.policy_status.result + description: 'Result of the policy' + type: String + - contextPath: Automox.Devices.policy_status.create_time + description: 'Policy created datetime' + type: Datetime + - contextPath: Automox.Devices.last_scan_failed + description: 'Whether the last scan failed on a device' + type: Boolean + - contextPath: Automox.Devices.pending + description: 'Whether work is pending on a device' + type: Boolean + - contextPath: Automox.Devices.compliant + description: 'Whether a device is compliant' + type: Boolean + - contextPath: Automox.Devices.display_name + description: 'The display name of a device' + type: String + - contextPath: Automox.Devices.commands.command_type_name + description: 'The type of a command previously issued on a device' + type: String + - contextPath: Automox.Devices.commands.args + description: 'The arguments of a command previously issued on a device' + type: String + - contextPath: Automox.Devices.commands.exec_time + description: 'The execution time of a command previously issued on a device' + type: Date + - contextPath: Automox.Devices.pending_patches + description: 'The number of pending patches for a device' + type: Number + - contextPath: Automox.Devices.connected + description: 'Whether a device is currently connected to Automox' + type: Boolean + - contextPath: Automox.Devices.last_process_time + description: 'The last time the device was processed' + type: String + - contextPath: Automox.Devices.next_patch_time + description: 'The next time the device is patched' + type: String + - contextPath: Automox.Devices.notification_count + description: 'The number of notifications for the device' + type: Number + - contextPath: Automox.Devices.reboot_notification_count + description: 'The number of reboot notifications for a device' + type: Number + - contextPath: Automox.Devices.patch_deferral_count + description: 'The number of patch deferrals for a device' + type: Number + - contextPath: Automox.Devices.is_delayed_by_notification + description: 'Whether a patch is delayed by notifications' + type: Boolean + - contextPath: Automox.Devices.reboot_is_delayed_by_notification + description: 'Whether a reboot is delayed by notifications' + type: Boolean + - contextPath: Automox.Devices.is_delayed_by_user + description: 'Whether a patch is delayed by the user' + type: Boolean + - contextPath: Automox.Devices.reboot_is_delayed_by_user + description: 'Whether a reboot is delayed by the user' + type: Boolean + - contextPath: Automox.Devices.last_disconnect_time + description: 'Last time a device disconnected from Automox' + type: Date + - contextPath: Automox.Devices.needs_attention + description: 'Whether a device currently needs attention' + type: Boolean + - contextPath: Automox.Devices.serial_number + description: 'The device serial number' + type: String + - contextPath: Automox.Devices.status.device_status + description: 'The status of a device' + type: String + - contextPath: Automox.Devices.status.agent_status + description: 'The status of a device agent' + type: String + - contextPath: Automox.Devices.status.policy_status + description: 'The overall status of all policies assigned to a device' + type: String + - contextPath: Automox.Devices.status.policy_statuses.id + description: 'The identifier of the policy' + type: Number + - contextPath: Automox.Devices.status.policy_statuses.compliant + description: 'Whether a device is compliant to a given status' + type: Boolean + - contextPath: Automox.Devices.last_logged_in_user + description: 'The last logged in user of a device' + type: String + - name: automox-organizations-list + arguments: + - name: limit + description: 'The maximum number of results to return per page.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 50 + secret: false + - name: page + description: 'The page of results to return.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 0 + secret: false + deprecated: false + description: 'List all Automox organizations based on user permissions.' + execution: false + outputs: + - contextPath: Automox.Organizations.id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.Organizations.name + description: 'Name of organization' + type: String + - contextPath: Automox.Organizations.create_time + description: 'The datetime when the organization was created' + type: Date + - contextPath: Automox.Organizations.server_limit + description: 'The organization server limit' + type: Number + - contextPath: Automox.Organizations.parent_id + description: 'The organization parent id' + type: Number + - contextPath: Automox.Organizations.device_limit + description: 'The organization device limit' + type: Number + - contextPath: Automox.Organizations.device_count + description: 'The organization device count' + type: Number + - name: automox-organization-users-list + description: 'List all Automox users within an organization.' + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: limit + description: 'The maximum number of results to return per page.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 50 + secret: false + - name: page + description: 'The page of results to return.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 0 + secret: false + deprecated: false + execution: false + outputs: + - contextPath: Automox.Users.id + description: 'Identifier of user' + type: Number + - contextPath: Automox.Users.firstname + description: 'The first name of the user' + type: String + - contextPath: Automox.Users.lastname + description: 'The last name of the user' + type: String + - contextPath: Automox.Users.email + description: 'The email of the user' + type: String + - contextPath: Automox.Users.orgs.id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.Users.orgs.name + description: 'Name of organization' + type: String + - contextPath: Automox.Users.tags + description: 'User tags' + type: String + - contextPath: Automox.Users.saml_enabled + description: 'Whether SAML has been enabled for the user' + type: Boolean + - contextPath: Automox.Users.rbac_roles.id + description: 'The RBAC role identifier' + type: Number + - contextPath: Automox.Users.rbac_roles.name + description: 'The RBAC role name' + type: String + - contextPath: Automox.Users.rbac_roles.organization_id + description: 'Identifier of organization' + type: Number + - name: automox-vulnerability-sync-batch-action + description: 'Perform an action on an Automox Vulnerability Sync batch.' + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: batch_id + description: 'Batch identifier' + type: 'number' + isArray: false + required: true + default: false + secret: false + - name: action + description: 'Action to perform on the batch specified. Options are "accept" or "reject".' + auto: PREDEFINED + predefined: + - accept + - reject + isArray: false + required: true + default: false + secret: false + deprecated: false + execution: false + - name: automox-vulnerability-sync-task-action + description: 'Perform an action on an Automox task.' + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: batch_id + description: 'Batch identifier' + type: 'number' + isArray: false + required: true + default: false + secret: false + - name: action + description: 'Action to perform on the batch specified. Options are "accept" or "reject".' + auto: PREDEFINED + predefined: + - accept + - reject + isArray: false + required: true + default: false + secret: false + deprecated: false + execution: false + - name: automox-vulnerability-sync-batch-get + description: 'Get details about a Vulnerability Sync batch.' + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: batch_id + description: 'Batch identifier' + type: 'number' + isArray: false + required: true + default: false + secret: false + outputs: + - contextPath: Automox.VulnSyncBatch.id + description: 'Identifier of batch' + type: Number + - contextPath: Automox.VulnSyncBatch.organization_id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.VulnSyncBatch.status + description: 'Status of batch' + type: String + - contextPath: Automox.VulnSyncBatch.source + description: 'Originating vendor of vulnerability information' + type: String + - contextPath: Automox.VulnSyncBatch.created_by.id + description: 'The identifier of the user who created this batch' + type: Number + - contextPath: Automox.VulnSyncBatch.created_by.firstname + description: 'The first name of the user who created this batch' + type: String + - contextPath: Automox.VulnSyncBatch.created_by.lastname + description: 'The last name of the user who created this batch' + type: String + - contextPath: Automox.VulnSyncBatch.created_by.email + description: 'The email of the user who created this batch' + type: String + - contextPath: Automox.VulnSyncBatch.updated_by.id + description: 'The identifier of the user who last updated this batch' + type: Number + - contextPath: Automox.VulnSyncBatch.updated_by.firstname + description: 'The first name of the user who last updated this batch' + type: String + - contextPath: Automox.VulnSyncBatch.updated_by.lastname + description: 'The last name of the user who last updated this batch' + type: String + - contextPath: Automox.VulnSyncBatch.updated_by.email + description: 'The email of the user who last updated this batch' + type: String + - contextPath: Automox.VulnSyncBatch.uploaded_at + description: 'Datetime of initial upload' + type: Date + - contextPath: Automox.VulnSyncBatch.task_count + description: 'Number of tasks related to batch' + type: Number + - contextPath: Automox.VulnSyncBatch.unknown_host_count + description: 'Number of hosts that are unknown within batch' + type: Number + - contextPath: Automox.VulnSyncBatch.impacted_device_count + description: 'Number of devices impacted by batch' + type: Number + - contextPath: Automox.VulnSyncBatch.issue_count + description: 'Number of issues identified with batch' + type: Number + - contextPath: Automox.VulnSyncBatch.cve_count + description: 'Number of CVEs impacted by batch' + type: Number + - name: automox-vulnerability-sync-batches-list + description: 'Get a list of Vulnerability Sync batches.' + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: limit + description: 'The maximum number of results to return per page.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 50 + secret: false + - name: page + description: 'The page of results to return.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 0 + secret: false + outputs: + - contextPath: Automox.VulnSyncBatches.id + description: 'Identifier of batch' + type: Number + - contextPath: Automox.VulnSyncBatches.organization_id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.VulnSyncBatches.status + description: 'Status of batch' + type: String + - contextPath: Automox.VulnSyncBatches.source + description: 'Source of batch' + type: String + - contextPath: Automox.VulnSyncBatches.created_by.id + description: 'Identifier of user who created the batch' + type: Number + - contextPath: Automox.VulnSyncBatches.created_by.firstname + description: 'First name of the user who created the batch' + type: String + - contextPath: Automox.VulnSyncBatches.created_by.lastname + description: 'Last name of the user who created the batch' + type: String + - contextPath: Automox.VulnSyncBatches.created_by.email + description: 'Email of the user who created the batch' + type: String + - contextPath: Automox.VulnSyncBatches.updated_by.id + description: 'Identifier of the user who last updated the batch' + type: Number + - contextPath: Automox.VulnSyncBatches.updated_by.firstname + description: 'First name of the user who last updated the batch' + type: String + - contextPath: Automox.VulnSyncBatches.updated_by.lastname + description: 'Last name of the user who last updated the batch' + type: String + - contextPath: Automox.VulnSyncBatches.updated_by.email + description: 'Email off the user who last updated the batch' + type: String + - contextPath: Automox.VulnSyncBatches.uploaded_at + description: 'Datetime the batch was uploaded' + type: Date + - contextPath: Automox.VulnSyncBatches.task_count + description: 'Number of tasks related to batch' + type: Number + - contextPath: Automox.VulnSyncBatches.unknown_host_count + description: 'number of hosts that are unknown within batch' + type: Number + - contextPath: Automox.VulnSyncBatches.impacted_device_count + description: 'Number of devices that are impacted by batch' + type: Number + - contextPath: Automox.VulnSyncBatches.issue_count + description: 'Number of issues identified with batch' + type: Number + - contextPath: Automox.VulnSyncBatches.cve_count + description: 'Number of CVEs that are impacted by batch' + type: Number + - name: automox-vulnerability-sync-tasks-list + description: 'Get a list of Automox tasks.' + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: batch_id + description: 'Batch identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: status + description: 'Filter by status of tasks' + type: 'string' + auto: PREDEFINED + predefined: + - pending + - in_progress + - completed + - canceled + isArray: false + required: false + default: false + secret: false + - name: limit + description: 'The maximum number of results to return per page.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 50 + secret: false + - name: page + description: 'The page of results to return.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 0 + secret: false + outputs: + - contextPath: Automox.VulnSyncTasks.id + description: 'Identifier of task' + type: Number + - contextPath: Automox.VulnSyncTasks.organization_id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.VulnSyncTasks.task_type + description: 'Type of task' + type: String + - contextPath: Automox.VulnSyncTasks.payload.patch_id + description: 'Identifier of patch associated with the task' + type: String + - contextPath: Automox.VulnSyncTasks.payload.severity + description: 'Severity of patch associated with the task' + type: String + - contextPath: Automox.VulnSyncTasks.payload.package_versions.id + description: 'Identifier of package associated with the task' + type: String + - contextPath: Automox.VulnSyncTasks.payload.package_versions.name + description: 'Name of the package associated with the task' + type: String + - contextPath: Automox.VulnSyncTasks.payload.package_versions.version + description: 'Version of the package associated with the task' + type: String + - contextPath: Automox.VulnSyncTasks.payload.package_versions.display_name + description: 'Display name of the package associated with the task' + type: String + - contextPath: Automox.VulnSyncTasks.payload.package_versions.requires_reboot + description: 'Whether the package installed by the task will require a reboot' + type: Boolean + - contextPath: Automox.VulnSyncTasks.source + description: 'Source of task' + type: String + - contextPath: Automox.VulnSyncTasks.notes + description: 'Notes associated with task' + type: String + - contextPath: Automox.VulnSyncTasks.status + description: 'Status of task' + type: String + - contextPath: Automox.VulnSyncTasks.created_by_user.id + description: 'Identifier of user who created the task' + type: Number + - contextPath: Automox.VulnSyncTasks.created_by_user.email + description: 'Email of user who created the task' + type: String + - contextPath: Automox.VulnSyncTasks.created_by_user.firstname + description: 'First name of user who created the task' + type: String + - contextPath: Automox.VulnSyncTasks.created_by_user.lastname + description: 'Last name of user who created the task' + type: String + - contextPath: Automox.VulnSyncTasks.last_updated_by_user.id + description: 'Identifier of user who last updated the task' + type: Number + - contextPath: Automox.VulnSyncTasks.last_updated_by_user.email + description: 'Email of user who last updated the task' + type: String + - contextPath: Automox.VulnSyncTasks.last_updated_by_user.firstname + description: 'First name of user who last updated the task' + type: String + - contextPath: Automox.VulnSyncTasks.last_updated_by_user.lastname + description: 'Last name of user who last updated the task' + type: String + - contextPath: Automox.VulnSyncTasks.created_at + description: 'Datetime the task was created at' + type: Date + - contextPath: Automox.VulnSyncTasks.updated_at + description: 'Datetime the task was last updated at' + type: Date + - contextPath: Automox.VulnSyncTasks.completed_at + description: 'Datetime the task was completed' + type: Date + - name: automox-vulnerability-sync-file-upload + description: 'Upload a vulnerability report to Automox Vulnerability Sync.' + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: entry_id + description: 'Entry ID of the CSV file to upload' + type: 'string' + isArray: false + required: true + default: false + secret: false + - name: csv_file_name + description: 'Name for CSV file uploaded and shown within Automox.' + type: 'string' + isArray: false + required: false + default: false + defaultValue: 'XSOAR-uploaded-report.csv' + secret: false + - name: reports_source + description: 'The third-party source of the vulnerability report.' + type: 'string' + isArray: false + required: false + default: false + defaultValue: 'Generic Report' + secret: false + - name: type + description: 'The type of task to create.' + type: 'string' + isArray: false + required: false + default: false + defaultValue: 'patch' + secret: false + deprecated: false + execution: false + outputs: + - contextPath: Automox.VulnUpload.batch_id + description: 'Identifier of batch' + type: Number + - name: automox-policies-list + description: 'Retrieve a list of Automox policies belonging to an organization.' + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: limit + description: 'The maximum number of results to return per page.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 50 + secret: false + - name: page + description: 'The page of results to return.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 0 + secret: false + deprecated: false + execution: false + outputs: + - contextPath: Automox.Policies.id + description: 'Identifier of policy' + type: Number + - contextPath: Automox.Policies.organization_id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.Policies.name + description: 'Name of policy' + type: String + - contextPath: Automox.Policies.policy_type_name + description: 'Policy type name' + type: String + - contextPath: Automox.Policies.server_groups + description: 'List of identifiers for device groups assigned to the policy' + type: Number + - name: automox-command-run + description: 'Run a command on a device in Automox' + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: device_id + description: 'Device identifier' + type: 'number' + isArray: false + required: true + default: false + secret: false + - name: patches + description: 'List of patches to be installed by name. (Note: this only works with the InstallUpdate command)' + type: 'string' + isArray: true + required: false + default: false + secret: false + - name: command + description: 'Command to run on device' + type: 'String' + auto: PREDEFINED + predefined: + - GetOS + - InstallUpdate + - InstallAllUpdates + - Reboot + isArray: false + required: true + default: false + secret: false + deprecated: false + execution: false + outputs: + - name: automox-device-delete + description: "Delete a device from Automox" + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: device_id + description: 'Device identifier' + type: 'number' + isArray: false + required: true + default: false + secret: false + deprecated: false + execution: false + - name: automox-device-update + description: "Update a device's information in Automox" + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: device_id + description: 'Device identifier' + type: 'number' + isArray: false + required: true + default: false + secret: false + - name: custom_name + description: 'Custom name to set on device' + type: 'string' + isArray: false + required: false + default: false + secret: false + - name: exception + description: 'Exclude the device from reports and statistics' + type: Boolean + isArray: false + required: true + default: false + defaultValue: false + secret: false + - name: server_group_id + description: 'Identifier of server group' + type: Number + isArray: false + required: true + default: false + secret: false + - name: tags + description: 'List of tags to associate with the device' + type: String + isArray: true + required: false + default: false + secret: false + - name: ip_addrs + description: 'IP address of the device' + type: String + isArray: false + required: false + default: false + secret: false + deprecated: false + execution: false + - name: automox-groups-list + description: "List all groups in Automox based on organization permissions." + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: limit + description: 'The maximum number of results to return per page.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 50 + secret: false + - name: page + description: 'The page of results to return.' + type: 'number' + isArray: false + required: false + default: false + defaultValue: 0 + secret: false + deprecated: false + execution: false + outputs: + - contextPath: Automox.Groups.id + description: 'Identifier of the created group' + type: Number + - contextPath: Automox.Groups.organization_id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.Groups.name + description: 'The name of the group' + type: String + - contextPath: Automox.Groups.refresh_interval + description: 'Frequency of device refreshes in minutes.' + type: Number + - contextPath: Automox.Groups.parent_server_group_id + description: 'Identifier of parent group' + type: Number + - contextPath: Automox.Groups.ui_color + description: 'Automox console highlight color for the group' + type: String + - contextPath: Automox.Groups.notes + description: 'Notes defined for the group' + type: String + - contextPath: Automox.Groups.enable_os_auto_update + description: 'Enable operating system auto updates' + type: Boolean + - contextPath: Automox.Groups.server_count + description: 'Number of devices assigned to group' + type: Number + - contextPath: Automox.Groups.policies + description: 'List of policies assigned to group' + type: Number + - contextPath: Automox.Groups.deleted + description: 'Whether a group is deleted' + type: Boolean + - name: automox-group-create + description: "Create a group in Automox" + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: name + description: 'Name of the group' + type: String + isArray: false + required: true + default: false + secret: false + - name: notes + description: 'Define notes for the group' + type: String + isArray: false + required: false + default: false + secret: false + - name: parent_server_group_id + description: 'Identifier of the parent group. Defaults to default group id if omitted.' + type: Number + isArray: false + required: false + default: false + secret: false + - name: policies + description: 'List of policy identifiers to assign to group' + type: Number + isArray: true + required: false + default: false + secret: false + - name: refresh_interval + description: 'Frequency of device refreshes in minutes. (Must be between 360 and 1440)' + type: Number + isArray: false + required: true + default: false + secret: false + - name: color + description: 'Automox console highlight color for the group. Value should be a valid Hex color code' + type: String + isArray: false + required: false + default: false + secret: false + deprecated: false + execution: false + outputs: + - contextPath: Automox.CreatedGroups.id + description: 'Identifier of the created group' + type: Number + - contextPath: Automox.CreatedGroups.organization_id + description: 'Identifier of organization' + type: Number + - contextPath: Automox.CreatedGroups.name + description: 'The name of the group' + type: String + - contextPath: Automox.CreatedGroups.refresh_interval + description: 'Frequency of device refreshes in minutes' + type: Number + - contextPath: Automox.CreatedGroups.parent_server_group_id + description: 'Identifier of parent group' + type: Number + - contextPath: Automox.CreatedGroups.ui_color + description: 'Automox console highlight color for the group' + type: String + - contextPath: Automox.CreatedGroups.notes + description: 'Notes defined for the group' + type: String + - contextPath: Automox.CreatedGroups.enable_os_auto_update + description: 'Enable operating system auto updates' + type: Boolean + - contextPath: Automox.CreatedGroups.server_count + description: 'Number of devices assigned to group' + type: Number + - contextPath: Automox.CreatedGroups.policies + description: 'List of policies assigned to group' + type: Number + - name: automox-group-update + description: "Update a group's information in Automox" + arguments: + - name: org_id + description: 'Organization identifier' + type: 'number' + isArray: false + required: false + default: false + secret: false + - name: group_id + description: 'Group identifier' + type: 'number' + isArray: false + required: true + default: false + secret: false + - name: name + description: 'Name of the group' + type: String + isArray: false + required: false + default: false + secret: false + - name: notes + description: 'Define notes for the group' + type: String + isArray: false + required: false + default: false + secret: false + - name: parent_server_group_id + description: 'Identifier of the parent group. Defaults to default group id if omitted.' + type: Number + isArray: false + required: false + default: false + secret: false + - name: policies + description: 'List of policy identifiers to assign to group' + type: Number + isArray: true + required: false + default: false + secret: false + - name: refresh_interval + description: 'Frequency of device refreshes in minutes' + type: Number + isArray: false + required: false + default: false + secret: false + - name: color + description: 'Automox console highlight color for the group. Value should be a valid Hex color code' + type: String + isArray: false + required: false + default: false + secret: false + deprecated: false + execution: false + - name: automox-group-delete + description: "Delete a group from Automox" + arguments: + - name: org_id + description: 'Organization identifier' + type: Number + isArray: false + required: false + default: false + secret: false + - name: group_id + description: 'Group identifier' + type: Number + isArray: false + required: true + default: false + secret: false + deprecated: false + execution: false + isfetch: false + runonce: false + script: '-' + type: python + subtype: python3 + dockerimage: demisto/python3:3.10.4.28442 +fromversion: 6.0.0 +tests: +- No tests diff --git a/Packs/Automox/Integrations/Automox/Automox_description.md b/Packs/Automox/Integrations/Automox/Automox_description.md new file mode 100644 index 000000000000..8af79a083f61 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/Automox_description.md @@ -0,0 +1,9 @@ +# Automox Help + +## Configuring your Automox XSOAR Instance +In order for the XSOAR Automox Integration to authenticate with the Automox API, you'll need to get an API key from the Automox console. Here's how: +* Navigate to the [Automox console](https://console.automox.com/) and log in. +* Once you're logged in, navigate to the "Keys" page under "Settings". +* Here you can add a new key for XSOAR (recommended), or use an existing one. + +For more information about managing keys, please read our [support article](https://support.automox.com/help/managing-keys) about it (with pictures!) diff --git a/Packs/Automox/Integrations/Automox/Automox_image.png b/Packs/Automox/Integrations/Automox/Automox_image.png new file mode 100644 index 000000000000..7bb79749ab69 Binary files /dev/null and b/Packs/Automox/Integrations/Automox/Automox_image.png differ diff --git a/Packs/Automox/Integrations/Automox/Automox_test.py b/Packs/Automox/Integrations/Automox/Automox_test.py new file mode 100644 index 000000000000..f09871d0ca8e --- /dev/null +++ b/Packs/Automox/Integrations/Automox/Automox_test.py @@ -0,0 +1,511 @@ +"""Automox Integration for Cortex XSOAR - Unit Tests file + +Pytest Unit Tests: all funcion names must start with "test_" + +More details: https://xsoar.pan.dev/docs/integrations/unit-testing + +MAKE SURE YOU REVIEW/REPLACE ALL THE COMMENTS MARKED AS "TODO" + +You must add at least a Unit Test function for every XSOAR command +you are implementing with your integration +""" + +import json +import io +import demistomock as demisto +from Automox import Client + +TEST_URL = "http://fake-api.com" + + +def util_load_json(path): + with io.open(path, mode='r', encoding='utf-8') as f: + return json.loads(f.read()) + + +def util_mock_client(): + + return Client( + base_url=TEST_URL, + verify=False, + headers=None, + proxy=False + ) + + +def test_remove_keys(): + from Automox import remove_keys + + test_data = { + "keep": { + "remove": True, + }, + "remove": [ + { + "remove": True, + }, + { + "remove": True, + } + ], + "foo": { + "bar": True, + "remove": True, + } + } + + exclude_keys = [ + "remove", + "foo.remove", + ] + + sanitized_data = remove_keys(exclude_keys, test_data) + + assert 'remove' in sanitized_data['keep'] + assert 'remove' not in sanitized_data + assert 'remove' not in sanitized_data['foo'] + assert 'bar' in sanitized_data['foo'] + + +def test_remove_key(): + from Automox import remove_key + + test_data = { + "keep": { + "remove": True, + }, + "remove": [ + { + "remove": True, + }, + { + "remove": True, + } + ], + } + + keys_to_traverse = ['remove', 'remove'] + + sanitized_data = remove_key(keys_to_traverse, test_data) + + assert 'remove' not in sanitized_data['remove'][0] + assert 'remove' not in sanitized_data['remove'][1] + assert 'keep' in sanitized_data + + +def test_get_default_server_group_id(requests_mock): + from Automox import get_default_server_group_id + + client = util_mock_client() + expected_response = util_load_json("./test_data/automox-groups-list.json") + + requests_mock.get(f"{TEST_URL}/servergroups", json=expected_response) + + org_id = 1 + result = get_default_server_group_id(client, org_id) + + assert result == 1 + + +def test_action_on_vulnerability_sync_batch(requests_mock): + from Automox import action_on_vulnerability_sync_batch + + org_id = 1 + batch_id = 1 + + requests_mock.post(f"{TEST_URL}/orgs/{org_id}/tasks/batches/{batch_id}/accept", status_code=204) + requests_mock.post(f"{TEST_URL}/orgs/{org_id}/tasks/batches/{batch_id}/reject", status_code=204) + + client = util_mock_client() + + args = { + "org_id": org_id, + "batch_id": batch_id, + "action": "accept" + } + + result = action_on_vulnerability_sync_batch(client, args) + + assert "Action: accept" in result.readable_output + assert "ID: 1" in result.readable_output + + args = { + "org_id": org_id, + "batch_id": batch_id, + "action": "reject" + } + + result = action_on_vulnerability_sync_batch(client, args) + + assert "Action: reject" in result.readable_output + assert "ID: 1" in result.readable_output + + +def test_action_on_vulnerability_sync_task(requests_mock): + from Automox import action_on_vulnerability_sync_task + + org_id = 1 + task_id = 1 + + requests_mock.patch(f"/orgs/{org_id}/tasks/{task_id}", status_code=204) + + args = { + 'org_id': org_id, + 'task_id': task_id, + 'action': "execute", + } + + client = util_mock_client() + result = action_on_vulnerability_sync_task(client, args) + + assert "Action: execute" in result.readable_output + assert "ID: 1" in result.readable_output + + args = { + 'org_id': org_id, + 'task_id': task_id, + 'action': "cancel", + } + + result = action_on_vulnerability_sync_task(client, args) + + assert "Action: cancel" in result.readable_output + assert "ID: 1" in result.readable_output + + +def test_create_group(requests_mock): + from Automox import create_group + + org_id = 1 + + expected_response = util_load_json("./test_data/automox-group-create.json") + requests_mock.post(f"{TEST_URL}/servergroups", json=expected_response) + + args = { + 'color': '#FFFFFF', + 'name': 'Test Group', + 'notes': 'My notes', + 'refresh_interval': 360, + 'parent_server_group_id': 1, + 'policy_list': [0], + } + + client = util_mock_client() + result = create_group(client, args) + group = result.outputs + + assert group['ui_color'] == args['color'] + assert group['name'] == args['name'] + assert group['notes'] == args['notes'] + assert group['refresh_interval'] == args['refresh_interval'] + assert group['parent_server_group_id'] == args['parent_server_group_id'] + assert group['policies'] == args['policy_list'] + assert group['organization_id'] == org_id + + +def test_delete_device(requests_mock): + from Automox import delete_device + org_id = 1 + device_id = 123 + + requests_mock.delete(f"{TEST_URL}/servers/{device_id}") + + args = { + 'org_id': org_id, + 'device_id': device_id, + } + + client = util_mock_client() + result = delete_device(client, args) + + assert f"Device: {device_id}" in result.readable_output + + +def test_delete_group(requests_mock): + from Automox import delete_group + org_id = 1 + group_id = 1 + + requests_mock.delete(f"{TEST_URL}/servergroups/{group_id}") + + args = { + 'org_id': org_id, + 'group_id': group_id, + } + + client = util_mock_client() + result = delete_group(client, args) + + assert f"Group: {group_id}" in result.readable_output + + +def test_get_vulnerability_sync_batch(requests_mock): + from Automox import get_vulnerability_sync_batch + org_id = 1 + batch_id = 1 + + expected_response = util_load_json("./test_data/automox-vulnerability-sync-batch-get.json") + requests_mock.get(f"{TEST_URL}/orgs/{org_id}/tasks/batches/{batch_id}", json=expected_response) + + args = { + 'org_id': org_id, + 'batch_id': batch_id + } + + client = util_mock_client() + result = get_vulnerability_sync_batch(client, args) + + assert result.outputs_prefix == "Automox.VulnSyncBatch" + assert result.outputs['id'] == 1 + assert result.outputs['organization_id'] == 1 + + +def test_list_devices(requests_mock): + from Automox import list_devices + + expected_response = util_load_json("./test_data/automox-devices-list.json") + requests_mock.get(f"{TEST_URL}/servers", json=expected_response) + + client = util_mock_client() + + args = { + 'org_id': 1, + 'group_id': 10, + 'limit': 50, + 'page': 0, + } + + result = list_devices(client, args) + + outputs = result.outputs + + assert result.outputs_prefix == "Automox.Devices" + assert len(outputs) == 1 + assert "detail" not in outputs[0] + + +def test_list_groups(requests_mock): + from Automox import list_groups + org_id = 1 + + expected_response = util_load_json("./test_data/automox-groups-list.json") + requests_mock.get(f"{TEST_URL}/servergroups", json=expected_response) + + args = { + 'org_id': org_id, + 'limit': 50, + 'page': 0, + } + + client = util_mock_client() + result = list_groups(client, args) + + assert result.outputs_prefix == "Automox.Groups" + assert "wsus_config" not in result.outputs[0] + assert result.outputs[0]['organization_id'] == org_id + + +def test_list_organization_users(requests_mock): + from Automox import list_organization_users + org_id = 1 + + expected_response = util_load_json("./test_data/automox-organization-users-list.json") + requests_mock.get(f"{TEST_URL}/users", json=expected_response) + + args = { + 'org_id': org_id, + 'limit': 50, + 'page': 0, + } + + client = util_mock_client() + result = list_organization_users(client, args) + + assert result.outputs_prefix == "Automox.Users" + assert "prefs" not in result.outputs[0] + assert result.outputs[0]['orgs'][0]['id'] == org_id + + +def test_list_organizations(requests_mock): + from Automox import list_organizations + + expected_response = util_load_json("./test_data/automox-organizations-list.json") + requests_mock.get(f"{TEST_URL}/orgs", json=expected_response) + + args = { + "limit": 50, + "page": 0, + } + + client = util_mock_client() + result = list_organizations(client, args) + + assert result.outputs_prefix == "Automox.Organizations" + assert "addr1" not in result.outputs[0] + + +def test_list_policies(requests_mock): + from Automox import list_policies + org_id = 1 + + expected_response = util_load_json("./test_data/automox-policies-list.json") + requests_mock.get(f"{TEST_URL}/policies", json=expected_response) + + args = { + "org_id": org_id, + "limit": 50, + "page": 0, + } + + client = util_mock_client() + result = list_policies(client, args) + + assert result.outputs_prefix == "Automox.Policies" + assert result.outputs[0]['organization_id'] == org_id + + +def test_list_vulnerability_sync_batches(requests_mock): + from Automox import list_vulnerability_sync_batches + org_id = 1 + + expected_response = util_load_json("./test_data/automox-vulnerability-sync-batches-list.json") + requests_mock.get(f"{TEST_URL}/orgs/{org_id}/tasks/batches", json=expected_response) + + args = { + 'org_id': org_id, + 'limit': 50, + 'page': 0, + } + + client = util_mock_client() + result = list_vulnerability_sync_batches(client, args) + + assert result.outputs_prefix == "Automox.VulnSyncBatches" + assert result.outputs[0]['organization_id'] == org_id + + +def test_list_vulnerability_sync_tasks(requests_mock): + from Automox import list_vulnerability_sync_tasks + org_id = 10586 + batch_id = 1 + + expected_response = util_load_json("./test_data/automox-vulnerability-sync-tasks-list.json") + requests_mock.get(f"{TEST_URL}/orgs/{org_id}/tasks", json=expected_response) + + args = { + 'org_id': org_id, + 'batch_id': batch_id, + 'status': None, + 'limit': 50, + 'page': 0, + } + + client = util_mock_client() + result = list_vulnerability_sync_tasks(client, args) + + assert result.outputs_prefix == "Automox.VulnSyncTasks" + assert result.outputs[0]['organization_id'] == org_id + + +def test_run_command(requests_mock): + from Automox import run_command + org_id = 1 + device_id = 1 + command_type_name = "GetOS" + args = "" + + requests_mock.post(f"{TEST_URL}/servers/{device_id}/queues", status_code=201, json={}) + + args = { + 'org_id': org_id, + 'device_id': device_id, + 'command': command_type_name, + 'args': args, + } + + client = util_mock_client() + result = run_command(client, args) + + assert f"Command: {command_type_name}" in result.readable_output + assert f"device ID: {device_id}" in result.readable_output + + +def test_update_device(requests_mock): + from Automox import update_device + device_id = 1 + + expected_response = util_load_json("./test_data/automox-device-get.json") + requests_mock.get(f"{TEST_URL}/servers/{device_id}", json=expected_response) + requests_mock.put(f"{TEST_URL}/servers/{device_id}", status_code=204) + + args = { + 'device_id': device_id, + 'server_group_id': 1, + 'custom_name': "Custom name string", + 'tags': "tag1,tag2", + 'ip_addrs': "1.1.1.1", + 'exception': False, + } + + client = util_mock_client() + result = update_device(client, args) + + assert f"Device: {device_id}" in result.readable_output + + +def test_update_group(requests_mock): + from Automox import update_group + group_id = 1 + name = "Test Group" + + expected_response = util_load_json("./test_data/automox-groups-list.json") + requests_mock.get(f"{TEST_URL}/servergroups/{group_id}", json=expected_response) + requests_mock.put(f"{TEST_URL}/servergroups/{group_id}", status_code=204, json={}) + + args = { + 'group_id': group_id, + 'color': '#FFFFFF', + 'name': name, + 'notes': 'My notes', + 'refresh_interval': 360, + 'parent_server_group_id': 1, + 'policies': "0", + } + + client = util_mock_client() + result = update_group(client, args) + + assert f"Group: {group_id} ({name})" in result.readable_output + + +def test_upload_vulnerability_sync_file(requests_mock, mocker): + from Automox import upload_vulnerability_sync_file + org_id = 10586 + report_source = "Generic Report" + entry_id = "123" + csv_file_name = "report.csv" + task_type = "patch" + + expected_response = util_load_json("./test_data/automox-vulnerability-sync-file-upload.json") + requests_mock.post(f"{TEST_URL}/orgs/{org_id}/tasks/{task_type}/batches/upload", json=expected_response) + + mock_file = { + 'id': 'test_id', + 'path': 'test_data/xsoar_vuln_test.csv', + 'name': 'xsoar_vuln_test.csv', + } + mocker.patch.object(demisto, 'getFilePath', return_value=mock_file) + + args = { + 'org_id': org_id, + 'report_source': report_source, + 'entry_id': entry_id, + 'csv_file_name': csv_file_name, + 'task_type': task_type, + } + + client = util_mock_client() + result = upload_vulnerability_sync_file(client, args) + + assert result.outputs_prefix == "Automox.VulnUpload" + assert result.outputs['batch_id'] > 0 diff --git a/Packs/Automox/Integrations/Automox/Pipfile b/Packs/Automox/Integrations/Automox/Pipfile new file mode 100644 index 000000000000..3523d3b6b93b --- /dev/null +++ b/Packs/Automox/Integrations/Automox/Pipfile @@ -0,0 +1,18 @@ +[[source]] +name = "pypi" +url = "https://pypi.org/simple" +verify_ssl = true + +[dev-packages] +pylint = "*" +pytest = "==5.0.1" +pytest-mock = "*" +requests-mock = "*" +pytest-asyncio = "*" + +[packages] +pytest = "*" +requests = "*" + +[requires] +python_version = "3.7" diff --git a/Packs/Automox/Integrations/Automox/Pipfile.lock b/Packs/Automox/Integrations/Automox/Pipfile.lock new file mode 100644 index 000000000000..6bdb9313414e --- /dev/null +++ b/Packs/Automox/Integrations/Automox/Pipfile.lock @@ -0,0 +1,369 @@ +{ + "_meta": { + "hash": { + "sha256": "278db815bec49c11262633d34305f9b33f09432a223bedd5329a04f758f78b55" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "3.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "atomicwrites": { + "hashes": [ + "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", + "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" + ], + "version": "==1.3.0" + }, + "attrs": { + "hashes": [ + "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", + "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" + ], + "version": "==19.1.0" + }, + "certifi": { + "hashes": [ + "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", + "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" + ], + "version": "==2019.9.11" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "idna": { + "hashes": [ + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + ], + "version": "==2.8" + }, + "importlib-metadata": { + "hashes": [ + "sha256:652234b6ab8f2506ae58e528b6fbcc668831d3cc758e1bc01ef438d328b68cdb", + "sha256:6f264986fb88042bc1f0535fa9a557e6a376cfe5679dc77caac7fe8b5d43d05f" + ], + "markers": "python_version < '3.8'", + "version": "==0.22" + }, + "more-itertools": { + "hashes": [ + "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", + "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" + ], + "version": "==7.2.0" + }, + "packaging": { + "hashes": [ + "sha256:a7ac867b97fdc07ee80a8058fe4435ccd274ecc3b0ed61d852d7d53055528cf9", + "sha256:c491ca87294da7cc01902edbe30a5bc6c4c28172b5138ab4e4aa1b9d7bfaeafe" + ], + "version": "==19.1" + }, + "pluggy": { + "hashes": [ + "sha256:0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", + "sha256:fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34" + ], + "version": "==0.13.0" + }, + "py": { + "hashes": [ + "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", + "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" + ], + "version": "==1.8.0" + }, + "pyparsing": { + "hashes": [ + "sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80", + "sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4" + ], + "version": "==2.4.2" + }, + "pytest": { + "hashes": [ + "sha256:95d13143cc14174ca1a01ec68e84d76ba5d9d493ac02716fd9706c949a505210", + "sha256:b78fe2881323bd44fd9bd76e5317173d4316577e7b1cddebae9136a4495ec865" + ], + "index": "pypi", + "version": "==5.1.2" + }, + "requests": { + "hashes": [ + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + ], + "index": "pypi", + "version": "==2.22.0" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "version": "==1.12.0" + }, + "urllib3": { + "hashes": [ + "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", + "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" + ], + "version": "==1.25.3" + }, + "wcwidth": { + "hashes": [ + "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", + "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" + ], + "version": "==0.1.7" + }, + "zipp": { + "hashes": [ + "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", + "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" + ], + "version": "==0.6.0" + } + }, + "develop": { + "astroid": { + "hashes": [ + "sha256:6560e1e1749f68c64a4b5dee4e091fce798d2f0d84ebe638cf0e0585a343acf4", + "sha256:b65db1bbaac9f9f4d190199bb8680af6f6f84fd3769a5ea883df8a91fe68b4c4" + ], + "version": "==2.2.5" + }, + "atomicwrites": { + "hashes": [ + "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4", + "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6" + ], + "version": "==1.3.0" + }, + "attrs": { + "hashes": [ + "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79", + "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399" + ], + "version": "==19.1.0" + }, + "certifi": { + "hashes": [ + "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50", + "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef" + ], + "version": "==2019.9.11" + }, + "chardet": { + "hashes": [ + "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", + "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" + ], + "version": "==3.0.4" + }, + "idna": { + "hashes": [ + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" + ], + "version": "==2.8" + }, + "importlib-metadata": { + "hashes": [ + "sha256:652234b6ab8f2506ae58e528b6fbcc668831d3cc758e1bc01ef438d328b68cdb", + "sha256:6f264986fb88042bc1f0535fa9a557e6a376cfe5679dc77caac7fe8b5d43d05f" + ], + "markers": "python_version < '3.8'", + "version": "==0.22" + }, + "isort": { + "hashes": [ + "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1", + "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd" + ], + "version": "==4.3.21" + }, + "lazy-object-proxy": { + "hashes": [ + "sha256:02b260c8deb80db09325b99edf62ae344ce9bc64d68b7a634410b8e9a568edbf", + "sha256:18f9c401083a4ba6e162355873f906315332ea7035803d0fd8166051e3d402e3", + "sha256:1f2c6209a8917c525c1e2b55a716135ca4658a3042b5122d4e3413a4030c26ce", + "sha256:2f06d97f0ca0f414f6b707c974aaf8829c2292c1c497642f63824119d770226f", + "sha256:616c94f8176808f4018b39f9638080ed86f96b55370b5a9463b2ee5c926f6c5f", + "sha256:63b91e30ef47ef68a30f0c3c278fbfe9822319c15f34b7538a829515b84ca2a0", + "sha256:77b454f03860b844f758c5d5c6e5f18d27de899a3db367f4af06bec2e6013a8e", + "sha256:83fe27ba321e4cfac466178606147d3c0aa18e8087507caec78ed5a966a64905", + "sha256:84742532d39f72df959d237912344d8a1764c2d03fe58beba96a87bfa11a76d8", + "sha256:874ebf3caaf55a020aeb08acead813baf5a305927a71ce88c9377970fe7ad3c2", + "sha256:9f5caf2c7436d44f3cec97c2fa7791f8a675170badbfa86e1992ca1b84c37009", + "sha256:a0c8758d01fcdfe7ae8e4b4017b13552efa7f1197dd7358dc9da0576f9d0328a", + "sha256:a4def978d9d28cda2d960c279318d46b327632686d82b4917516c36d4c274512", + "sha256:ad4f4be843dace866af5fc142509e9b9817ca0c59342fdb176ab6ad552c927f5", + "sha256:ae33dd198f772f714420c5ab698ff05ff900150486c648d29951e9c70694338e", + "sha256:b4a2b782b8a8c5522ad35c93e04d60e2ba7f7dcb9271ec8e8c3e08239be6c7b4", + "sha256:c462eb33f6abca3b34cdedbe84d761f31a60b814e173b98ede3c81bb48967c4f", + "sha256:fd135b8d35dfdcdb984828c84d695937e58cc5f49e1c854eb311c4d6aa03f4f1" + ], + "version": "==1.4.2" + }, + "mccabe": { + "hashes": [ + "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", + "sha256:dd8d182285a0fe56bace7f45b5e7d1a6ebcbf524e8f3bd87eb0f125271b8831f" + ], + "version": "==0.6.1" + }, + "more-itertools": { + "hashes": [ + "sha256:409cd48d4db7052af495b09dec721011634af3753ae1ef92d2b32f73a745f832", + "sha256:92b8c4b06dac4f0611c0729b2f2ede52b2e1bac1ab48f089c7ddc12e26bb60c4" + ], + "version": "==7.2.0" + }, + "packaging": { + "hashes": [ + "sha256:a7ac867b97fdc07ee80a8058fe4435ccd274ecc3b0ed61d852d7d53055528cf9", + "sha256:c491ca87294da7cc01902edbe30a5bc6c4c28172b5138ab4e4aa1b9d7bfaeafe" + ], + "version": "==19.1" + }, + "pluggy": { + "hashes": [ + "sha256:0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6", + "sha256:fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34" + ], + "version": "==0.13.0" + }, + "py": { + "hashes": [ + "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa", + "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53" + ], + "version": "==1.8.0" + }, + "pylint": { + "hashes": [ + "sha256:5d77031694a5fb97ea95e828c8d10fc770a1df6eb3906067aaed42201a8a6a09", + "sha256:723e3db49555abaf9bf79dc474c6b9e2935ad82230b10c1138a71ea41ac0fff1" + ], + "index": "pypi", + "version": "==2.3.1" + }, + "pyparsing": { + "hashes": [ + "sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80", + "sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4" + ], + "version": "==2.4.2" + }, + "pytest": { + "hashes": [ + "sha256:95d13143cc14174ca1a01ec68e84d76ba5d9d493ac02716fd9706c949a505210", + "sha256:b78fe2881323bd44fd9bd76e5317173d4316577e7b1cddebae9136a4495ec865" + ], + "index": "pypi", + "version": "==5.1.2" + }, + "pytest-asyncio": { + "hashes": [ + "sha256:9fac5100fd716cbecf6ef89233e8590a4ad61d729d1732e0a96b84182df1daaf", + "sha256:d734718e25cfc32d2bf78d346e99d33724deeba774cc4afdf491530c6184b63b" + ], + "index": "pypi", + "version": "==0.10.0" + }, + "pytest-mock": { + "hashes": [ + "sha256:43ce4e9dd5074993e7c021bb1c22cbb5363e612a2b5a76bc6d956775b10758b7", + "sha256:5bf5771b1db93beac965a7347dc81c675ec4090cb841e49d9d34637a25c30568" + ], + "index": "pypi", + "version": "==1.10.4" + }, + "requests": { + "hashes": [ + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" + ], + "index": "pypi", + "version": "==2.22.0" + }, + "requests-mock": { + "hashes": [ + "sha256:510df890afe08d36eca5bb16b4aa6308a6f85e3159ad3013bac8b9de7bd5a010", + "sha256:88d3402dd8b3c69a9e4f9d3a73ad11b15920c6efd36bc27bf1f701cf4a8e4646" + ], + "index": "pypi", + "version": "==1.7.0" + }, + "six": { + "hashes": [ + "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c", + "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73" + ], + "version": "==1.12.0" + }, + "typed-ast": { + "hashes": [ + "sha256:18511a0b3e7922276346bcb47e2ef9f38fb90fd31cb9223eed42c85d1312344e", + "sha256:262c247a82d005e43b5b7f69aff746370538e176131c32dda9cb0f324d27141e", + "sha256:2b907eb046d049bcd9892e3076c7a6456c93a25bebfe554e931620c90e6a25b0", + "sha256:354c16e5babd09f5cb0ee000d54cfa38401d8b8891eefa878ac772f827181a3c", + "sha256:4e0b70c6fc4d010f8107726af5fd37921b666f5b31d9331f0bd24ad9a088e631", + "sha256:630968c5cdee51a11c05a30453f8cd65e0cc1d2ad0d9192819df9978984529f4", + "sha256:66480f95b8167c9c5c5c87f32cf437d585937970f3fc24386f313a4c97b44e34", + "sha256:71211d26ffd12d63a83e079ff258ac9d56a1376a25bc80b1cdcdf601b855b90b", + "sha256:95bd11af7eafc16e829af2d3df510cecfd4387f6453355188342c3e79a2ec87a", + "sha256:bc6c7d3fa1325a0c6613512a093bc2a2a15aeec350451cbdf9e1d4bffe3e3233", + "sha256:cc34a6f5b426748a507dd5d1de4c1978f2eb5626d51326e43280941206c209e1", + "sha256:d755f03c1e4a51e9b24d899561fec4ccaf51f210d52abdf8c07ee2849b212a36", + "sha256:d7c45933b1bdfaf9f36c579671fec15d25b06c8398f113dab64c18ed1adda01d", + "sha256:d896919306dd0aa22d0132f62a1b78d11aaf4c9fc5b3410d3c666b818191630a", + "sha256:ffde2fbfad571af120fcbfbbc61c72469e72f550d676c3342492a9dfdefb8f12" + ], + "markers": "implementation_name == 'cpython'", + "version": "==1.4.0" + }, + "urllib3": { + "hashes": [ + "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1", + "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232" + ], + "version": "==1.25.3" + }, + "wcwidth": { + "hashes": [ + "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e", + "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c" + ], + "version": "==0.1.7" + }, + "wrapt": { + "hashes": [ + "sha256:565a021fd19419476b9362b05eeaa094178de64f8361e44468f9e9d7843901e1" + ], + "version": "==1.11.2" + }, + "zipp": { + "hashes": [ + "sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e", + "sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335" + ], + "version": "==0.6.0" + } + } +} diff --git a/Packs/Automox/Integrations/Automox/README.md b/Packs/Automox/Integrations/Automox/README.md new file mode 100644 index 000000000000..14ef899942e8 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/README.md @@ -0,0 +1,950 @@ +Use the Automox integration to create device groups, update devices, run policies, and remediate vulnerabilities of devices through the Automox platform. +This integration was integrated and tested as of 2022-03-21 with the Automox API + +## Configure Automox on Cortex XSOAR + +1. Navigate to **Settings** > **Integrations** > **Servers & Services**. +2. Search for Automox. +3. Click **Add instance** to create and configure a new integration instance. + + | **Parameter** | **Description** | **Required** | + | --- | --- | --- | + | Organization ID | A comma-separated list of organization ids. When specified, data pulled from Automox will only belong to this organization; otherwise, the default permissions for this API key will be used. | False | + | API Key | The API Key to use for connection | True | + | Trust any certificate (not secure) | | False | + | Use system proxy settings | | False | + +4. Click **Test** to validate the URLs, token, and connection. +## Commands +You can execute these commands from the Cortex XSOAR CLI, as part of an automation, or in a playbook. +After you successfully execute a command, a DBot message appears in the War Room with the command details. +### automox-devices-list +*** +List all devices in Automox based on group and organization permissions. + + +#### Base Command + +`automox-devices-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization ID. | Optional | +| group_id | Group ID. | Optional | +| limit | The maximum number of results to return per page. Default is 50. | Optional | +| page | The page of results to return. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.Devices.id | Number | Identifier of device | +| Automox.Devices.server_group_id | Number | Identifier of server group | +| Automox.Devices.organization_id | Number | Identifier of organization | +| Automox.Devices.uuid | String | The Automox UUID of a device | +| Automox.Devices.name | String | The name of a device | +| Automox.Devices.refresh_interval | Number | Frequency of device refreshes in minutes | +| Automox.Devices.last_update_time | String | The last time a device was updated in Automox | +| Automox.Devices.last_refresh_time | String | The last time a device was refreshed in Automox | +| Automox.Devices.uptime | Number | The device uptime in minutes | +| Automox.Devices.needs_reboot | Boolean | Whether a device needs to be rebooted | +| Automox.Devices.timezone | String | The device timezone | +| Automox.Devices.tags | String | List of tags for the device | +| Automox.Devices.deleted | Boolean | Whether a device is deleted | +| Automox.Devices.create_time | Date | The time a device was created in Automox | +| Automox.Devices.os_version | String | The operating system version of a device | +| Automox.Devices.os_name | String | The operating system name of a device | +| Automox.Devices.os_family | String | the operating system family of a device | +| Automox.Devices.ip_addrs | String | List of IP addresses for a device | +| Automox.Devices.ip_addrs_private | String | List of private IP addresses for a device | +| Automox.Devices.patches | Number | The number of patches currently identified for a device | +| Automox.Devices.agent_version | String | The version of the Automox agent on the device | +| Automox.Devices.custom_name | String | The Automox specific custom name for the device | +| Automox.Devices.is_compatible | Boolean | Whether a device is compatible with Automox | +| Automox.Devices.policy_status.id | Number | Identifier of policy | +| Automox.Devices.policy_status.organization_id | Number | Identifier of organization | +| Automox.Devices.policy_status.policy_name | String | Name of the policy | +| Automox.Devices.policy_status.policy_type_name | String | Type of the policy | +| Automox.Devices.policy_status.status | Number | Current status of the policy | +| Automox.Devices.policy_status.result | String | Result of the policy | +| Automox.Devices.policy_status.create_time | Datetime | Policy created datetime | +| Automox.Devices.last_scan_failed | Boolean | Whether the last scan failed on a device | +| Automox.Devices.pending | Boolean | Whether work is pending on a device | +| Automox.Devices.compliant | Boolean | Whether a device is compliant | +| Automox.Devices.display_name | String | The display name of a device | +| Automox.Devices.commands.command_type_name | String | The type of a command previously issued on a device | +| Automox.Devices.commands.args | String | The arguments of a command previously issued on a device | +| Automox.Devices.commands.exec_time | Date | The execution time of a command previously issued on a device | +| Automox.Devices.pending_patches | Number | The number of pending patches for a device | +| Automox.Devices.connected | Boolean | Whether a device is currently connected to Automox | +| Automox.Devices.last_process_time | String | The last time the device was processed | +| Automox.Devices.next_patch_time | String | The next time the device is patched | +| Automox.Devices.notification_count | Number | The number of notifications for the device | +| Automox.Devices.reboot_notification_count | Number | The number of reboot notifications for a device | +| Automox.Devices.patch_deferral_count | Number | The number of patch deferrals for a device | +| Automox.Devices.is_delayed_by_notification | Boolean | Whether a patch is delayed by notifications | +| Automox.Devices.reboot_is_delayed_by_notification | Boolean | Whether a reboot is delayed by notifications | +| Automox.Devices.is_delayed_by_user | Boolean | Whether a patch is delayed by the user | +| Automox.Devices.reboot_is_delayed_by_user | Boolean | Whether a reboot is delayed by the user | +| Automox.Devices.last_disconnect_time | Date | Last time a device disconnected from Automox | +| Automox.Devices.needs_attention | Boolean | Whether a device currently needs attention | +| Automox.Devices.serial_number | String | The device serial number | +| Automox.Devices.status.device_status | String | The status of a device | +| Automox.Devices.status.agent_status | String | The status of a device agent | +| Automox.Devices.status.policy_status | String | The overall status of all policies assigned to a device | +| Automox.Devices.status.policy_statuses.id | Number | The identifier of the policy | +| Automox.Devices.status.policy_statuses.compliant | Boolean | Whether a device is compliant to a given status | +| Automox.Devices.last_logged_in_user | String | The last logged in user of a device | + +#### Command Example +``` +!automox-devices-list limit=1 +``` + +#### Context Example +```json +{ + "Automox": { + "Devices": { + "agent_version": "string", + "commands": [ + { + "command_type_name": "InstallUpdate", + "args": "KB12345 KB67890", + "exec_time": "2017-06-29T16:39:50.951Z" + } + ], + "compliant": true, + "connected": true, + "create_time": "2019-08-24T14:15:22Z", + "custom_name": "string", + "deleted": true, + "display_name": "string", + "exception": true, + "id": 0, + "ip_addrs": [ + "string" + ], + "ip_addrs_private": [ + "string" + ], + "is_compatible": true, + "is_delayed_by_notification": true, + "is_delayed_by_user": true, + "last_disconnect_time": "2019-08-24T14:15:22Z", + "last_logged_in_user": "string", + "last_process_time": "string", + "last_refresh_time": "string", + "last_scan_failed": true, + "last_update_time": "string", + "name": "string", + "needs_attention": true, + "needs_reboot": true, + "next_patch_time": "string", + "notification_count": 0, + "organization_id": 0, + "os_family": "string", + "os_name": "string", + "os_version": "string", + "patch_deferral_count": 0, + "patches": 0, + "pending": true, + "pending_patches": 0, + "policy_status": [ + { + "id": 0, + "organization_id": 0, + "policy_id": 0, + "server_id": 0, + "policy_name": "string", + "policy_type_name": "patch", + "status": 0, + "result": "string", + "create_time": "string" + } + ], + "reboot_is_delayed_by_notification": true, + "reboot_is_delayed_by_user": true, + "reboot_notification_count": 0, + "refresh_interval": 0, + "serial_number": "string", + "server_group_id": 0, + "status": { + "device_status": "string", + "agent_status": "string", + "policy_status": "string", + "policy_statuses": [ + { + "id": 0, + "compliant": true + } + ] + }, + "tags": [ + "string" + ], + "timezone": "string", + "total_count": 0, + "uptime": 0, + "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f" + } + } +} +``` + +#### Human Readable Output +>### Devices +>| agent_version | commands | compliant | connected | create_time | custom_name | deleted | display_name | exception | id | ip_addrs | ip_addrs_private | is_compatible | is_delayed_by_notification | is_delayed_by_user | last_disconnect_time | last_logged_in_user | last_process_time | last_refresh_time | last_scan_failed | last_update_time | name | needs_attention | needs_reboot | next_patch_time | notification_count | organization_id | os_family | os_name | os_version | patch_deferral_count | patches | pending | pending_patches | policy_status | reboot_is_delayed_by_notification | reboot_is_delayed_by_user | reboot_notification_count | refresh_interval | serial_number | server_group_id | status | tags | timezone | total_count | uptime | uuid | +>| ------------- | ------------------------------------------------------------------------------------------------------- | --------- | --------- | -------------------- | ----------- | ------- | ------------ | --------- | --- | -------- | ---------------- | ------------- | -------------------------- | ------------------ | -------------------- | ------------------- | ----------------- | ----------------- | ---------------- | ---------------- | ------ | --------------- | ------------ | --------------- | ------------------ | --------------- | --------- | ------- | ---------- | -------------------- | ------- | ------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | ------------------------- | ------------------------- | ---------------- | ------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------- | ------ | -------- | ----------- | ------ | ------------------------------------ | +>| string | command_type_name: InstallUpdate
args: KB12345 KB67890
exec_time: 2017-06-29T16:39:50.951Z | true | true | 2019-08-24T14:15:22Z | string | true | string | true | 0 | 1.1.1.1 | 1.1.1.1 | true | true | true | 2019-08-24T14:15:22Z | string | string | string | true | string | string | true | true | string | 0 | 0 | string | string | string | 0 | 0 | true | 0 | id: 0
organization_id: 0
policy_id: 0
server_id: 0
policy_name: string
policy_type_name: patch
status: 0
result: string
create_time: string | true | true | 0 | 0 | string | 0 | {"device_status": "string","agent_status": "string","policy_status": "string","policy_statuses": [{"id": 0,"compliant": true}]} | string | string | 0 | 0 | 095be615-a8ad-4c33-8e9c-c7612fbf6c9f | + +### automox-organizations-list +*** +List all Automox organizations based on user permissions. + + +#### Base Command + +`automox-organizations-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| limit | The maximum number of results to return per page. Default is 50. | Optional | +| page | The page of results to return. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.Organizations.id | Number | Identifier of organization | +| Automox.Organizations.name | String | Name of organization | +| Automox.Organizations.create_time | Date | The datetime when the organization was created | +| Automox.Organizations.server_limit | Number | The organization server limit | +| Automox.Organizations.parent_id | Number | The organization parent id | +| Automox.Organizations.device_limit | Number | The organization device limit | +| Automox.Organizations.device_count | Number | The organization device count | + +#### Command example +```!automox-organizations-list limit=1``` +#### Context Example +```json +{ + "Automox": { + "Organizations": { + "create_time": "2019-08-27T21:59:19+0000", + "device_count": 26, + "device_limit": null, + "id": 9237, + "name": "string", + "parent_id": 65, + "server_limit": 0 + } + } +} +``` + +#### Human Readable Output +>### Organizations +>| create_time | device_count | device_limit | id | name | parent_id | server_limit | +>| ------------------------ | ------------ | ------------ | ---- | ------ | --------- | ------------ | +>| 2019-08-27T21:59:19+0000 | 26 | | 9237 | string | 65 | 0 | +### automox-organization-users-list +*** +List all Automox users within an organization. + + +#### Base Command + +`automox-organization-users-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| limit | The maximum number of results to return per page. Default is 50. | Optional | +| page | The page of results to return. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.Users.id | Number | Identifier of user | +| Automox.Users.firstname | String | The first name of the user | +| Automox.Users.lastname | String | The last name of the user | +| Automox.Users.email | String | The email of the user | +| Automox.Users.orgs.id | Number | Identifier of organization | +| Automox.Users.orgs.name | String | Name of organization | +| Automox.Users.tags | String | User tags | +| Automox.Users.saml_enabled | Boolean | Whether SAML has been enabled for the user | +| Automox.Users.rbac_roles.id | Number | The RBAC role identifier | +| Automox.Users.rbac_roles.name | String | The RBAC role name | +| Automox.Users.rbac_roles.organization_id | Number | Identifier of organization | + +#### Command example +```!automox-organization-users-list limit=1``` +#### Context Example +```json +{ + "Automox": { + "Users": { + "email": "string", + "firstname": "string", + "id": 1, + "lastname": "string", + "orgs": [ + { + "id": 1, + "name": "string" + } + ], + "rbac_roles": [ + { + "id": 0, + "name": "string", + "organization_id": 1 + } + ], + "saml_enabled": true, + "tags": [ + "string" + ] + } + } +} +``` + +#### Human Readable Output +##### Organization Users +| id | firstname | lastname | email | orgs | tags | saml_enabled | rbac_roles | +| --- | --------- | -------- | ------ | ---------------------------- | ------ | ------------ | ------------------------------------------------- | +| 0 | string | string | string | id: 0
name: string | string | true | id: 0
name: string
organization_id: 0 | +### automox-vulnerability-sync-batch-action +*** +Perform an action on an Automox Vulnerability Sync batch. + + +#### Base Command + +`automox-vulnerability-sync-batch-action` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| batch_id | Batch identifier. | Required | +| action | Action to perform on the batch specified. Options are "accept" or "reject". Possible values are: accept, reject. | Required | + + +#### Context Output + +There is no context output for this command. +### automox-vulnerability-sync-task-action +*** +Perform an action on an Automox task. + + +#### Base Command + +`automox-vulnerability-sync-task-action` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| batch_id | Batch identifier. | Required | +| action | Action to perform on the batch specified. Options are "accept" or "reject". Possible values are: accept, reject. | Required | + + +#### Context Output + +There is no context output for this command. +### automox-vulnerability-sync-batch-get +*** +Get details about a Vulnerability Sync batch. + + +#### Base Command + +`automox-vulnerability-sync-batch-get` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| batch_id | Batch identifier. | Required | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.VulnSyncBatch.id | Number | Identifier of batch | +| Automox.VulnSyncBatch.organization_id | Number | Identifier of organization | +| Automox.VulnSyncBatch.status | String | Status of batch | +| Automox.VulnSyncBatch.source | String | Originating vendor of vulnerability information | +| Automox.VulnSyncBatch.created_by.id | Number | The identifier of the user who created this batch | +| Automox.VulnSyncBatch.created_by.firstname | String | The first name of the user who created this batch | +| Automox.VulnSyncBatch.created_by.lastname | String | The last name of the user who created this batch | +| Automox.VulnSyncBatch.created_by.email | String | The email of the user who created this batch | +| Automox.VulnSyncBatch.updated_by.id | Number | The identifier of the user who last updated this batch | +| Automox.VulnSyncBatch.updated_by.firstname | String | The first name of the user who last updated this batch | +| Automox.VulnSyncBatch.updated_by.lastname | String | The last name of the user who last updated this batch | +| Automox.VulnSyncBatch.updated_by.email | String | The email of the user who last updated this batch | +| Automox.VulnSyncBatch.uploaded_at | Date | Datetime of initial upload | +| Automox.VulnSyncBatch.task_count | Number | Number of tasks related to batch | +| Automox.VulnSyncBatch.unknown_host_count | Number | Number of hosts that are unknown within batch | +| Automox.VulnSyncBatch.impacted_device_count | Number | Number of devices impacted by batch | +| Automox.VulnSyncBatch.issue_count | Number | Number of issues identified with batch | +| Automox.VulnSyncBatch.cve_count | Number | Number of CVEs impacted by batch | + + +#### Command Example +``` +!automox-vulnerability-sync-batch-get batch_id=1 +``` + +#### Context Example +```json +{ + "Automox": { + "Batch": { + "created_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "cve_count": 0, + "id": 1, + "impacted_device_count": 0, + "issue_count": 0, + "organization_id": 1, + "source": "string", + "status": "processing", + "task_count": 0, + "unknown_host_count": 0, + "updated_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "uploaded_at": "2019-08-24T14:15:22Z" + } + } +} +``` + +#### Human Readable Output +>### Batch +>| created_by | cve_count | id | impacted_device_count | issue_count | organization_id | source | status | task_count | unknown_host_count | updated_by | uploaded_at | +>| ------------------------------------------------------------------- | --------- | --- | --------------------- | ----------- | --------------- | ------ | ---------- | ---------- | ------------------ | ------------------------------------------------------------------- | -------------------- | +>| id: 0
firstname: string
lastname: string
email: string
| 0 | 1 | 0 | 0 | 1 | string | processing | 0 | 0 | id: 0
firstname: string
lastname: string
email: string
| 2019-08-24T14:15:22Z | + +### automox-vulnerability-sync-batches-list +*** +Get a list of Vulnerability Sync batches. + + +#### Base Command + +`automox-vulnerability-sync-batches-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| limit | The maximum number of results to return per page. Default is 50. | Optional | +| page | The page of results to return. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.VulnSyncBatches.id | Number | Identifier of batch | +| Automox.VulnSyncBatches.organization_id | Number | Identifier of organization | +| Automox.VulnSyncBatches.status | String | Status of batch | +| Automox.VulnSyncBatches.source | String | Source of batch | +| Automox.VulnSyncBatches.created_by.id | Number | Identifier of user who created the batch | +| Automox.VulnSyncBatches.created_by.firstname | String | First name of the user who created the batch | +| Automox.VulnSyncBatches.created_by.lastname | String | Last name of the user who created the batch | +| Automox.VulnSyncBatches.created_by.email | String | Email of the user who created the batch | +| Automox.VulnSyncBatches.updated_by.id | Number | Identifier of the user who last updated the batch | +| Automox.VulnSyncBatches.updated_by.firstname | String | First name of the user who last updated the batch | +| Automox.VulnSyncBatches.updated_by.lastname | String | Last name of the user who last updated the batch | +| Automox.VulnSyncBatches.updated_by.email | String | Email off the user who last updated the batch | +| Automox.VulnSyncBatches.uploaded_at | Date | Datetime the batch was uploaded | +| Automox.VulnSyncBatches.task_count | Number | Number of tasks related to batch | +| Automox.VulnSyncBatches.unknown_host_count | Number | number of hosts that are unknown within batch | +| Automox.VulnSyncBatches.impacted_device_count | Number | Number of devices that are impacted by batch | +| Automox.VulnSyncBatches.issue_count | Number | Number of issues identified with batch | +| Automox.VulnSyncBatches.cve_count | Number | Number of CVEs that are impacted by batch | +#### Command example +```!automox-vulnerability-sync-batches-list limit=1``` +#### Context Example +```json +{ + "Automox": { + "VulnSyncBatches": { + "created_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "cve_count": 0, + "id": 1, + "impacted_device_count": 0, + "issue_count": 0, + "organization_id": 1, + "source": "string", + "status": "processing", + "task_count": 0, + "unknown_host_count": 0, + "updated_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "uploaded_at": "2019-08-24T14:15:22Z" + } + } +} +``` + +#### Human Readable Output +>### Batches +>| created_by | cve_count | id | impacted_device_count | issue_count | organization_id | source | status | task_count | unknown_host_count | updated_by | uploaded_at | +>| ------------------------------------------------------------------- | --------- | --- | --------------------- | ----------- | --------------- | ------ | ---------- | ---------- | ------------------ | ------------------------------------------------------------------- | -------------------- | +>| id: 0
firstname: string
lastname: string
email: string
| 0 | 1 | 0 | 0 | 1 | string | processing | 0 | 0 | id: 0
firstname: string
lastname: string
email: string
| 2019-08-24T14:15:22Z | + +### automox-vulnerability-sync-tasks-list +*** +Get a list of Automox tasks. + + +#### Base Command + +`automox-vulnerability-sync-tasks-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| batch_id | Batch identifier. | Optional | +| status | Filter by status of tasks. Possible values are: pending, in_progress, completed, canceled. | Optional | +| limit | The maximum number of results to return per page. Default is 50. | Optional | +| page | The page of results to return. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.VulnSyncTasks.id | Number | Identifier of task | +| Automox.VulnSyncTasks.organization_id | Number | Identifier of organization | +| Automox.VulnSyncTasks.task_type | String | Type of task | +| Automox.VulnSyncTasks.payload.patch_id | String | Identifier of patch associated with the task | +| Automox.VulnSyncTasks.payload.severity | String | Severity of patch associated with the task | +| Automox.VulnSyncTasks.payload.package_versions.id | String | Identifier of package associated with the task | +| Automox.VulnSyncTasks.payload.package_versions.name | String | Name of the package associated with the task | +| Automox.VulnSyncTasks.payload.package_versions.version | String | Version of the package associated with the task | +| Automox.VulnSyncTasks.payload.package_versions.display_name | String | Display name of the package associated with the task | +| Automox.VulnSyncTasks.payload.package_versions.requires_reboot | Boolean | Whether the package installed by the task will require a reboot | +| Automox.VulnSyncTasks.source | String | Source of task | +| Automox.VulnSyncTasks.notes | String | Notes associated with task | +| Automox.VulnSyncTasks.status | String | Status of task | +| Automox.VulnSyncTasks.created_by_user.id | Number | Identifier of user who created the task | +| Automox.VulnSyncTasks.created_by_user.email | String | Email of user who created the task | +| Automox.VulnSyncTasks.created_by_user.firstname | String | First name of user who created the task | +| Automox.VulnSyncTasks.created_by_user.lastname | String | Last name of user who created the task | +| Automox.VulnSyncTasks.last_updated_by_user.id | Number | Identifier of user who last updated the task | +| Automox.VulnSyncTasks.last_updated_by_user.email | String | Email of user who last updated the task | +| Automox.VulnSyncTasks.last_updated_by_user.firstname | String | First name of user who last updated the task | +| Automox.VulnSyncTasks.last_updated_by_user.lastname | String | Last name of user who last updated the task | +| Automox.VulnSyncTasks.created_at | Date | Datetime the task was created at | +| Automox.VulnSyncTasks.updated_at | Date | Datetime the task was last updated at | +| Automox.VulnSyncTasks.completed_at | Date | Datetime the task was completed | + +#### Command example +```!automox-vulnerability-sync-tasks-list limit=1``` +#### Context Example +```json +{ + "Automox": { + "VulnSyncTasks": { + "completed_at": "2022-03-30 20:00:03", + "created_at": "2022-03-29T19:46:12+0000", + "created_by_user": { + "email": "string", + "firstname": "string", + "id": 19017, + "lastname": "string" + }, + "cves": [], + "id": 1221, + "last_updated_by_user": { + "email": "string", + "firstname": "string", + "id": 19017, + "lastname": "string" + }, + "notes": "", + "organization_id": 9237, + "payload": { + "package_versions": [ + { + "display_name": "2020-05 Cumulative Update for Windows 10 Version 1809 for x64-based Systems (KB4551853)", + "id": "223683225", + "name": "3f646594-9a4f-4b7a-bb7b-1932a5b490a6", + "requires_reboot": false, + "version": "1" + }, + ], + "patch_id": "CVE-2018-0886", + "severity": "critical" + }, + "source": "Automox", + "status": "executed", + "task_type": "patch-now", + "updated_at": "2022-03-30T20:00:03+0000" + } + } +} +``` + +#### Human Readable Output +>### Tasks +>|completed_at|created_at|created_by_user|cves|id|last_updated_by_user|notes|organization_id|payload|source|status|task_type|updated_at| +>|---|---|---|---|---|---|---|---|---|---|---|---|---| +>| 2022-03-30 20:00:03 | 2022-03-29T19:46:12+0000 | id: 19017
email: string
firstname: string
lastname: string | | 1221 | id: 19017
email: string
firstname: string
lastname: string | | 9237 | patch_id: CVE-2018-0886
severity: critical
package_versions: {'id': '223683225', 'name': '3f646594-9a4f-4b7a-bb7b-1932a5b490a6', 'version': '1', 'display_name': '2020-05 Cumulative Update for Windows 10 Version 1809 for x64-based Systems (KB4551853)', 'requires_reboot': False} | Automox | executed | patch-now | 2022-03-30T20:00:03+0000 | +### automox-vulnerability-sync-file-upload +*** +Upload a vulnerability report to Automox Vulnerability Sync. + + +#### Base Command + +`automox-vulnerability-sync-file-upload` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| entry_id | Entry ID of the CSV file to upload. | Required | +| csv_file_name | Name for CSV file uploaded and shown within Automox. Default is XSOAR-uploaded-report.csv. | Optional | +| reports_source | The third-party source of the vulnerability report. Default is Generic Report. | Optional | +| type | The type of task to create | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.VulnUpload.batch_id | Number | Identifier of batch | + +#### Command example +```!automox-vulnerability-sync-file-upload entry_id="1075@1a203850-514b-4ba5-848e-f944bd9ab460"``` +#### Context Example +```json +{ + "Automox": { + "VulnUpload": { + "batch_id": 1241 + } + } +} +``` + +#### Human Readable Output +### Upload +| batch_id | +| -------- | +| 1241 | +### automox-policies-list +*** +Retrieve a list of Automox policies belonging to an organization. + + +#### Base Command + +`automox-policies-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| limit | The maximum number of results to return per page. Default is 50. | Optional | +| page | The page of results to return. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.Policies.id | Number | Identifier of policy | +| Automox.Policies.organization_id | Number | Identifier of organization | +| Automox.Policies.name | String | Name of policy | +| Automox.Policies.policy_type_name | String | Policy type name | +| Automox.Policies.server_groups | Number | List of identifiers for device groups assigned to the policy | + +#### Command example +```!automox-policies-list limit=1``` +#### Context Example +```json +{ + "Automox": { + "Policies": { + "create_time": "2021-03-03T21:29:09+0000", + "id": 112411, + "name": "string", + "notes": "", + "organization_id": 9237, + "policy_type_name": "patch", + "server_count": 1, + "server_groups": [ + 85579, + 86754 + ] + } + } +} +``` + +#### Human Readable Output +>### Policies +>| create_time | id | name | notes | organization_id | policy_type_name | server_count | server_groups +>| ------------------------ | ------ | ---------------- | ----- | --------------- | ---------------- | ------------ | --------------- +>| 2021-03-03T21:29:09+0000 | 112411 | string | | 9237 | patch | 1 | 85579,
86754 +### automox-command-run +*** +Run a command on a device in Automox + +#### Base Command + +`automox-command-run` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| device_id | Device identifier. | Required | +| patches | List of patches to be installed by name. (Note: this only works with the InstallUpdate command). | Optional | +| command | Command to run on device. Possible values are: GetOS, InstallUpdate, InstallAllUpdates, Reboot. | Required | + + +#### Context Output +There is no context output for this command. +#### Command example +```!automox-command-run command=GetOS device_id=1375363``` +#### Human Readable Output + +>Command: GetOS successfully sent to Automox device ID: 1375363 +### automox-device-delete +*** +Delete a device from Automox + + +#### Base Command + +`automox-device-delete` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| device_id | Device identifier. | Required | + + +#### Context Output + +There is no context output for this command. +### automox-device-update +*** +Update a device's information in Automox + + +#### Base Command + +`automox-device-update` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| device_id | Device identifier. | Required | +| custom_name | Custom name to set on device. | Optional | +| exception | Exclude the device from reports and statistics. | Required | +| server_group_id | Identifier of server group. | Required | +| tags | List of tags to associate with the device. | Optional | +| ip_addrs | IP address of the device. | Optional | + + +#### Context Output + +There is no context output for this command. +### automox-groups-list +*** +List all groups in Automox based on organization permissions. + + +#### Base Command + +`automox-groups-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| limit | The maximum number of results to return per page. Default is 50. | Optional | +| page | The page of results to return. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.Groups.id | Number | Identifier of the created group | +| Automox.Groups.organization_id | Number | Identifier of organization | +| Automox.Groups.name | String | The name of the group | +| Automox.Groups.refresh_interval | Number | Frequency of device refreshes in minutes. | +| Automox.Groups.parent_server_group_id | Number | Identifier of parent group | +| Automox.Groups.ui_color | String | Automox console highlight color for the group | +| Automox.Groups.notes | String | Notes defined for the group | +| Automox.Groups.enable_os_auto_update | Boolean | Enable operating system auto updates | +| Automox.Groups.server_count | Number | Number of devices assigned to group | +| Automox.Groups.policies | Number | List of policies assigned to group | +| Automox.Groups.deleted | Boolean | Whether a group is deleted | + +#### Command example +```!automox-groups-list limit=1``` +#### Context Example +```json +{ + "Automox": { + "Groups": { + "enable_os_auto_update": true, + "id": 1, + "name": "string", + "notes": "string", + "organization_id": 1, + "parent_server_group_id": 0, + "policies": [ + 163746, + 167809, + 172118, + 172076, + 156951, + 147303 + ], + "refresh_interval": 360, + "server_count": 5, + "ui_color": "#059F1D", + "deleted": false + } + } +} +``` + +#### Human Readable Output +##### Groups +| id | organization_id | name | refresh_interval | parent_server_group_id | ui_color | notes | enable_os_auto_update | server_count | policies | deleted | +| --- | --------------- | ------ | ---------------- | ---------------------- | -------- | ------ | --------------------- | ------------ | -------- | ------- | +| 0 | 0 | string | 0 | 0 | string | string | true | 0 | 0 | false | +### automox-group-create +*** +Create a group in Automox + + +#### Base Command + +`automox-group-create` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| name | Name of the group. | Required | +| notes | Define notes for the group. | Optional | +| parent_server_group_id | Identifier of the parent group. Defaults to default group id if omitted. | Optional | +| policies | List of policy identifiers to assign to group. | Optional | +| refresh_interval | Frequency of device refreshes in minutes. (Must be between 360 and 1440). | Required | +| color | Automox console highlight color for the group. Value should be a valid Hex color code | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Automox.CreatedGroups.id | Number | Identifier of the created group | +| Automox.CreatedGroups.organization_id | Number | Identifier of organization | +| Automox.CreatedGroups.name | String | The name of the group | +| Automox.CreatedGroups.refresh_interval | Number | Frequency of device refreshes in minutes | +| Automox.CreatedGroups.parent_server_group_id | Number | Identifier of parent group | +| Automox.CreatedGroups.ui_color | String | Automox console highlight color for the group | +| Automox.CreatedGroups.notes | String | Notes defined for the group | +| Automox.CreatedGroups.enable_os_auto_update | Boolean | Enable operating system auto updates | +| Automox.CreatedGroups.server_count | Number | Number of devices assigned to group | +| Automox.CreatedGroups.policies | Number | List of policies assigned to group | + +#### Command Example +``` +!automox-group-create +``` + +#### Human Readable Output +##### Group +| id | organization_id | name | refresh_interval | parent_server_group_id | ui_color | notes | enable_os_auto_update | server_count | policies | +| --- | --------------- | ------ | ---------------- | ---------------------- | -------- | ------ | --------------------- | ------------ | -------- | +| 0 | 0 | string | 0 | 0 | string | string | true | 0 | 0 | +### automox-group-update +*** +Update a group's information in Automox + + +#### Base Command + +`automox-group-update` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| group_id | Group identifier. | Required | +| name | Name of the group. | Optional | +| notes | Define notes for the group. | Optional | +| parent_server_group_id | Identifier of the parent group. Defaults to default group id if omitted. | Optional | +| policies | List of policy identifiers to assign to group. | Optional | +| refresh_interval | Frequency of device refreshes in minutes. | Optional | +| color | Automox console highlight color for the group. Value should be a valid Hex color code | Optional | + + +#### Context Output + +There is no context output for this command. +### automox-group-delete +*** +Delete a group from Automox + + +#### Base Command + +`automox-group-delete` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| org_id | Organization identifier. | Optional | +| group_id | Group identifier. | Required | + + +#### Context Output + +There is no context output for this command. diff --git a/Packs/Automox/Integrations/Automox/command_examples b/Packs/Automox/Integrations/Automox/command_examples new file mode 100644 index 000000000000..43acef930db6 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/command_examples @@ -0,0 +1,9 @@ +!automox-devices-list limit=1 +!automox-command-run command=GetOS device_id=1375363 +!automox-groups-list limit=1 +!automox-organization-users-list limit=1 +!automox-organizations-list limit=1 +!automox-policies-list limit=1 +!automox-vulnerability-sync-batches-list limit=1 +!automox-vulnerability-sync-file-upload entry_id="1075@1a203850-514b-4ba5-848e-f944bd9ab460" +!automox-vulnerability-sync-tasks-list limit=1 diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-device-get.json b/Packs/Automox/Integrations/Automox/test_data/automox-device-get.json new file mode 100644 index 000000000000..ad9196fae093 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-device-get.json @@ -0,0 +1,171 @@ +{ + "id": 0, + "os_version_id": 0, + "server_group_id": 0, + "organization_id": 0, + "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f", + "name": "string", + "instance_id": "string", + "refresh_interval": 0, + "last_update_time": "string", + "last_refresh_time": "string", + "uptime": 0, + "needs_reboot": true, + "timezone": "string", + "tags": [ + "string" + ], + "deleted": true, + "create_time": "2019-08-24T14:15:22Z", + "os_version": "string", + "os_name": "string", + "os_family": "string", + "ip_addrs": [ + "string" + ], + "ip_addrs_private": [ + "string" + ], + "hostname": "string", + "patches": 0, + "details": { + "CPU": "string", + "DISKS": [ + { + "SIZE": "string", + "TYPE": "string" + } + ], + "MODEL": "string", + "NICS": [ + { + "CONNECTED": true, + "DEVICE": "string", + "IPS": [ + "string" + ], + "MAC": "string", + "TYPE": "string", + "VENDOR": "string" + } + ], + "RAM": "string", + "SERIAL": "string", + "SERVICETAG": "string", + "VENDOR": "string", + "VERSION": "string" + }, + "agent_version": "string", + "custom_name": "string", + "exception": true, + "total_count": 0, + "server_policies": [ + { + "id": 0, + "organization_id": 0, + "name": "string", + "policy_type_name": "patch", + "configuration": { + "auto_patch": true, + "auto_reboot": true, + "notify_user": true, + "missed_patch_window": true, + "patch_rule": "all", + "device_filters_enabled": true, + "device_filters": [ + { + "field": "tag", + "op": "in", + "value": [ + "Windows", + "Win10" + ] + } + ], + "include_optional": true, + "notify_reboot_user": true, + "notify_deferred_reboot_user": true, + "custom_notification_patch_message": "Necessary Windows updates are about to be installed!", + "custom_notification_patch_message_mac": "Necessary Mac updates are about to be installed!", + "custom_notification_reboot_message": "Necessary Windows updates are about to be installed! Reboot Needed!", + "custom_notification_reboot_message_mac": "Necessary Mac updates are about to be installed! Reboot Needed!", + "custom_notification_max_delays": 0, + "custom_notification_deferment_periods": [ + 1, + 4, + 8 + ], + "custom_pending_reboot_notification_message": "Your computer needs to restart to finish installing updates!", + "custom_pending_reboot_notification_message_mac": "Your Mac needs to restart to finish installing updates!", + "custom_pending_reboot_notification_max_delays": 0, + "custom_pending_reboot_notification_deferment_periods": [ + 2, + 4, + 6 + ], + "notify_user_message_timeout": 15, + "notify_deferred_reboot_user_timeout": 15, + "notify_user_auto_deferral_enabled": false, + "notify_deferred_reboot_user_auto_deferral_enabled": false + }, + "schedule_days": 0, + "schedule_weeks_of_month": 0, + "schedule_months": 0, + "schedule_time": "string", + "server_groups": [ + 0 + ] + } + ], + "policy_status": [ + { + "id": 0, + "organization_id": 0, + "policy_id": 0, + "server_id": 0, + "policy_name": "string", + "policy_type_name": "patch", + "status": 0, + "result": "string", + "create_time": "string", + "next_remediation": "2019-08-24T14:15:22Z" + } + ], + "last_scan_failed": true, + "pending": true, + "compliant": true, + "display_name": "string", + "commands": [ + { + "command_type_name": "InstallUpdate", + "args": "KB12345 KB67890", + "exec_time": "2017-06-29T16:39:50.951Z" + } + ], + "pending_patches": 0, + "connected": true, + "last_process_time": "string", + "next_patch_time": "string", + "notification_count": 0, + "reboot_notification_count": 0, + "patch_deferral_count": 0, + "is_delayed_by_notification": true, + "reboot_is_delayed_by_notification": true, + "is_delayed_by_user": true, + "reboot_is_delayed_by_user": true, + "last_disconnect_time": "2019-08-24T14:15:22Z", + "needs_attention": true, + "serial_number": "string", + "status": { + "device_status": "string", + "agent_status": "string", + "policy_status": "string", + "policy_statuses": [ + { + "id": 0, + "compliant": true + } + ] + }, + "last_logged_in_user": "string" +} diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-devices-list.json b/Packs/Automox/Integrations/Automox/test_data/automox-devices-list.json new file mode 100644 index 000000000000..89eb70d3e8da --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-devices-list.json @@ -0,0 +1,123 @@ +[ + { + "id": 0, + "os_version_id": 0, + "server_group_id": 0, + "organization_id": 0, + "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f", + "name": "string", + "instance_id": "string", + "refresh_interval": 0, + "last_update_time": "string", + "last_refresh_time": "string", + "uptime": 0, + "needs_reboot": true, + "timezone": "string", + "tags": [ + "string" + ], + "deleted": true, + "create_time": "2019-08-24T14:15:22Z", + "os_version": "string", + "os_name": "string", + "os_family": "string", + "ip_addrs": [ + "string" + ], + "ip_addrs_private": [ + "string" + ], + "patches": 0, + "detail": { + "CPU": "string", + "DISKS": [ + { + "SIZE": "string", + "TYPE": "string" + } + ], + "MODEL": "string", + "NICS": [ + { + "CONNECTED": true, + "DEVICE": "string", + "IPS": [ + "string" + ], + "MAC": "string", + "TYPE": "string", + "VENDOR": "string" + } + ], + "RAM": "string", + "SERIAL": "string", + "SERVICETAG": "string", + "VENDOR": "string", + "VERSION": "string" + }, + "agent_version": "string", + "custom_name": "string", + "exception": true, + "total_count": 0, + "is_compatible": true, + "compatibility_checks": { + "low_diskspace": true, + "missing_secure_token": true, + "app_store_disconnected": true, + "missing_powershell": true, + "missing_wmi_integrity_check": true, + "wsus_disconnected": true, + "windows_update_server_disconnected": true + }, + "policy_status": [ + { + "id": 0, + "organization_id": 0, + "policy_id": 0, + "server_id": 0, + "policy_name": "string", + "policy_type_name": "patch", + "status": 0, + "result": "string", + "create_time": "string" + } + ], + "last_scan_failed": true, + "pending": true, + "compliant": true, + "display_name": "string", + "commands": [ + { + "command_type_name": "InstallUpdate", + "args": "KB12345 KB67890", + "exec_time": "2017-06-29T16:39:50.951Z" + } + ], + "pending_patches": 0, + "connected": true, + "last_process_time": "string", + "next_patch_time": "string", + "notification_count": 0, + "reboot_notification_count": 0, + "patch_deferral_count": 0, + "is_delayed_by_notification": true, + "reboot_is_delayed_by_notification": true, + "is_delayed_by_user": true, + "reboot_is_delayed_by_user": true, + "last_disconnect_time": "2019-08-24T14:15:22Z", + "needs_attention": true, + "serial_number": "string", + "status": { + "device_status": "string", + "agent_status": "string", + "policy_status": "string", + "policy_statuses": [ + { + "id": 0, + "compliant": true + } + ] + }, + "last_logged_in_user": "string" + } +] diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-group-create.json b/Packs/Automox/Integrations/Automox/test_data/automox-group-create.json new file mode 100644 index 000000000000..b435092b7e7a --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-group-create.json @@ -0,0 +1,22 @@ +{ + "id": 2, + "organization_id": 1, + "name": "Test Group", + "refresh_interval": 360, + "parent_server_group_id": 1, + "ui_color": "#FFFFFF", + "notes": "My notes", + "enable_os_auto_update": true, + "server_count": 0, + "wsus_config": { + "id": 0, + "server_group_id": 0, + "is_managed": true, + "server_url": "string", + "created_at": "string", + "updated_at": "string" + }, + "policies": [ + 0 + ] +} diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-group-get.json b/Packs/Automox/Integrations/Automox/test_data/automox-group-get.json new file mode 100644 index 000000000000..ed7af41afd7a --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-group-get.json @@ -0,0 +1,22 @@ +{ + "id": 1, + "organization_id": 1, + "name": "string", + "refresh_interval": 0, + "parent_server_group_id": 0, + "ui_color": "string", + "notes": "string", + "enable_os_auto_update": true, + "server_count": 0, + "wsus_config": { + "id": 0, + "server_group_id": 0, + "is_managed": true, + "server_url": "string", + "created_at": "string", + "updated_at": "string" + }, + "policies": [ + 0 + ] +} diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-groups-list.json b/Packs/Automox/Integrations/Automox/test_data/automox-groups-list.json new file mode 100644 index 000000000000..ce19bb7abbae --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-groups-list.json @@ -0,0 +1,46 @@ +[ + { + "id": 1, + "organization_id": 1, + "name": "", + "refresh_interval": 0, + "parent_server_group_id": 0, + "ui_color": "string", + "notes": "string", + "enable_os_auto_update": true, + "server_count": 0, + "wsus_config": { + "id": 0, + "server_group_id": 0, + "is_managed": true, + "server_url": "string", + "created_at": "string", + "updated_at": "string" + }, + "policies": [ + 0 + ] + }, + { + "id": 123, + "organization_id": 1, + "name": "string", + "refresh_interval": 0, + "parent_server_group_id": 0, + "ui_color": "string", + "notes": "string", + "enable_os_auto_update": true, + "server_count": 0, + "wsus_config": { + "id": 0, + "server_group_id": 0, + "is_managed": true, + "server_url": "string", + "created_at": "string", + "updated_at": "string" + }, + "policies": [ + 0 + ] + } +] diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-organization-users-list.json b/Packs/Automox/Integrations/Automox/test_data/automox-organization-users-list.json new file mode 100644 index 000000000000..6d0df718e882 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-organization-users-list.json @@ -0,0 +1,38 @@ +[ + { + "id": 1, + "firstname": "string", + "lastname": "string", + "email": "string", + "features": { + "mo": true + }, + "prefs": [ + { + "user_id": 1, + "pref_name": "string", + "value": "string" + } + ], + "orgs": [ + { + "id": 1, + "name": "string", + "trial_end_time": "2019-08-24T14:15:22Z", + "trial_expired": true, + "access_key": "string" + } + ], + "tags": [ + "string" + ], + "saml_enabled": true, + "rbac_roles": [ + { + "id": 0, + "name": "string", + "organization_id": 1 + } + ] + } +] diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-organizations-list.json b/Packs/Automox/Integrations/Automox/test_data/automox-organizations-list.json new file mode 100644 index 000000000000..5536e4a42479 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-organizations-list.json @@ -0,0 +1,39 @@ +[ + { + "id": 0, + "name": "string", + "addr1": "string", + "addr2": "string", + "city": "string", + "state": "string", + "zipcode": "string", + "country": "string", + "create_time": "2019-08-24T14:15:22Z", + "access_key": "string", + "server_limit": 0, + "stripe_cust": "string", + "cc_last": "string", + "cc_exp": "string", + "cc_brand": "string", + "cc_name": "string", + "billing_interval": 0, + "billing_interval_count": 0, + "trial_end_time": "2019-08-24T14:15:22Z", + "trial_expired": true, + "sub_plan": "string", + "sub_systems": "string", + "sub_create_time": "string", + "sub_end_time": "string", + "next_bill_time": "string", + "rate_id": 0, + "parent_id": 0, + "bill_overages": true, + "metadata": {}, + "legacy_billing": true, + "billing_name": "string", + "billing_email": "string", + "billing_phone": "string", + "device_limit": 0, + "device_count": 0 + } +] diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-policies-list.json b/Packs/Automox/Integrations/Automox/test_data/automox-policies-list.json new file mode 100644 index 000000000000..e47ff857e348 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-policies-list.json @@ -0,0 +1,58 @@ +[ + { + "id": 0, + "organization_id": 1, + "name": "string", + "policy_type_name": "patch", + "configuration": { + "auto_patch": true, + "auto_reboot": true, + "notify_user": true, + "missed_patch_window": true, + "patch_rule": "all", + "device_filters_enabled": true, + "device_filters": [ + { + "field": "tag", + "op": "in", + "value": [ + "Windows", + "Win10" + ] + } + ], + "include_optional": true, + "notify_reboot_user": true, + "notify_deferred_reboot_user": true, + "custom_notification_patch_message": "Necessary Windows updates are about to be installed!", + "custom_notification_patch_message_mac": "Necessary Mac updates are about to be installed!", + "custom_notification_reboot_message": "Necessary Windows updates are about to be installed! Reboot Needed!", + "custom_notification_reboot_message_mac": "Necessary Mac updates are about to be installed! Reboot Needed!", + "custom_notification_max_delays": 0, + "custom_notification_deferment_periods": [ + 1, + 4, + 8 + ], + "custom_pending_reboot_notification_message": "Your computer needs to restart to finish installing updates!", + "custom_pending_reboot_notification_message_mac": "Your Mac needs to restart to finish installing updates!", + "custom_pending_reboot_notification_max_delays": 0, + "custom_pending_reboot_notification_deferment_periods": [ + 2, + 4, + 6 + ], + "notify_user_message_timeout": 15, + "notify_deferred_reboot_user_timeout": 15, + "notify_user_auto_deferral_enabled": false, + "notify_deferred_reboot_user_auto_deferral_enabled": false + }, + "schedule_days": 0, + "schedule_weeks_of_month": 0, + "schedule_months": 0, + "schedule_time": "string", + "server_groups": [ + 0 + ] + } +] diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-batch-get.json b/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-batch-get.json new file mode 100644 index 000000000000..9039b3d11c0e --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-batch-get.json @@ -0,0 +1,24 @@ +{ + "id": 1, + "organization_id": 1, + "status": "processing", + "source": "string", + "created_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "updated_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "uploaded_at": "2019-08-24T14:15:22Z", + "task_count": 0, + "unknown_host_count": 0, + "impacted_device_count": 0, + "issue_count": 0, + "cve_count": 0 +} diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-batches-list.json b/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-batches-list.json new file mode 100644 index 000000000000..c220c5513e07 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-batches-list.json @@ -0,0 +1,26 @@ +[ + { + "id": 1, + "organization_id": 1, + "status": "processing", + "source": "string", + "created_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "updated_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "uploaded_at": "2019-08-24T14:15:22Z", + "task_count": 0, + "unknown_host_count": 0, + "impacted_device_count": 0, + "issue_count": 0, + "cve_count": 0 + } +] diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-file-upload.json b/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-file-upload.json new file mode 100644 index 000000000000..7852435fb554 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-file-upload.json @@ -0,0 +1,24 @@ +{ + "id": 1, + "organization_id": 0, + "status": "processing", + "source": "string", + "created_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "updated_by": { + "id": 0, + "firstname": "string", + "lastname": "string", + "email": "string" + }, + "uploaded_at": "2019-08-24T14:15:22Z", + "task_count": 0, + "unknown_host_count": 0, + "impacted_device_count": 0, + "issue_count": 0, + "cve_count": 0 +} diff --git a/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-tasks-list.json b/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-tasks-list.json new file mode 100644 index 000000000000..eb7000695ec4 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/automox-vulnerability-sync-tasks-list.json @@ -0,0 +1,55 @@ +{ + "metadata": { + "total_pages": 1, + "current_page": 0, + "limit": 25, + "total": 1 + }, + "data": [ + { + "id": 69, + "organization_id": 10586, + "task_type": "patch-now", + "payload": { + "patch_id": "CVE-2020-16937", + "severity": "critical", + "package_versions": [ + { + "id": "226977092", + "name": "bcdd12d9-e56a-46be-88f6-8a97a9f9ad18", + "version": "200", + "display_name": "2020-10 Cumulative Update for .NET Framework 3.5 and 4.8 for Windows 10 Version 1903 for x64 (KB4578974)", + "requires_reboot": false + }, + { + "id": "226977252", + "name": "bcdd12d9-e56a-46be-88f6-8a97a9f9ad18", + "version": "200", + "display_name": "2020-10 Cumulative Update for .NET Framework 3.5 and 4.8 for Windows 10 Version 1903 for x64 (KB4578974)", + "requires_reboot": false + } + ] + }, + "source": "Automox", + "notes": "", + "status": "awaiting_approval", + "created_by_user": { + "id": 12381, + "email": "user@example.com", + "firstname": "user", + "lastname": "user" + }, + "last_updated_by_user": { + "id": 12381, + "email": "user@example.com", + "firstname": "user", + "lastname": "user" + }, + "created_at": "2021-09-10T13:51:40+0000", + "updated_at": "2021-09-10T13:51:40+0000", + "partner_user_id": null, + "completed_at": null, + "cves": [] + } + ] +} diff --git a/Packs/Automox/Integrations/Automox/test_data/xsoar_vuln_test.csv b/Packs/Automox/Integrations/Automox/test_data/xsoar_vuln_test.csv new file mode 100644 index 000000000000..281ece0220a2 --- /dev/null +++ b/Packs/Automox/Integrations/Automox/test_data/xsoar_vuln_test.csv @@ -0,0 +1,2 @@ +Hostname, CVE ID, Severity +WinDev2104Eval,CVE-2021-44228,high diff --git a/Packs/Automox/Playbooks/Upload_Vulnerability_Report_to_Automox.yml b/Packs/Automox/Playbooks/Upload_Vulnerability_Report_to_Automox.yml new file mode 100644 index 000000000000..37efd93b0fac --- /dev/null +++ b/Packs/Automox/Playbooks/Upload_Vulnerability_Report_to_Automox.yml @@ -0,0 +1,362 @@ +id: Upload Vulnerability Report to Automox +version: -1 +fromversion: 6.0.0 +name: Upload Vulnerability Report to Automox +description: This sub-playbook takes the entryId of a vulnerability report CSV file and uploads it to Automox for remediation. +tags: +- Endpoint +- Vulnerability +- Remediation +- Automated +starttaskid: "0" +tasks: + "0": + id: "0" + taskid: dd9db72a-6c4a-40c9-8c63-eb0fd97ea17c + type: start + task: + id: dd9db72a-6c4a-40c9-8c63-eb0fd97ea17c + version: -1 + name: "" + description: "" + iscommand: false + brand: "" + nexttasks: + '#none#': + - "1" + separatecontext: false + view: |- + { + "position": { + "x": 610, + "y": -10 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "1": + id: "1" + taskid: c11dbc02-6d2b-44e9-88e1-fa2951e4bbfe + type: condition + task: + id: c11dbc02-6d2b-44e9-88e1-fa2951e4bbfe + version: -1 + name: Is Automox enabled? + description: Checks whether Automox is enabled + type: condition + iscommand: false + brand: "" + nexttasks: + '#default#': + - "7" + "yes": + - "2" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: isExists + left: + value: + complex: + root: modules + filters: + - - operator: isEqualString + left: + value: + simple: modules.brand + iscontext: true + right: + value: + simple: Automox + - - operator: isEqualString + left: + value: + simple: modules.state + iscontext: true + right: + value: + simple: active + accessor: brand + iscontext: true + view: |- + { + "position": { + "x": 610, + "y": 120 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "2": + id: "2" + taskid: 6c18bf23-4a0b-49f5-8e19-04efa401d9a6 + type: regular + task: + id: 6c18bf23-4a0b-49f5-8e19-04efa401d9a6 + version: -1 + name: Upload Vulnerability Report + description: Upload a vulnerability report to Automox Vulnerability Sync. + script: '|||automox-vulnerability-sync-file-upload' + type: regular + iscommand: true + brand: "" + nexttasks: + '#none#': + - "3" + scriptarguments: + csv_file_name: + complex: + root: File + filters: + - - operator: isEqualString + left: + value: + simple: File.EntryID + iscontext: true + right: + value: + simple: inputs.entry_id + iscontext: true + accessor: Name + entry_id: + simple: ${inputs.entry_id} + separatecontext: false + view: |- + { + "position": { + "x": 410, + "y": 340 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "3": + id: "3" + taskid: a17056ef-a0b6-4360-8802-660e56599195 + type: condition + task: + id: a17056ef-a0b6-4360-8802-660e56599195 + version: -1 + name: Was the file successfully uploaded? + description: Checks to see if the file upload in the previous step was successful. + type: condition + iscommand: false + brand: "" + nexttasks: + '#default#': + - "7" + "yes": + - "4" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: isExists + left: + value: + simple: Automox.VulnUpload.batch_id + iscontext: true + view: |- + { + "position": { + "x": 410, + "y": 490 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "4": + id: "4" + taskid: 85afe6e5-17e8-4598-81d7-62b8e199621a + type: playbook + task: + id: 85afe6e5-17e8-4598-81d7-62b8e199621a + version: -1 + name: GenericPolling + description: |- + Use this playbook as a sub-playbook to block execution of the master playbook until a remote action is complete. + This playbook implements polling by continuously running the command in Step \#2 until the operation completes. + The remote action should have the following structure: + + 1. Initiate the operation. + 2. Poll to check if the operation completed. + 3. (optional) Get the results of the operation. + playbookName: GenericPolling + type: playbook + iscommand: false + brand: "" + nexttasks: + '#none#': + - "5" + scriptarguments: + Ids: + simple: ${Automox.VulnUpload.batch_id} + Interval: + simple: "1" + PollingCommandArgName: + simple: batch_id + PollingCommandName: + simple: automox-vulnerability-sync-batch-get + Timeout: + simple: "10" + dt: + simple: Automox.VulnSyncBatch(val.status == 'processing'||val.status=='building') + separatecontext: true + loop: + iscommand: false + exitCondition: "" + wait: 1 + max: 100 + view: |- + { + "position": { + "x": 410, + "y": 760 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "5": + id: "5" + taskid: b91e3b78-afd2-41cc-81ec-bc8a6f068957 + type: regular + task: + id: b91e3b78-afd2-41cc-81ec-bc8a6f068957 + version: -1 + name: Approve Batch + description: Perform an action on an Automox Vulnerability Sync batch. + script: '|||automox-vulnerability-sync-batch-action' + type: regular + iscommand: true + brand: "" + nexttasks: + '#none#': + - "6" + scriptarguments: + action: + simple: accept + batch_id: + simple: ${Automox.VulnUpload.batch_id} + separatecontext: false + view: |- + { + "position": { + "x": 410, + "y": 920 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "6": + id: "6" + taskid: fb737e18-cfa3-45be-8f60-dbe5d71d93fa + type: regular + task: + id: fb737e18-cfa3-45be-8f60-dbe5d71d93fa + version: -1 + name: Get Report + description: Get details about a Vulnerability Sync batch. + script: '|||automox-vulnerability-sync-batch-get' + type: regular + iscommand: true + brand: "" + nexttasks: + '#none#': + - "7" + scriptarguments: + batch_id: + simple: ${Automox.VulnUpload.batch_id} + separatecontext: false + view: |- + { + "position": { + "x": 410, + "y": 1080 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "7": + id: "7" + taskid: c75fd028-4c6a-493c-80fe-949448af5554 + type: title + task: + id: c75fd028-4c6a-493c-80fe-949448af5554 + version: -1 + name: Done + description: "" + type: title + iscommand: false + brand: "" + separatecontext: false + view: |- + { + "position": { + "x": 660, + "y": 1270 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false +view: |- + { + "linkLabelsPosition": {}, + "paper": { + "dimensions": { + "height": 1345, + "width": 630, + "x": 410, + "y": -10 + } + } + } +inputs: +- key: entry_id + value: {} + required: true + description: "The entryId of a vulnerability report CSV file. Currently accepted formats can be found in the Automox documentation: https://support.automox.com/help/exporting-vulnerability-scanner-reports" + playbookInputQuery: +outputs: [] +tests: +- No tests (auto formatted) diff --git a/Packs/Automox/Playbooks/Upload_Vulnerability_Report_to_Automox_README.md b/Packs/Automox/Playbooks/Upload_Vulnerability_Report_to_Automox_README.md new file mode 100644 index 000000000000..4719db90404f --- /dev/null +++ b/Packs/Automox/Playbooks/Upload_Vulnerability_Report_to_Automox_README.md @@ -0,0 +1,35 @@ +This sub-playbook takes the entryId of a vendor-generated vulnerability report CSV and uploads it to Automox for remediation. + +Information about supported CSV formats can be found in the [Automox Support Documentation](https://support.automox.com/help/exporting-vulnerability-scanner-reports) + +## Dependencies +This playbook uses the following sub-playbooks, integrations, and scripts. + +### Sub-playbooks +* GenericPolling + +### Integrations +* Automox + +### Scripts +This playbook does not use any scripts. + +### Commands +* automox-vulnerability-sync-file-upload +* automox-vulnerability-sync-batch-get +* automox-vulnerability-sync-batch-action + +## Playbook Inputs +--- + +| **Name** | **Description** | **Default Value** | **Required** | +| --- | --- | --- | --- | +| entry_id | The entryId of a vendor-generated vulnerability report. | | Required | + +## Playbook Outputs +--- +There are no outputs for this playbook. + +## Playbook Image +--- +![Upload Vulnerabilities to Automox](../doc_files/Upload_Vulnerability_Report_Image.png) diff --git a/Packs/Automox/README.md b/Packs/Automox/README.md new file mode 100644 index 000000000000..575ab503b817 --- /dev/null +++ b/Packs/Automox/README.md @@ -0,0 +1,16 @@ +# Automox Content Pack for XSOAR +The Automox Content Pack for XSOAR empowers users by providing the resources to administrate your IT organization, and remediate vulnerabilities with ease. Use the Automox integration to create device groups, update devices, and run policies. This content pack also includes a sub-playbook to use in your vulnerability remediation workflows to identify vulnerable devices, and automatically generate the remediation tasks necessary to patch them in the Automox platform. + +# What does this pack do? +- Upload Vulnerability Reports +- Get and approve/reject batches of tasks +- Get, update, and delete device groups +- Get and update devices +- Get organizations and their users +- Get and run policies + +This pack includes: +- Integrations: + - **Automox**: Administrate your IT organization from XSOAR with comprehensive commands for the Automox platform. +- Playbooks: + - **Upload Vulnerability Report to Automox**: This sub-playbook enables you to upload vulnerability data with ease. This playbook accepts the entryId of a vulnerability report CSV, and uploads it to Automox. After upload, remediation tasks are identified and created automatically for affected devices. diff --git a/Packs/Automox/doc_files/Upload_Vulnerability_Report_Image.png b/Packs/Automox/doc_files/Upload_Vulnerability_Report_Image.png new file mode 100644 index 000000000000..ce8ad5f3b550 Binary files /dev/null and b/Packs/Automox/doc_files/Upload_Vulnerability_Report_Image.png differ diff --git a/Packs/Automox/pack_metadata.json b/Packs/Automox/pack_metadata.json new file mode 100644 index 000000000000..a61e1b520358 --- /dev/null +++ b/Packs/Automox/pack_metadata.json @@ -0,0 +1,44 @@ +{ + "name": "Automox", + "description": "This pack empowers you with comprehensive solutions to manage your Automox device fleet with ease!", + "support": "partner", + "currentVersion": "1.0.0", + "author": "Automox Inc.", + "url": "https://www.automox.com/", + "email": "support@automox.com", + "categories": [ + "Endpoint", + "Vulnerability Management" + ], + "tags": [ + "IT", + "Network", + "Security", + "Use Case", + "New" + ], + "useCases": [ + "IT Services", + "Vulnerability Management" + ], + "keywords": [ + "Automox", + "Patch", + "Endpoint", + "Vulnerability", + "CVE" + ], + "marketplaces": [ + "xsoar", + "marketplacev2" + ], + "dependencies": { + "CommonPlaybooks": { + "mandatory": true, + "display_name": "Common Playbooks" + } + }, + "displayedImages": [ + "CommonPlaybooks" + ] +}