From 9599681526f470a6247e3d4c1c215dfad565f367 Mon Sep 17 00:00:00 2001 From: Aviya Baumgarten <71635916+abaumgarten@users.noreply.github.com> Date: Tue, 12 Apr 2022 12:12:13 +0300 Subject: [PATCH] Absolute V1 (#18079) * stated the yml file * start implementation * auth implementation * auth implementation works correctly * update_custom_device_field_command added * added more commands * added UT and query fix * more commands implementation * edit outputs * added get location command * added description * added description * fixes * fixes * added UT * added UTs * added UTs * added UTs * added UTs * added UTs * added UTs * added UTs * added UTs * update docker * update mypy * Delete test.py * delete file * update location command * update custom fields command hr * update hr * change auth params * change hm create freeze msg * update command * update command * update command * added TPB * fixed an issue where the response is empty * added readme * added query example to readme * secrets ignore * code review * update human readable for freeze req command * Update Absolute_description.md Done. * Update Absolute.yml Done. * Update README.md Done. * Update README.md Done. * fix error response * fix error response Co-authored-by: ShirleyDenkberg <62508050+ShirleyDenkberg@users.noreply.github.com> --- Packs/Absolute/.pack-ignore | 0 Packs/Absolute/.secrets-ignore | 8 + .../Integrations/Absolute/Absolute.py | 962 +++++++++++++++++ .../Integrations/Absolute/Absolute.yml | 928 +++++++++++++++++ .../Absolute/Absolute_description.md | 38 + .../Integrations/Absolute/Absolute_image.png | Bin 0 -> 2040 bytes .../Integrations/Absolute/Absolute_test.py | 500 +++++++++ Packs/Absolute/Integrations/Absolute/Pipfile | 18 + .../Integrations/Absolute/Pipfile.lock | 369 +++++++ .../Absolute/Integrations/Absolute/README.md | 977 ++++++++++++++++++ .../Integrations/Absolute/command_examples | 14 + .../custom_device_field_list_response.json | 22 + ...om_get_device_freeze_request_response.json | 82 ++ .../device_freeze_message_list_response.json | 11 + .../test_data/device_location_get.json | 52 + .../test_data/unenroll_device_response.json | 18 + Packs/Absolute/README.md | 42 + .../TestPlaybooks/playbook-Absolute.yml | 668 ++++++++++++ Packs/Absolute/pack_metadata.json | 19 + Tests/conf.json | 5 + 20 files changed, 4733 insertions(+) create mode 100644 Packs/Absolute/.pack-ignore create mode 100644 Packs/Absolute/.secrets-ignore create mode 100644 Packs/Absolute/Integrations/Absolute/Absolute.py create mode 100644 Packs/Absolute/Integrations/Absolute/Absolute.yml create mode 100644 Packs/Absolute/Integrations/Absolute/Absolute_description.md create mode 100644 Packs/Absolute/Integrations/Absolute/Absolute_image.png create mode 100644 Packs/Absolute/Integrations/Absolute/Absolute_test.py create mode 100644 Packs/Absolute/Integrations/Absolute/Pipfile create mode 100644 Packs/Absolute/Integrations/Absolute/Pipfile.lock create mode 100644 Packs/Absolute/Integrations/Absolute/README.md create mode 100644 Packs/Absolute/Integrations/Absolute/command_examples create mode 100644 Packs/Absolute/Integrations/Absolute/test_data/custom_device_field_list_response.json create mode 100644 Packs/Absolute/Integrations/Absolute/test_data/custom_get_device_freeze_request_response.json create mode 100644 Packs/Absolute/Integrations/Absolute/test_data/device_freeze_message_list_response.json create mode 100644 Packs/Absolute/Integrations/Absolute/test_data/device_location_get.json create mode 100644 Packs/Absolute/Integrations/Absolute/test_data/unenroll_device_response.json create mode 100644 Packs/Absolute/README.md create mode 100644 Packs/Absolute/TestPlaybooks/playbook-Absolute.yml create mode 100644 Packs/Absolute/pack_metadata.json diff --git a/Packs/Absolute/.pack-ignore b/Packs/Absolute/.pack-ignore new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/Packs/Absolute/.secrets-ignore b/Packs/Absolute/.secrets-ignore new file mode 100644 index 000000000000..096311ae572f --- /dev/null +++ b/Packs/Absolute/.secrets-ignore @@ -0,0 +1,8 @@ +https://absolute.com +absolute.com +https://cc.absolute.com +https://cc.us.absolute.com +https://cc.eu2.absolute.com +https://api.absolute.com +https://api.us.absolute.com +https://api.eu2.absolute.com \ No newline at end of file diff --git a/Packs/Absolute/Integrations/Absolute/Absolute.py b/Packs/Absolute/Integrations/Absolute/Absolute.py new file mode 100644 index 000000000000..3e528307e382 --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/Absolute.py @@ -0,0 +1,962 @@ +import copy +import hashlib + +import demistomock as demisto +from CommonServerPython import * # noqa # pylint: disable=unused-wildcard-import +from CommonServerUserPython import * # noqa +import urllib.parse +import requests +import traceback +from typing import Dict, Any +import hmac + +# Disable insecure warnings +requests.packages.urllib3.disable_warnings() # pylint: disable=no-member + +''' CONSTANTS ''' + +ABSOLUTE_URL_TO_API_URL = { + 'https://cc.absolute.com': 'https://api.absolute.com', + 'https://cc.us.absolute.com': 'https://api.us.absolute.com', + 'https://cc.eu2.absolute.com': 'https://api.eu2.absolute.com', +} +ABSOLUTE_URL_REGION = { + 'https://api.absolute.com': 'cadc', + 'https://api.us.absolute.com': 'usdc', + 'https://api.eu2.absolute.com': 'eudc', +} +ABSOLUTE_AGET_STATUS = { + 'Active': 'A', + 'Disabled': 'D', + 'Inactive': 'I', +} +INTEGRATION = "Absolute" +STRING_TO_SIGN_ALGORITHM = "ABS1-HMAC-SHA-256" +STRING_TO_SIGN_SIGNATURE_VERSION = "abs1" +DATE_FORMAT = '%Y%m%dT%H%M%SZ' +DATE_FORMAT_CREDENTIAL_SCOPE = '%Y%m%d' + +DEVICE_LIST_RETURN_FIELDS = [ + "id", + "esn", + "lastConnectedUtc", + "systemName", + "systemModel", + "fullSystemName", + "agentStatus", + "os.name", + "systemManufacturer", + "serial", + "systemType", + "localIp", + "publicIp", + "espInfo.encryptionStatus", +] + +DEVICE_GET_COMMAND_RETURN_FIELDS = [ + "id", + "esn", + "domain", + "lastConnectedUtc", + "systemName", + "systemModel", + "systemType", + "fullSystemName", + "agentStatus", + "os.name", + "os.version", + "os.currentBuild", + "os.architecture", + "os.installDate", + "os.productKey", + "os.serialNumber", + "os.lastBootTime", + "systemManufacturer", + "serial", + "localIp", + "publicIp", + "username", + "espInfo.encryptionStatus", + "bios.id", + "bios.serialNumber", + "bios.version", + "bios.versionDate", + "bios.smBiosVersion", + "policyGroupUid", + "policyGroupName", + "isStolen", + "deviceStatus.type", + "deviceStatus.reported", + "networkAdapters.networkSSID" +] + +DEVICE_GET_LOCATION_COMMAND_RETURN_FIELDS = [ + "geoData.location.coordinates", + "geoData.geoAddress.city", + "geoData.geoAddress.state", + "geoData.geoAddress.countryCode", + "geoData.geoAddress.country", + "geoData.locationTechnology", + "geoData.accuracy", + "geoData.lastUpdate", +] + + +class Client(BaseClient): + def __init__(self, base_url: str, token_id: str, secret_key: str, verify: bool, headers: dict, proxy: bool, + x_abs_date: str): + """ + Client to use in the Absolute integration. Overrides BaseClient. + + Args: + base_url (str): URL to access when doing a http request. + token_id (str): The Absolute token id + secret_key (str): User's Absolute secret key + verify (bool): Whether to check for SSL certificate validity. + proxy (bool): Whether the client should use proxies. + headers (dict): Headers to set when doing a http request. + x_abs_date (str): The automatically generated header that indicates the time (in UTC) the request was made. + """ + super().__init__(base_url=base_url, verify=verify, proxy=proxy) + self._payload = None + self._base_url = base_url + self._token_id = token_id + self._secret_key = secret_key + self._headers = headers + self._x_abs_date = x_abs_date + + def prepare_request_for_api(self, method: str, canonical_uri: str, query_string: str, payload: str): + """ + The Absolute v2 API requires following 5 steps in order to properly authorize the API request. + We must follow the steps: + 1. Create a canonical request + 2. Create a signing string + 3. Create a signing key + 4. Create a signature + 5. Add the authorization header + + For more info https://www.absolute.com/media/2221/abt-api-working-with-absolute.pdf + """ + canonical_req = self.create_canonical_request(method, canonical_uri, query_string, payload) + signing_string = self.create_signing_string(canonical_req) + signing_key = self.create_signing_key() + signing_signature = self.create_signature(signing_string, signing_key) + self._headers['Authorization'] = self.add_authorization_header(signing_signature) + + def create_canonical_request(self, method: str, canonical_uri: str, query_string: str, payload: str) -> str: + """ + The canonical request should look like (for example): + + GET + /v2/reporting/devices + %24filter=substringof%28%2760001%27%2C%20esn%29%20eq%20true + host:api.absolute.com + content-type:application/json + x-abs-date:20170926T172213Z + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + """ + canonical_request = [method, canonical_uri, self.prepare_query_string_for_canonical_request(query_string), + self.prepare_canonical_headers(), self.prepare_canonical_hash_payload(payload)] + return "\n".join(canonical_request).rstrip() + + def prepare_query_string_for_canonical_request(self, query_string: str) -> str: + """ + Query is given as a string represents the filter query. For example, + query_string = "$top=10 $skip=20" + 1. Splitting into a list (by space as a separator). + 2. Sorting arguments in ascending order; for example, 'A' is before 'a'. + 3. URI encode the parameter name and value using URI generic syntax. + 4. Reassembling the list into a string. + """ + if not query_string: + return "" + return urllib.parse.quote(query_string, safe='=&') + + def prepare_canonical_headers(self) -> str: + """ + Create the canonical headers and signed headers. Header names must be trimmed and lowercase, + and sorted in code point order from low to high. Note that there is a trailing \n. + """ + canonical_headers = "" + for header, value in self._headers.items(): + canonical_headers += f'{header.lower()}:{value.strip()}\n' + return canonical_headers.rstrip() + + def prepare_canonical_hash_payload(self, payload: str) -> str: + """ + According to the API we should do: + Hash the entire body using SHA-256 algorithm, HexEncode. + Create payload hash (hash of the request body content). + For GET requests, the payload is an empty string (""). + """ + return hashlib.sha256(payload.encode('utf-8')).hexdigest() + + def create_signing_string(self, canonical_req: str) -> str: + """ + The signing string should look like (for example): + + ABS1-HMAC-SHA-256 + 20170926T172032Z + 20170926/cadc/abs1 + 63f83d2c7139b6119d4954e6766ce90871e41334c3f29b6d64201639d273fa19 + + Algorithm: The string used to identify the algorithm. For example, ABS1-HMAC-SHA-256 + + RequestedDateTime: The date and time (in UTC) from XAbs-Date. Format:
TZ + + CredentialScope: The CredentialScope is defined in three parts: + 1. The date (in UTC) of the request. Format: YYYYMMDD + 2. Region or data center (must be in lowercase) Possible values: cadc, usdc, eudc + 3. Version or type of signature. Always abs1 + + HashedCanonicalRequest: The hashed, hex-converted, and lowercase value of the canonical request. + """ + credential_scope = self.create_credential_scope() + canonical_req_hashed = hashlib.sha256(canonical_req.encode('utf-8')).hexdigest() + return "\n".join([STRING_TO_SIGN_ALGORITHM, self._x_abs_date, credential_scope, canonical_req_hashed]) + + def create_credential_scope(self) -> str: + """ + CredentialScope: The CredentialScope is defined in three parts: + 1. The date (in UTC) of the request. Format: YYYYMMDD + 2. Region or data center (must be in lowercase) Possible values: cadc, usdc, eudc + 3. Version or type of signature. Always abs1 + """ + credential_scope_date = datetime.utcnow().date().strftime(DATE_FORMAT_CREDENTIAL_SCOPE) + region = ABSOLUTE_URL_REGION[self._base_url] + return f'{credential_scope_date}/{region}/{STRING_TO_SIGN_SIGNATURE_VERSION}' + + def create_signing_key(self): + """ + HMAC-SHA256 is used for authentication. + The signing key should be created by: + + kSecret: The kSecret value is calculated by concatenating the static string “ABS1” with the value of the + secret key from your API token and then encoding the resulting string using UTF8. + The secret is the secret key value from the token that you created in the Absolute console. + + kDate: The date (in UTC) of the request. Format:
. The result is a byte array. + + kSigning: Use the binary hash to get a pure binary kSigning key. The result is a byte array. + Note:Do not use a hex digest method. + + """ + credential_scope_date = datetime.now().date().strftime(DATE_FORMAT_CREDENTIAL_SCOPE) + k_date = sign((STRING_TO_SIGN_SIGNATURE_VERSION.upper() + self._secret_key).encode('utf-8'), + credential_scope_date) + return sign(k_date, 'abs1_request') + + def create_signature(self, signing_string, signing_key): + """ + As a result of creating a signing key, kSigning is used as the key for hashing. + The StringToSign is the string data to be hashed. + + The signature should look like this: + + signature = lowercase(hexencode(HMAC(kSigning, StringToSign))) + """ + return hmac.new(signing_key, signing_string.encode('utf-8'), hashlib.sha256).hexdigest() + + def add_authorization_header(self, signing_signature: str) -> str: + """ + Use the standard HTTP Authorization header. Should look like this: + Authorization: Credential=/, + SignedHeaders=, Signature= + + Authorization: The string used to identify the algorithm + + Credential: The token ID + + CredentialScope: the same as described in the create_credential_scope func. + + SignedHeaders: Semi-colon ; delimited list of lowercase headers used in CanonicalHeaders + + Signature: The fully calculated resulting signature from the signing key and the signature + """ + credential_scope = self.create_credential_scope() + canonical_headers = ";".join([header.lower() for header in self._headers.keys()]) + # There is a space after each comma in the authorization header + return f'{STRING_TO_SIGN_ALGORITHM} Credential={self._token_id}/{credential_scope}, ' \ + f'SignedHeaders={canonical_headers}, Signature={signing_signature}' + + def api_request_absolute(self, method: str, url_suffix: str, body: str = "", success_status_code=None, + query_string: str = ''): + """ + Makes an HTTP request to the Absolute API. + Args: + method (str): HTTP request method (GET/PUT/POST/DELETE). + url_suffix (str): The API endpoint. + body (str): The body to set. + success_status_code (int): an HTTP status code of success. + query_string (str): The query to filter results by. + + Note: As on the put and post requests we should pass a body from type str, we couldn't use the _http_request + function in CSP (as it does not receive body from type str). + """ + demisto.debug(f'current request is: method={method}, url suffix={url_suffix}, body={body}') + full_url = urljoin(self._base_url, url_suffix) + + if success_status_code is None: + success_status_code = [200] + + self.prepare_request_for_api(method=method, canonical_uri=url_suffix, query_string=query_string, payload=body) + + if method == 'GET': + if query_string: + url_suffix = f'{url_suffix}?{self.prepare_query_string_for_canonical_request(query_string)}' + return self._http_request(method=method, url_suffix=url_suffix, headers=self._headers, + return_empty_response=True) + + elif method == 'DELETE': + return self._http_request(method=method, url_suffix=url_suffix, headers=self._headers, + ok_codes=tuple(success_status_code), resp_type='response') + + elif method == 'PUT': + res = requests.put(full_url, data=body, headers=self._headers, verify=self._verify) + if res.status_code not in success_status_code: + raise DemistoException(f'{INTEGRATION} error: the operation was failed due to: {res.json()}') + + elif method == 'POST': + res = requests.post(full_url, data=body, headers=self._headers, verify=self._verify) + if res.status_code not in success_status_code: + raise DemistoException(f'{INTEGRATION} error: the operation was failed due to: {res.json()}') + return res.json() + + +def sign(key, msg): + return hmac.new(key, msg.encode('utf-8'), hashlib.sha256).digest() + + +def validate_absolute_api_url(base_url): + if base_url not in ABSOLUTE_URL_TO_API_URL.keys(): + raise_demisto_exception( + f"The Absolute server url {base_url} in not a valid url. " + f"Possible options: {list(ABSOLUTE_URL_TO_API_URL.keys())}") + return ABSOLUTE_URL_TO_API_URL[base_url] + + +def test_module(client: Client) -> str: + """Tests API connectivity to Absolute """ + try: + client.api_request_absolute('GET', '/v2/device-freeze/messages', success_status_code=(200, 204)) + message = 'ok' + 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: + raise e + return message + + +def parse_device_field_list_response(response: dict) -> Dict[str, Any]: + parsed_data = {'DeviceUID': response.get('deviceUid'), 'ESN': response.get('esn'), 'CDFValues': []} # type: ignore + for cdf_item in response.get('cdfValues', []): + parsed_data['CDFValues'].append({ # type: ignore + 'CDFUID': cdf_item.get('cdfUid'), + 'FieldKey': cdf_item.get('fieldKey'), + 'FieldName': cdf_item.get('fieldName'), + 'CategoryCode': cdf_item.get('categoryCode'), + 'FieldValue': cdf_item.get('fieldValue'), + 'Type': cdf_item.get('type'), + }) + return parsed_data + + +def parse_device_field_list_response_human_readable(outputs): + human_readable = [] + for cdf_values in outputs.get('CDFValues', []): + human_readable.append({ + 'Filed Name': cdf_values.get('FieldName'), + 'CDF ID': cdf_values.get('CDFUID'), + 'Field Value': cdf_values.get('FieldName'), + }) + return human_readable + + +def get_custom_device_field_list_command(args, client) -> CommandResults: + device_id = args.get('device_id') + res = client.api_request_absolute('GET', f'/v2/devices/{device_id}/cdf') + outputs = parse_device_field_list_response(res) + human_readable = tableToMarkdown(f'{INTEGRATION} Custom device field list', + parse_device_field_list_response_human_readable(outputs), + removeNull=True) + return CommandResults(outputs=outputs, + outputs_prefix="Absolute.CustomDeviceField", + outputs_key_field='DeviceUID', + readable_output=human_readable, raw_response=res) + + +def update_custom_device_field_command(args, client) -> CommandResults: + device_id = args.get('device_id') + cdf_uid = args.get('cdf_uid') + field_value = args.get('value') + + payload = json.dumps({"cdfValues": [{'cdfUid': cdf_uid, 'fieldValue': field_value}]}) + client.api_request_absolute('PUT', f'/v2/devices/{device_id}/cdf', body=payload) + return CommandResults(readable_output=f"Device {device_id} with value {field_value} was updated successfully.") + + +def validate_device_freeze_type_offline(offline_time_seconds): + if not offline_time_seconds: + # the default is 30 days + offline_time_seconds = 22592000 + else: + # must be between 1200 seconds (20 minutes) and 172800000 seconds (2000 days) + offline_time_seconds_valid = 1200 <= offline_time_seconds <= 172800000 + if not offline_time_seconds_valid: + raise_demisto_exception("the offline_time_seconds arg is not valid. Must be between 1200 seconds" + " (20 minutes) and 172800000 seconds (2000 days).") + return offline_time_seconds + + +def raise_demisto_exception(msg): + raise DemistoException(f'{INTEGRATION} error: {msg}') + + +def validate_device_freeze_type_scheduled(scheduled_freeze_date): + if not scheduled_freeze_date: + raise_demisto_exception('When setting device_freeze_type to be Scheduled, you must specify the scheduled_' + 'freeze_date arg.') + return scheduled_freeze_date + + +def validate_passcode_type_args(passcode_type, passcode, passcode_length, payload): + if passcode_type == "UserDefined": + if not passcode: + raise_demisto_exception( + 'when setting passcode_type to be UserDefined, you must specify the passcode arg.') + payload["passcodeDefinition"].update({"passcode": passcode}) + + elif passcode_type == "RandomForEach" or passcode_type == "RandomForAl": + not_valid_passcode_length = not passcode_length or passcode_length > 8 or passcode_length < 4 + if not_valid_passcode_length: + raise_demisto_exception('when setting passcode_type to be RandomForEach or RandomForAl, ' + 'you must specify the passcode_length arg to be between 4 to 8.') + payload["passcodeDefinition"].update({"length": passcode_length}) + + return payload + + +def parse_freeze_device_response(response: dict): + outputs = {'RequestUID': response.get('requestUid'), 'SucceededDeviceUIDs': response.get('deviceUids')} + errors = response.get('errors', []) + human_readable_errors = [] + if errors: + for error in errors: + human_readable_errors.append({'Failed UID': ','.join(error.get('detail', []).get('deviceUids')), + 'Error Message': error.get('message', '')}) + outputs['Errors'] = errors + outputs['FailedDeviceUIDs'] = human_readable_errors + return outputs + + +def device_freeze_request_command(args, client) -> CommandResults: + payload = prepare_payload_to_freeze_request(args) + res = client.api_request_absolute('POST', '/v2/device-freeze/requests', body=json.dumps(payload), + success_status_code=[201]) + outputs = parse_freeze_device_response(res) + human_readable = tableToMarkdown(f'{INTEGRATION} device freeze requests results', outputs, + headers=['FailedDeviceUIDs', 'RequestUID', 'SucceededDeviceUIDs'], removeNull=True, + json_transform_mapping={'FailedDeviceUIDs': JsonTransformer()},) + + outputs.pop('FailedDeviceUIDs', '') + return CommandResults(readable_output=human_readable, outputs=outputs, outputs_prefix="Absolute.FreezeRequest", + outputs_key_field="RequestUID", raw_response=res) + + +def prepare_payload_to_freeze_request(args): + request_name = args.get('request_name') + html_message = args.get('html_message') + message_name = args.get('message_name') + device_ids = argToList(args.get('device_ids')) + notification_emails = argToList(args.get('notification_emails')) + device_freeze_type = args.get('device_freeze_type') + passcode_type = args.get('passcode_type') + + payload = { + "name": request_name, + "message": html_message, + "messageName": message_name, + "freezeDefinition": + { + "deviceFreezeType": device_freeze_type + }, + "deviceUids": device_ids, + "notificationEmails": notification_emails, + "passcodeDefinition": + { + "option": passcode_type + } + } + + scheduled_freeze_date = args.get('scheduled_freeze_date') + offline_time_seconds = arg_to_number(args.get('offline_time_seconds'), required=False) + if device_freeze_type == "Scheduled": + scheduled_freeze_date = validate_device_freeze_type_scheduled(scheduled_freeze_date) + payload["freezeDefinition"].update({"scheduledFreezeDate": scheduled_freeze_date}) + + elif device_freeze_type == "Offline": + offline_time_seconds = validate_device_freeze_type_offline(offline_time_seconds) + payload["freezeDefinition"].update({"offlineTimeSeconds": offline_time_seconds}) + passcode = args.get('passcode') + passcode_length = arg_to_number(args.get('passcode_length'), required=False) + payload = validate_passcode_type_args(passcode_type, passcode, passcode_length, payload) + return payload + + +def remove_device_freeze_request_command(args, client) -> CommandResults: + device_ids = argToList(args.get('device_ids')) + remove_scheduled = args.get('remove_scheduled') + remove_offline = args.get('remove_offline') + + # from the API docs: unfreeze - Make frozen devices usable immediately, Applies to all Freeze types. + # Always set to true + payload = {"deviceUids": device_ids, "unfreeze": "true", "removeScheduled": remove_scheduled, + "removeOffline": remove_offline} + + client.api_request_absolute('PUT', '/v2/device-freeze/requests', body=json.dumps(payload), + success_status_code=[204]) + return CommandResults( + readable_output=f"Successfully removed freeze request for devices ids: {args.get('device_ids')}.") + + +def parse_get_device_freeze_response(response: List): + parsed_data = [] + for freeze_request in response: + parsed_data.append({ + 'ID': freeze_request.get('id'), + 'AccountUid': freeze_request.get('accountUid'), + 'ActionRequestUid': freeze_request.get('actionRequestUid'), + 'DeviceUid': freeze_request.get('deviceUid'), + 'Name': freeze_request.get('name'), + 'Statuses': freeze_request.get('statuses', []), + 'Configuration': freeze_request.get('configuration', {}), + 'Requester': freeze_request.get('requester'), + 'RequesterUid': freeze_request.get('requesterUid'), + 'CreatedUTC': freeze_request.get('createdUTC'), + 'ChangedUTC': freeze_request.get('changedUTC'), + 'NotificationEmails': freeze_request.get('notificationEmails'), + 'EventHistoryId': freeze_request.get('eventHistoryId'), + 'PolicyGroupUid': freeze_request.get('policyGroupUid'), + 'PolicyConfigurationVersion': freeze_request.get('policyConfigurationVersion'), + 'FreezePolicyUid': freeze_request.get('freezePolicyUid'), + 'Downloaded': freeze_request.get('downloaded'), + 'IsCurrent': freeze_request.get('isCurrent'), + # for the freeze message command + 'Content': freeze_request.get('content'), + 'CreatedBy': freeze_request.get('createdBy'), + 'ChangedBy': freeze_request.get('changedBy'), + }) + return parsed_data + + +def parse_device_freeze_message_response(response): + if not isinstance(response, list): + # in case we got here from the f'/v2/device-freeze/messages/{message_id}' url, the response is a json + response = [response] + parsed_data = [] + for freeze_request in response: + parsed_data.append({ + 'ID': freeze_request.get('id'), + 'Name': freeze_request.get('name'), + 'CreatedUTC': freeze_request.get('createdUTC'), + 'ChangedUTC': freeze_request.get('changedUTC'), + 'Content': freeze_request.get('content'), + 'CreatedBy': freeze_request.get('createdBy'), + 'ChangedBy': freeze_request.get('changedBy'), + }) + return parsed_data + + +def get_device_freeze_request_command(args, client) -> CommandResults: + request_uid = args.get('request_uid') + res = client.api_request_absolute('GET', f'/v2/device-freeze/requests/{request_uid}') + outputs = parse_get_device_freeze_response(res) + + human_readable = tableToMarkdown(f'{INTEGRATION} Freeze request details for: {request_uid}', outputs, + headers=['ID', 'Name', 'AccountUid', 'ActionRequestUid', 'EventHistoryId', + 'FreezePolicyUid', 'CreatedUTC', 'ChangedUTC', 'Requester'], + removeNull=True) + return CommandResults(outputs=outputs, outputs_prefix="Absolute.FreezeRequestDetail", outputs_key_field='ID', + readable_output=human_readable, raw_response=res) + + +def list_device_freeze_message_command(args, client) -> CommandResults: + message_id = args.get('message_id') + if message_id: + res = client.api_request_absolute('GET', f'/v2/device-freeze/messages/{message_id}') + else: + res = client.api_request_absolute('GET', '/v2/device-freeze/messages', success_status_code=(200, 204)) + + if isinstance(res, list): + outputs = parse_device_freeze_message_response(res) + human_readable = tableToMarkdown(f'{INTEGRATION} Device freeze message details:', outputs, + headers=['ID', 'Name', 'CreatedUTC', 'ChangedUTC', 'ChangedBy', 'CreatedBy'], + removeNull=True) + return CommandResults(outputs=outputs, outputs_prefix="Absolute.FreezeMessage", outputs_key_field='ID', + readable_output=human_readable, raw_response=res) + else: + # in this case the response is empty, no content in response, no messages found + return CommandResults(readable_output=f'{INTEGRATION}: your account has no existing Freeze messages.') + + +def create_device_freeze_message_command(args, client) -> CommandResults: + html_message = args.get('html_message') + message_name = args.get('message_name') + + payload = {"name": message_name, "content": html_message} + + res = client.api_request_absolute('POST', '/v2/device-freeze/messages', body=json.dumps(payload), + success_status_code=(200, 201)) + human_readable = f"{INTEGRATION} New freeze message was created with ID: {res.get('id')}" + return CommandResults(outputs={'ID': res.get('id')}, outputs_prefix="Absolute.FreezeMessage", + outputs_key_field='ID', + readable_output=human_readable, raw_response=res) + + +def update_device_freeze_message_command(args, client) -> CommandResults: + message_id = args.get('message_id') + html_message = args.get('html_message') + message_name = args.get('message_name') + payload = {"name": message_name, "content": html_message} + client.api_request_absolute('PUT', f'/v2/device-freeze/messages/{message_id}', body=json.dumps(payload)) + return CommandResults(readable_output=f'{INTEGRATION} Freeze message: {message_id} was updated successfully') + + +def delete_device_freeze_message_command(args, client) -> CommandResults: + message_id = args.get('message_id') + client.api_request_absolute('DELETE', f'/v2/device-freeze/messages/{message_id}', success_status_code=[204]) + return CommandResults(readable_output=f'{INTEGRATION} Freeze message: {message_id} was deleted successfully') + + +def parse_device_unenroll_response(response): + parsed_data = [] + for device in response: + parsed_data.append({ + 'DeviceUid': device.get('deviceUid'), + 'SystemName': device.get('systemName'), + 'Username': device.get('username'), + 'EligibleStatus': device.get('eligibleStatus'), + 'Serial': device.get('serial'), + 'ESN': device.get('esn'), + }) + return parsed_data + + +def device_unenroll_command(args, client) -> CommandResults: + device_ids = argToList(args.get('device_ids')) + payload = [{'deviceUid': device_id} for device_id in device_ids] + res = client.api_request_absolute('POST', '/v2/device-unenrollment/unenroll', body=json.dumps(payload)) + outputs = parse_device_unenroll_response(res) + human_readable = tableToMarkdown(f'{INTEGRATION} unenroll devices:', outputs, removeNull=True) + return CommandResults(outputs_prefix='Absolute.DeviceUnenroll', + outputs=outputs, + readable_output=human_readable, + raw_response=res) + + +def add_list_to_filter_string(field_name, list_of_values, query): + if not list_of_values: + return query + + query_list = [] + list_of_values.sort() + query_list.extend([f"substringof('{value}',{field_name})" for value in list_of_values]) + new_query = " or ".join(query_list) + + if query: + return f'{query} or {new_query}' + return new_query + + +def add_value_to_filter_string(field_name, value, query): + if not value: + return query + if query: + # if there is already a query, we should add 'or' before appending the new query + return f"{query} or {field_name} eq '{value}'" + + return f"{field_name} eq '{value}'" + + +def create_filter_query_from_args_helper(args, arg_name, source_name, query): + list_no_duplicates = remove_duplicates_from_list_arg(args, arg_name) + query = add_list_to_filter_string(source_name, list_no_duplicates, query) + return query + + +def create_filter_query_from_args(args: dict, change_device_name_to_system=False): + custom_filter = args.get('filter') + if custom_filter: + return f"$filter={custom_filter}" + query = "" + + query = create_filter_query_from_args_helper(args, 'account_uids', "accountUid", query) + query = create_filter_query_from_args_helper(args, 'device_ids', "deviceUid", query) + query = create_filter_query_from_args_helper(args, 'app_names', "appName", query) + query = create_filter_query_from_args_helper(args, 'app_publishers', "appPublisher", query) + query = create_filter_query_from_args_helper(args, 'user_names', "userName", query) + query = create_filter_query_from_args_helper(args, 'os', "osName", query) + query = create_filter_query_from_args_helper(args, 'esn', "esn", query) + query = create_filter_query_from_args_helper(args, 'local_ips', "localIp", query) + query = create_filter_query_from_args_helper(args, 'public_ips', "publicIp", query) + + device_names = remove_duplicates_from_list_arg(args, 'device_names') + if device_names and change_device_name_to_system: + query = add_list_to_filter_string("systemName", device_names, query) + else: + query = add_list_to_filter_string("deviceName", device_names, query) + + if args.get('agent_status'): + agent_status = ABSOLUTE_AGET_STATUS[args.get('agent_status')] # type: ignore + query = add_value_to_filter_string("agentStatus", agent_status, query) + + os_name = args.get('os_name') + query = add_value_to_filter_string("osName", os_name, query) + + os_version = args.get('os_version') + query = add_value_to_filter_string("osVersion", os_version, query) + + manufacturer = args.get('manufacturer') + query = add_value_to_filter_string("systemManufacturer", manufacturer, query) + + model = args.get('model') + query = add_value_to_filter_string("systemModel", model, query) + + return f"$filter={query}" + + +def parse_return_fields(return_fields: str, query: str): + """ + Returns values only for the fields that meet the specified criteria in the query. + All other fields are returned with a null value. + """ + if not return_fields: + return query + + if query: + return f"{query}&$select={return_fields}" + return f"$select={return_fields}" + + +def parse_paging(page: int, limit: int, query: str) -> str: + """ + Add pagination query format to the existing query + """ + if query: + return f'{query}&$skip={page}&$top={limit}' + return f"$skip={page}&$top={limit}" + + +def parse_device_list_response(response, keep_os_in_list=True): + parsed_response = [] + for device in response: + parsed_device = {} + for key, val in device.items(): + if val: + if key == 'os' and not keep_os_in_list: + parsed_device['osName'] = val.get('name') + elif key == 'espInfo': + parsed_device['encryptionStatus'] = val.get('encryptionStatus') + else: + parsed_device[key[0].upper() + key[1:]] = val + parsed_response.append(parsed_device) + + if len(parsed_response) == 1: + return parsed_response[0] + return parsed_response + + +def parse_geo_location_outputs(response): + parsed_response = [] + for device in response: + parsed_device = {} + geo_data = device.get('geoData', {}).get('location', {}) + parsed_device['Coordinates'] = geo_data.get('point', {}).get('coordinates') + parsed_device['LocationTechnology'] = geo_data.get('locationTechnology') + parsed_device['Accuracy'] = geo_data.get('accuracy') + parsed_device['LastUpdate'] = geo_data.get('lastUpdate') + parsed_device['City'] = geo_data.get('geoAddress', {}).get('city') + parsed_device['State'] = geo_data.get('geoAddress', {}).get('state') + parsed_device['CountryCode'] = geo_data.get('geoAddress', {}).get('countryCode') + parsed_device['Country'] = geo_data.get('geoAddress', {}).get('country') + parsed_device['ID'] = device.get('id') + + parsed_response.append(parsed_device) + + if len(parsed_response) == 1: + return parsed_response[0] + return parsed_response + + +def get_device_application_list_command(args, client) -> CommandResults: + page = arg_to_number(args.get('page', 0)) + limit = arg_to_number(args.get('limit', 50)) + + query_string = create_filter_query_from_args(args) + query_string = parse_return_fields(args.get('return_fields'), query_string) + query_string = parse_paging(page, limit, query_string) # type: ignore + + res = client.api_request_absolute('GET', '/v2/sw/deviceapplications', query_string=query_string) + if res: + outputs = parse_device_list_response(res) + human_readable = tableToMarkdown(f'{INTEGRATION} device applications list:', outputs, removeNull=True) + human_readable += f"Above results are with page number: {page} and with size: {limit}." + return CommandResults(outputs_prefix='Absolute.DeviceApplication', + outputs=outputs, + outputs_key_field='Appid', + readable_output=human_readable, + raw_response=res) + else: + return CommandResults(readable_output=f"No applications found in {INTEGRATION} for the given filters: {args}") + + +def device_list_command(args, client) -> CommandResults: + page = arg_to_number(args.get('page', 0)) + limit = arg_to_number(args.get('limit', 50)) + + query_string = create_filter_query_from_args(args, change_device_name_to_system=True) + query_string = parse_return_fields(",".join(DEVICE_LIST_RETURN_FIELDS), query_string) + query_string = parse_paging(page, limit, query_string) # type: ignore + + res = client.api_request_absolute('GET', '/v2/reporting/devices', query_string=query_string) + if res: + outputs = parse_device_list_response(copy.deepcopy(res), keep_os_in_list=False) + human_readable = tableToMarkdown(f'{INTEGRATION} devices list:', outputs, removeNull=True) + human_readable += f"Above results are with page number: {page} and with size: {limit}." + return CommandResults(outputs_prefix='Absolute.Device', + outputs=outputs, + outputs_key_field="Id", + readable_output=human_readable, + raw_response=res) + else: + return CommandResults(readable_output=f"No devices found in {INTEGRATION} for the given filters: {args}") + + +def get_device_command(args, client) -> CommandResults: + if not ('device_ids' in args or 'device_names' in args or 'local_ips' in args or 'public_ips' in args): + raise_demisto_exception( + "at least one of the commands args (device_ids, device_names, local_ips, public_ips must be provided.") + + query_string = create_filter_query_from_args(args, change_device_name_to_system=True) + custom_fields_to_return = remove_duplicates_from_list_arg(args, 'fields') + if custom_fields_to_return: + custom_fields_to_return.extend(DEVICE_GET_COMMAND_RETURN_FIELDS) + query_string = parse_return_fields(",".join(custom_fields_to_return), query_string) + else: + query_string = parse_return_fields(",".join(DEVICE_GET_COMMAND_RETURN_FIELDS), query_string) + + res = client.api_request_absolute('GET', '/v2/reporting/devices', query_string=query_string) + if res: + outputs = parse_device_list_response(copy.deepcopy(res)) + human_readable = tableToMarkdown(f'{INTEGRATION} devices list:', outputs, removeNull=True) + return CommandResults(outputs_prefix='Absolute.Device', + outputs=outputs, + outputs_key_field="Id", + readable_output=human_readable, + raw_response=res) + else: + return CommandResults(readable_output=f"No devices found in {INTEGRATION} for the given filters: {args}") + + +def get_device_location_command(args, client) -> CommandResults: + query_string = create_filter_query_from_args(args) + query_string = parse_return_fields(",".join(DEVICE_GET_LOCATION_COMMAND_RETURN_FIELDS), query_string) + + res = client.api_request_absolute('GET', '/v2/reporting/devices', query_string=query_string) + if res: + outputs = parse_geo_location_outputs(copy.deepcopy(res)) + human_readable = tableToMarkdown(f'{INTEGRATION} devices location:', outputs, removeNull=True) + return CommandResults(outputs_prefix='Absolute.LocationReport', + outputs=outputs, + readable_output=human_readable, + raw_response=res) + else: + return CommandResults( + readable_output=f"No device locations found in {INTEGRATION} for the given filters: {args}") + + +''' MAIN FUNCTION ''' + + +def main() -> None: # pragma: no cover + params = demisto.params() + try: + base_url = validate_absolute_api_url(params.get('url')) + token_id = params.get('credentials').get('identifier') + secret_key = params.get('credentials').get('password') + verify_certificate = not params.get('insecure', False) + proxy = params.get('proxy', False) + + demisto.debug(f'Command being called is {demisto.command()}') + host = base_url.split('https://')[-1] + x_abs_date = datetime.utcnow().strftime(DATE_FORMAT) + headers: Dict = {"host": host, "content-type": "application/json", "x-abs-date": x_abs_date} + + client = Client( + base_url=base_url, + verify=verify_certificate, + headers=headers, + proxy=proxy, + token_id=token_id, + secret_key=secret_key, + x_abs_date=x_abs_date, + ) + args = demisto.args() + if demisto.command() == 'test-module': + return_results(test_module(client)) + + elif demisto.command() == 'absolute-custom-device-field-list': + return_results(get_custom_device_field_list_command(args=args, client=client)) + + elif demisto.command() == 'absolute-custom-device-field-update': + return_results(update_custom_device_field_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-freeze-request': + return_results(device_freeze_request_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-remove-freeze-request': + return_results(remove_device_freeze_request_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-freeze-request-get': + return_results(get_device_freeze_request_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-freeze-message-list': + return_results(list_device_freeze_message_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-freeze-message-create': + return_results(create_device_freeze_message_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-freeze-message-update': + return_results(update_device_freeze_message_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-freeze-message-delete': + return_results(delete_device_freeze_message_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-unenroll': + return_results(device_unenroll_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-application-list': + return_results(get_device_application_list_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-list': + return_results(device_list_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-get': + return_results(get_device_command(args=args, client=client)) + + elif demisto.command() == 'absolute-device-location-get': + return_results(get_device_location_command(args=args, client=client)) + + else: + raise NotImplementedError(f'{demisto.command()} is not an existing {INTEGRATION} command.') + + except Exception as e: + demisto.error(traceback.format_exc()) # print the traceback + return_error(f'Failed to execute {demisto.command()} command.\nError:\n{str(e)}') + + +''' ENTRY POINT ''' + +if __name__ in ('__main__', '__builtin__', 'builtins'): # pragma: no cover + main() diff --git a/Packs/Absolute/Integrations/Absolute/Absolute.yml b/Packs/Absolute/Integrations/Absolute/Absolute.yml new file mode 100644 index 000000000000..1fe292280aa5 --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/Absolute.yml @@ -0,0 +1,928 @@ +category: Endpoint +commonfields: + id: Absolute + version: -1 +configuration: +- defaultvalue: https://cc.absolute.com + display: Your Absolute server URL + name: url + required: true + type: 0 +- name: credentials + display: Token ID + required: true + defaultvalue: + type: 9 + additionalinfo: Token ID and Secret Key. + displaypassword: "Secret Key" + hiddenusername: false +- display: Trust any certificate (not secure) + name: insecure + required: false + type: 8 +- display: Use system proxy settings + name: proxy + required: false + type: 8 +description: "Absolute is an adaptive endpoint security solution that delivers device security, data security, and asset management of endpoints." +display: Absolute +name: Absolute +script: + commands: + - arguments: + - default: false + description: The system unique identifier of the device. + isArray: false + name: device_id + required: true + secret: false + deprecated: false + description: Returns a list of custom device fields associated with the given device_id, based on the authorization token. + execution: false + name: absolute-custom-device-field-list + outputs: + - contextPath: Absolute.CustomDeviceField.DeviceUID + description: The system-defined unique identifier of the device. + type: String + - contextPath: Absolute.CustomDeviceField.ESN + description: The unique ESN (identifier) assigned to the Absolute agent that is installed on a device. + type: String + - contextPath: Absolute.CustomDeviceField.CDFValues.CDFUID + description: The unique identifier of the custom device field. + type: String + - contextPath: Absolute.CustomDeviceField.CDFValues.FieldKey + description: The unique identifier of the custom device field in the classic version of Absolute. + type: String + - contextPath: Absolute.CustomDeviceField.CDFValues.FieldName + description: The name assigned to the custom device field. + type: String + - contextPath: Absolute.CustomDeviceField.CDFValues.CategoryCode + description: 'The type of custom device field. Possible values are: PREDEFINED, ESNCOLUMN, UDF.' + type: String + - contextPath: Absolute.CustomDeviceField.CDFValues.FieldValue + description: The current value of the custom device field. + type: String + - contextPath: Absolute.CustomDeviceField.CDFValues.Type + description: 'The data type of the field value. Possible values are: Text, Date, Dropdown.' + type: String + - arguments: + - default: false + description: The system unique identifier of the device. + isArray: false + name: device_id + required: true + secret: false + - default: false + description: 'The unique identifier of the custom device field. Note: In order to get this value, use the "absolute-custom-device-field-list" command.' + isArray: false + name: cdf_uid + required: true + secret: false + - default: false + description: The new value of the custom device field to be set. + isArray: false + name: value + required: true + secret: false + deprecated: false + description: Updates the value of the included custom device fields for the given device_id. + execution: false + name: absolute-custom-device-field-update + - arguments: + - default: false + description: A comma-separated list of the unique identifiers of devices included in the request. The recommendation is using up to 10,000 devices per request. + isArray: true + name: device_ids + required: true + secret: false + - default: false + description: The user-defined name for the Freeze request. The name should be a non-unique string and has 1-250 characters. + isArray: false + name: request_name + required: true + secret: false + - default: false + description: The user-defined HTML coded message shown on devices when the Freeze is applied. The message should be in a non-unique HTML format and has 1-4000 characters. + isArray: false + name: html_message + required: true + secret: false + - default: false + description: The user-defined name for the Freeze message. + isArray: false + name: message_name + required: true + secret: false + - auto: PREDEFINED + default: false + description: 'The type of Freeze. You cannot freeze a device that has been reported stolen in the Absolute console. + - OnDemand: Freezes a device on its next connection to the Absolute Monitoring Center, which is typically within 15 minutes. This applies for all supported operating systems. + - Scheduled: Freezes a device on its next connection to the Absolute Monitoring Center on or after a specified date and time. This applies to Windows and Mac devices. The scheduled freeze date is specified in the scheduled_freeze_date argument. Scheduled Freeze requests are only supported on Windows and Mac devices with an active Absolute agent that is regularly connecting to the Absolute Monitoring Center. + - Offline: Freezes a device if it has been offline for a specified period of time. Applies to Windows and Mac devices. Offline period is specified in the offline_time_seconds argument. Offline freeze is not available if your Absolute account has been migrated to Offline Freeze Rules. For more information, see the console Help.' + isArray: false + name: device_freeze_type + predefined: + - 'OnDemand' + - 'Scheduled' + - 'Offline' + required: true + secret: false + - default: false + description: 'The date and time (in UTC) when the device should be frozen in ISO 8601 format: YYYY-MM-DDThh:mm:ss.SSSZ. Required if device_freeze_type is Scheduled. For example, 2022-01-01T00:00:00.000Z.' + isArray: false + name: scheduled_freeze_date + required: false + secret: false + - default: false + description: 'The length of time (in seconds) that a device can be offline before the device is frozen. Required if device_freeze_type is Offline. Must be between 1200 seconds (20 minutes) and 172800000 seconds (2000 days). Default value is 30 days.' + isArray: false + defaultValue: 22592000 + name: offline_time_seconds + required: false + secret: false + - auto: PREDEFINED + default: false + description: 'The type of passcode to unfreeze a device. + - UserDefined: Manually set the passcode in passcode. You must specify the passcode argument. + - RandomForEach: A unique passcode is randomly generated for each device. You must specify the passcode_length argument. + - RandomForAll: A passcode is randomly generated and is the same for all devices. You must specify the passcode_length argument.' + isArray: false + name: passcode_type + predefined: + - 'UserDefined' + - 'RandomForEach' + - 'RandomForAll' + required: true + secret: false + - default: false + description: 'The passcode used to unfreeze the devices. Required if passcode_type is UserDefined. A valid passcode is a number that has 4-8 characters. For example, 12345678.' + isArray: false + name: passcode + required: false + secret: false + - default: false + description: 'The length of the passcode when it is randomly generated. Required if passcode_type is RandomForEach or RandomForAll. A valid passcode is a number from 4 - 8. For example, 8.' + isArray: false + name: passcode_length + required: false + secret: false + - default: false + description: 'A comma-separated list of user-entered email addresses that will receive an email notification when the status of the Freeze request changes. The API supports up to 10 email addresses.' + isArray: true + name: notification_emails + required: false + secret: false + deprecated: false + description: Creates a new Freeze request for the devices specified in the device_ids argument. + execution: false + name: absolute-device-freeze-request + outputs: + - contextPath: Absolute.FreezeRequest.RequestUID + description: The system-defined, unique identifier of the Freeze request. + type: String + - contextPath: Absolute.FreezeRequest.SucceededDeviceUIDs + description: An array of the unique devices identifiers that succeeded in creating a Freeze request. + type: Unknown + - contextPath: Absolute.FreezeRequest.Errors.detail.deviceUids + description: An array of the unique identifiers of devices for the Freeze request error. + type: Unknown + - contextPath: Absolute.FreezeRequest.Errors.message + description: The reason for the Freeze failure. + type: String + - contextPath: Absolute.FreezeRequest.Errors.messageKey + description: The reference key for the error message. + type: String + - arguments: + - default: false + description: A comma-separated list of the unique identifiers of devices included in the request. The recommendation is to use up to 10,000 devices per request. + isArray: true + name: device_ids + required: true + secret: false + - auto: PREDEFINED + default: false + description: 'Whether to remove only a Scheduled Freeze request. Note: When setting to true, if the Freeze request is a Scheduled Freeze request, the Freeze request is removed. Otherwise, when setting to false, if the Freeze request is not a Scheduled Freeze request, the Freeze request is not removed.' + isArray: false + name: remove_scheduled + predefined: + - 'true' + - 'false' + required: false + secret: false + - auto: PREDEFINED + default: false + description: 'Whether to remove only an Offline Freeze request. Note: When setting to true, if the Freeze request is an Offline Freeze request, the Freeze request is removed. Otherwise, when setting to false, if the Freeze request is not a Offline Freeze request, the Freeze request is not removed.' + isArray: false + name: remove_offline + predefined: + - 'true' + - 'false' + required: false + secret: false + deprecated: false + description: 'Creates a new Remove Freeze request for one or more devices, regardless of their Freeze status. You can submit Remove Freeze requests to perform the following actions: unfreeze frozen devices, remove newly submitted Freeze requests, or remove outstanding Scheduled and Offline Freeze requests.' + execution: false + name: absolute-device-remove-freeze-request + - arguments: + - default: false + description: The system-defined, unique identifier of the Freeze request. + isArray: false + name: request_uid + required: true + secret: false + deprecated: false + description: Gets detailed information about the Freeze request specified by request_uid. + execution: false + name: absolute-device-freeze-request-get + outputs: + - contextPath: Absolute.FreezeRequestDetail.ID + description: The system-defined, unique identifier of the Freeze request. + type: String + - contextPath: Absolute.FreezeRequestDetail.AccountUid + description: The system-defined, unique identifier associated with this Absolute account. + type: String + - contextPath: Absolute.FreezeRequestDetail.ActionRequestUid + description: The system-defined, unique identifier of the Freeze request (the same as ID). + type: String + - contextPath: Absolute.FreezeRequestDetail.DeviceUid + description: The system-defined, unique identifier of the device. + type: String + - contextPath: Absolute.FreezeRequestDetail.Statuses.actionUid + description: The system-defined, unique identifier of the Freeze action. + type: String + - contextPath: Absolute.FreezeRequestDetail.Statuses.statusUid + description: The system-defined, unique identifier of the Freeze status. + type: String + - contextPath: Absolute.FreezeRequestDetail.Statuses.messageKey + description: The reference key for the error message or the info message. Error messages start with 'dds'. Info messages start with 'ddsui'. + type: String + - contextPath: Absolute.FreezeRequestDetail.Statuses.messageParams + description: A list of strings describing the error message when the status is LaunchFailed. If the status isn't LaunchFailed, messageParams is empty. + type: Unknown + - contextPath: Absolute.FreezeRequestDetail.Statuses.message + description: The message for the status change that occurred. + type: String + - contextPath: Absolute.FreezeRequestDetail.Statuses.updatedBy + description: The last entity to update the Freeze request. + type: String + - contextPath: Absolute.FreezeRequestDetail.Statuses.updatedUtc + description: The time (in Unix epoch) when the Freeze request was last updated. + type: Date + - contextPath: Absolute.FreezeRequestDetail.Statuses.triggerActionUid + description: The system-defined, unique identifier of a new Freeze request that replaces another Freeze request of the same type. + type: String + - contextPath: Absolute.FreezeRequestDetail.Statuses.eventType + description: Device freeze type event. + type: String + - contextPath: Absolute.FreezeRequestDetail.Statuses.ackClientTS + description: The acknowledgment timestamp (in UNIX epoch local time) when the request was downloaded on the device. + type: Number + - contextPath: Absolute.FreezeRequestDetail.Statuses.ackClientUtc + description: The acknowledgment timestamp (in UNIX epoch UTC) when the request was downloaded to the device. + type: Number + - contextPath: Absolute.FreezeRequestDetail.Statuses.instruction + description: All action instructions which are sent from the device DFZ agent component. + type: String + - contextPath: Absolute.FreezeRequestDetail.Statuses.scheduledFreezeDateUTC + description: The date and time (in Unix epoch) when a Scheduled Freeze request was scheduled to be performed. + type: Number + - contextPath: Absolute.FreezeRequestDetail.Configuration.messageName + description: The user-defined name for the Freeze message. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.htmlClear + description: The user-defined, HTML coded message shown on the device when the Freeze is applied (the same as Configuration.freezeMessage except it contains the HTML tags). + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.passcodeClear + description: The passcode that can be used to unfreeze the device. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.passcodeOption + description: The type of passcode to unfreeze a device. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.freezeMessage + description: The content of the Freeze message without the HTML tags. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.freezeId + description: The user-friendly identifier of the request that is displayed in the event history in the Absolute console (same as EventHistoryId). + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.configurationUid + description: The system-defined unique identifier assigned to the Freeze configuration. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.action + description: The type of action being performed on the device. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.type + description: The type of Freeze. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.passcodeLength + description: The length of the device unfreeze passcode when it is randomly generated. + type: Number + - contextPath: Absolute.FreezeRequestDetail.Configuration.passcodeSalt + description: The salt used for hashing the passcode before the passcode is sent to the device. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.passcodeHashed + description: The hashed value of the passcode. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.html + description: The encoded value of Configuration.htmlClear. + type: String + - contextPath: Absolute.FreezeRequestDetail.Configuration.disableRemoteLogin + description: Whether remote login is disabled on the device. + type: Boolean + - contextPath: Absolute.FreezeRequestDetail.Configuration.disableFileSharing + description: Whether file sharing is disabled on the device. + type: Boolean + - contextPath: Absolute.FreezeRequestDetail.Configuration.Conditions.secondsUntilFreeze + description: The amount of time (in seconds) a device can be offline before the device is frozen. + type: Number + - contextPath: Absolute.FreezeRequestDetail.Configuration.Conditions.scheduledFreezeDate + description: The date and time (in UTC) when a Scheduled Freeze request is scheduled to be performed. + type: Date + - contextPath: Absolute.FreezeRequestDetail.Configuration.issuedUtc + description: The date and time (in UNIX epoch) when the Freeze request was created. + type: Date + - contextPath: Absolute.FreezeRequestDetail.Configuration.preLoginEnabled + description: Whether pre-login is enabled on the device. + type: Boolean + - contextPath: Absolute.FreezeRequestDetail.Configuration.serviceControlList + description: List of service controls that the server sends to the device. + type: String + - contextPath: Absolute.FreezeRequestDetail.Name + description: The user-defined name for the Freeze request. + type: String + - contextPath: Absolute.FreezeRequestDetail.Requester + description: The user ID of the entity that created the Freeze request. + type: String + - contextPath: Absolute.FreezeRequestDetail.RequesterUid + description: The system-defined unique identifier of the user who created the Freeze request. + type: String + - contextPath: Absolute.FreezeRequestDetail.CreatedUTC + description: The date and time (in UNIX epoch) when the Freeze request was created. + type: Date + - contextPath: Absolute.FreezeRequestDetail.ChangedUTC + description: The date and time (in UNIX epoch) when the Freeze request was last modified. + type: Date + - contextPath: Absolute.FreezeRequestDetail.NotificationEmails + description: An array of user-entered email addresses that will receive an email notification when the status of the Freeze request changes. Supports up to 10 email addresses. + type: Unknown + - contextPath: Absolute.FreezeRequestDetail.EventHistoryId + description: The user-friendly identifier of the request that is displayed in the event history in the Absolute console (same as freezeId). + type: String + - contextPath: Absolute.FreezeRequestDetail.PolicyGroupUid + description: The system-defined unique identifier of the policy group that the device belongs to. + type: String + - contextPath: Absolute.FreezeRequestDetail.PolicyConfigurationVersion + description: The version of the configuration for the policy. + type: Number + - contextPath: Absolute.FreezeRequestDetail.FreezePolicyUid + description: The unique identifier of the Freeze policy. + type: String + - contextPath: Absolute.FreezeRequestDetail.Downloaded + description: Whether the Freeze request has been downloaded to the device. + type: Boolean + - contextPath: Absolute.FreezeRequestDetail.IsCurrent + description: Internal flag. + type: Boolean + - arguments: + - default: false + description: The system-defined, unique identifier of the Freeze message. + isArray: false + name: message_id + required: false + secret: false + deprecated: false + description: Gets all the Freeze messages that are configured for the account by the given message_id. If message_id is not given all the messages will be returned. + execution: false + name: absolute-device-freeze-message-list + outputs: + - contextPath: Absolute.FreezeMessage.ID + description: The system-defined, unique identifier of the Freeze message. + type: String + - contextPath: Absolute.FreezeMessage.Name + description: The user-defined name for the Freeze message. + type: String + - contextPath: Absolute.FreezeMessage.Content + description: The user-defined, HTML coded message that shows on a device when a Freeze is applied. + type: String + - contextPath: Absolute.FreezeMessage.CreatedBy + description: The username of the entity that created the Freeze message. + type: String + - contextPath: Absolute.FreezeMessage.ChangedBy + description: The username of the entity that last updated the Freeze message. + type: String + - contextPath: Absolute.FreezeMessage.CreatedUTC + description: The date and time when the Freeze message was created. + type: String + - contextPath: Absolute.FreezeMessage.ChangedUTC + description: The date and time when the Freeze message was last modified. + type: String + - arguments: + - default: false + description: The user-defined, HTML coded message that shows on a device when a Device Freeze is applied. Should be in HTML format with 1-4000 characters. + isArray: false + name: html_message + required: true + secret: false + - default: false + description: The user-defined name for the Device Freeze message. The name should be a string with 1-255 characters. + isArray: false + name: message_name + required: true + secret: false + deprecated: false + description: Creates a new Freeze message for the account. + execution: false + name: absolute-device-freeze-message-create + outputs: + - contextPath: Absolute.FreezeMessage.ID + description: The system-defined, unique identifier of the Freeze message. + type: String + - arguments: + - default: false + description: The user-defined, HTML coded message that shows on a device when a Device Freeze is applied. Should be in HTML format with 1-4000 characters. + isArray: false + name: html_message + required: true + secret: false + - default: false + description: The user-defined name for the Device Freeze message. The name should be a string with 1-255 characters. + isArray: false + name: message_name + required: true + secret: false + - default: false + description: The system-defined, unique identifier of the Freeze message. + isArray: false + name: message_id + required: true + secret: false + deprecated: false + description: Updates the content of an existing Freeze message. + execution: false + name: absolute-device-freeze-message-update + - arguments: + - default: false + description: The system-defined, unique identifier of the Freeze message. + isArray: false + name: message_id + required: true + secret: false + deprecated: false + description: Deletes an existing Freeze message for the account. + execution: false + name: absolute-device-freeze-message-delete + - arguments: + - default: false + description: A comma-separated list of device UIDs that should be unenrolled. + isArray: true + name: device_ids + required: true + secret: false + deprecated: false + description: Initiates an unenroll request on a list of eligible devices. + execution: false + name: absolute-device-unenroll + outputs: + - contextPath: Absolute.DeviceUnenroll.DeviceUid + description: The unique GUID identifier of the device. + type: String + - contextPath: Absolute.DeviceUnenroll.SystemName + description: The name assigned to the device. + type: String + - contextPath: Absolute.DeviceUnenroll.Username + description: The unique user name of the user who was logged into the device at the time of the agent call. + type: String + - contextPath: Absolute.DeviceUnenroll.EligibleStatus + description: 'The eligibility status of the device. Possible vales are: 0 for eligible, 1 for inactive or disabled, and 2 for stolen.' + type: Number + - contextPath: Absolute.DeviceUnenroll.Serial + description: The identification number that is assigned to the device by the device manufacturer. + type: String + - contextPath: Absolute.DeviceUnenroll.ESN + description: The unique Electronic SerialNumber (ESN) that is assigned to the agent installed on the device. + type: String + - arguments: + - default: false + description: The query by which to filter the device applications. If this argument is set, it overrides the others. For example, appName eq 'someName' or availableVirtualMemoryBytes lt 1073741824. + isArray: false + name: filter + required: false + secret: false + - default: false + description: A comma-separated list of all specific values to return. If not set, all possible values will be returned. + isArray: true + name: return_fields + required: false + secret: false + - default: false + description: A comma-separated list of the unique IDs associated with this Absolute account. + isArray: true + name: account_uids + required: false + secret: false + - default: false + description: A comma-separated list of the system-defined unique identifier of the devices. + isArray: true + name: device_ids + required: false + secret: false + - default: false + description: A comma-separated list of the devices names. + isArray: true + name: device_names + required: false + secret: false + - default: false + description: A comma-separated list of the application names. + isArray: true + name: app_names + required: false + secret: false + - default: false + description: A comma-separated list of the name of the software publishers of the application. + isArray: true + name: app_publishers + required: false + secret: false + - default: false + description: A comma-separated list of the user names of the users logged in to the device. + isArray: true + name: user_names + required: false + secret: false + - default: false + description: A comma-separated list of the operating systems that are installed on the device. + isArray: true + name: os + required: false + secret: false + - default: false + description: A comma-separated list of the system-defined unique Electronic Serial Numbers (ESN) assigned to the Absolute agent installed on the device. + isArray: true + name: esn + required: false + secret: false + - default: false + defaultValue: '50' + description: Maximum number of results to return. + isArray: false + name: limit + required: false + secret: false + - default: false + defaultValue: '0' + description: The page number of the results to retrieve. Minimum value is 0. + isArray: false + name: page + required: false + secret: false + deprecated: false + description: Gets a list of device records and the corresponding software application data for each device on the account that you have access to or that meets the given filter. + execution: false + name: absolute-device-application-list + outputs: + - contextPath: Absolute.DeviceApplication.DeviceAppId + description: The unique ID of the application. + type: String + - contextPath: Absolute.DeviceApplication.DeviceUid + description: The system-defined unique identifier of the device. + type: String + - contextPath: Absolute.DeviceApplication.AccountUid + description: The unique ID associated with this Absolute account. + type: String + - contextPath: Absolute.DeviceApplication.AppId + description: The identifier of the application. + type: String + - contextPath: Absolute.DeviceApplication.AppName + description: The name of the application. + type: String + - contextPath: Absolute.DeviceApplication.AppPublisher + description: The name of the software publisher of the application. + type: String + - contextPath: Absolute.DeviceApplication.AppOriginalPublisher + description: The original name of the software publisher of the application. + type: String + - contextPath: Absolute.DeviceApplication.AppVersion + description: The version of the application. + type: String + - contextPath: Absolute.DeviceApplication.Ens + description: The system-defined unique Electronic Serial Number (ESN) assigned to the Absolute agent installed on the device. + type: String + - contextPath: Absolute.DeviceApplication.DeviceName + description: The name of the device. + type: String + - contextPath: Absolute.DeviceApplication.DeviceSerialNumber + description: The identification number that is assigned to the device by the device manufacturer. + type: String + - contextPath: Absolute.DeviceApplication.UserName + description: Includes the device name and the username of the user logged in to the device at the time of the agent call. + type: String + - contextPath: Absolute.DeviceApplication.InstallPath + description: The location where the application is installed. + type: String + - contextPath: Absolute.DeviceApplication.InstallDate + description: The date (in UNIX epoch time) when the application was installed. + type: Date + - contextPath: Absolute.DeviceApplication.FirstDetectUtc + description: The date and time (in Unix epoch time) when the indicated version of the application was first detected on the device. + type: Date + - contextPath: Absolute.DeviceApplication.OsName + description: The operating system that is installed on the device. + type: String + - contextPath: Absolute.DeviceApplication.LastScanTimeUtc + description: The date and time (in Unix epoch time) of the most recent installed software (SNG) scan. + type: Date + - arguments: + - default: false + description: The query by which to filter all the devices managed by the account. If this argument is set, it overrides the others. For example, agentStatus eq 'A' or lastConnectedUtc lt datetime'2021-01-01T00:00:00Z'. + isArray: false + name: filter + required: false + secret: false + - auto: PREDEFINED + default: false + description: The status of the Absolute agent on the device. + isArray: false + name: agent_status + predefined: + - 'Active' + - 'Disabled' + - 'Inactive' + required: false + secret: false + - default: false + description: Short description of the operating system expressed as a one-line string that includes the version of the operating system. + isArray: false + name: os_name + required: false + secret: false + - default: false + description: The version of the operating system. + isArray: false + name: os_version + required: false + secret: false + - default: false + description: The manufacturer of the device. + isArray: false + name: manufacturer + required: false + secret: false + - default: false + description: The product name from the manufacturer. + isArray: false + name: model + required: false + secret: false + - default: false + description: A comma-separated list of the usernames of the users who were logged in to the device at the time of the most recent agent call. If no user was logged in during the last agent call, the last detected username is used. + isArray: true + name: user_names + required: false + secret: false + - default: false + defaultValue: '50' + description: Maximum number of results to return. + isArray: false + name: limit + required: false + secret: false + - default: false + defaultValue: '0' + description: The page number of the results to retrieve. Minimum value is 0. + isArray: false + name: page + required: false + secret: false + deprecated: false + description: Gets a list of device records and their corresponding data that meets the required filter for all devices in your account, based on your authorization token. + execution: false + name: absolute-device-list + outputs: + - contextPath: Absolute.Device.Id + description: The unique identifier assigned to the device. + type: String + - contextPath: Absolute.Device.Esn + description: The unique ESN (Absolute Identifier) assigned to the agent installed on the device. + type: String + - contextPath: Absolute.Device.LastConnectedUtc + description: The date and time (in Unix epoch) when the device last connected to the Absolute Monitoring Center. + type: Number + - contextPath: Absolute.Device.SystemName + description: The name assigned to the device. + type: String + - contextPath: Absolute.Device.FullSystemName + description: The full name assigned to the device consisting of the system name and the domain name. + type: String + - contextPath: Absolute.Device.AgentStatus + description: The status of the Absolute agent on the device. + type: String + - contextPath: Absolute.Device.osName + description: Short description of the operating system expressed as a one-line string that includes the version of the operating system. + type: String + - contextPath: Absolute.Device.SystemManufacturer + description: The manufacturer of the device. + type: String + - contextPath: Absolute.Device.SystemModel + description: The product name from the manufacturer. + type: String + - contextPath: Absolute.Device.SystemType + description: The system running on the Windows-based computer. + type: String + - contextPath: Absolute.Device.Serial + description: The manufacturer-defined unique identifier assigned to the device. May correspond to the serial number of the BIOS, the motherboard, or the chassis, depending on the manufacturer. + type: String + - contextPath: Absolute.Device.LocalIp + description: Last known local IP address of this device. + type: String + - contextPath: Absolute.Device.PublicIp + description: Last known public IP address of this device. + type: String + - contextPath: Absolute.Device.EncryptionStatus + description: The summarized encryption status of the device. + type: String + - arguments: + - default: false + description: A comma-separated list of all specific values to return. + isArray: true + name: fields + required: false + secret: false + - default: false + description: A comma-separated list of the system-defined unique identifier of the devices. + isArray: true + name: device_ids + required: false + secret: false + - default: false + description: A comma-separated list of the devices names. + isArray: true + name: device_names + required: false + secret: false + - default: false + description: A comma-separated list of the last known local IP addresses of a device. + isArray: true + name: local_ips + required: false + secret: false + - default: false + description: A comma-separated list of the last known public IP addresses of a device. + isArray: true + name: public_ips + required: false + secret: false + deprecated: false + description: Gets a list of device records and their corresponding data that meets the required fields for all devices in your account. + execution: false + name: absolute-device-get + outputs: + - contextPath: Absolute.Device.Id + description: The unique identifier assigned to the device. + type: String + - contextPath: Absolute.Device.Esn + description: The unique ESN (Absolute Identifier) assigned to the agent installed on the device. + type: String + - contextPath: Absolute.Device.Domain + description: The name of the Windows domain to which this device belongs. + type: String + - contextPath: Absolute.Device.LastConnectedUtc + description: The date and time (in Unix epoch) when the device last connected to the Absolute Monitoring Center. + type: Number + - contextPath: Absolute.Device.SystemName + description: The name assigned to the device. + type: String + - contextPath: Absolute.Device.FullSystemName + description: The full name assigned to the device consisting of the system name and the domain name. + type: String + - contextPath: Absolute.Device.AgentStatus + description: The status of the Absolute agent on the device. + type: String + - contextPath: Absolute.Device.Os.name + description: Short description of the operating system expressed as a one-line string that includes the version of the operating system. + type: String + - contextPath: Absolute.Device.Os.version + description: The version of the operating system. + type: String + - contextPath: Absolute.Device.Os.currentBuild + description: The current build number of the operating system. + type: String + - contextPath: Absolute.Device.Os.architecture + description: The architecture of the operating system. + type: String + - contextPath: Absolute.Device.Os.installDate + description: The date and time (in Unix epoch) when the operating system was installed. + type: Number + - contextPath: Absolute.Device.Os.productKey + description: The product key of the operating system. + type: String + - contextPath: Absolute.Device.Os.serialNumber + description: The serial identification number of the operating system. + type: String + - contextPath: Absolute.Device.Os.lastBootTime + description: The date and time (in Unix epoch) when the operating system was last restarted. + type: Number + - contextPath: Absolute.Device.Bios.id + description: The unique identifier of this BIOS given by the manufacturer. + type: String + - contextPath: Absolute.Device.Bios.serialNumber + description: The serial number assigned to the BIOS. + type: String + - contextPath: Absolute.Device.Bios.smBiosVersion + description: The major version number of the BIOS, as reported by SMBIOS. + type: String + - contextPath: Absolute.Device.Bios.version + description: The version of the BIOS, as reported by SMBIOS. + type: String + - contextPath: Absolute.Device.Bios.versionDate + description: A substring of the manufacturer of the BIOS + the version of the BIOS version, as reported by SMBIOS + the release date of the Window BIOS. + type: String + - contextPath: Absolute.Device.SystemManufacturer + description: The manufacturer of the device. + type: String + - contextPath: Absolute.Device.SystemModel + description: The product name from the manufacturer. + type: String + - contextPath: Absolute.Device.SystemType + description: The system running on the Windows-based computer. + type: String + - contextPath: Absolute.Device.Serial + description: The manufacturer-defined unique identifier assigned to the device. May correspond to the serial number of the BIOS, the motherboard, or the chassis, depending on the manufacturer. + type: String + - contextPath: Absolute.Device.LocalIp + description: Last known local IP address of this device. + type: String + - contextPath: Absolute.Device.PublicIp + description: Last known public IP address of this device. + type: String + - contextPath: Absolute.Device.EncryptionStatus + description: The summarized encryption status of the device. + type: String + - contextPath: Absolute.Device.Username + description: The unique username of the user that was logged in to the device at the time of the most recent agent call. + type: String + - contextPath: Absolute.Device.PolicyGroupUid + description: The unique identifier of the policy group that the device belongs to. + type: String + - contextPath: Absolute.Device.PolicyGroupName + description: The name of the policy group that the device belongs to. + type: String + - contextPath: Absolute.Device.IsStolen + description: Indicates whether this device was reported as stolen. + type: String + - contextPath: Absolute.Device.DeviceStatus.type + description: The status of the device. Possible values are STOLEN or MISSING. + type: String + - contextPath: Absolute.Device.DeviceStatus.reported + description: The data and time (in Unix epoch) when the device was reported missing or stolen. + type: Number + - contextPath: Absolute.Device.NetworkAdapters.networkSSID + description: The Service Set Identifier (SSID) of the connected Wi-Fi adapter. + type: String + - arguments: + - default: false + description: A comma-separated list of the system-defined unique identifier of the devices. + isArray: true + name: device_ids + required: true + secret: false + deprecated: false + description: Gets a list of devices geo location records and their corresponding data that meets the required devices IDs. + execution: false + name: absolute-device-location-get + outputs: + - contextPath: Absolute.LocationReport.Coordinates + description: A comma-separated list where the first number is the estimated latitude and the second number is the estimated longitude (in degrees) where the device is located. + type: Unknown + - contextPath: Absolute.LocationReport.ID + description: The system-defined unique identifier of the device. + type: String + - contextPath: Absolute.LocationReport.City + description: The city where the device is located. + type: String + - contextPath: Absolute.LocationReport.State + description: The state or province where the device is located. + type: String + - contextPath: Absolute.LocationReport.CountryCode + description: The country code for the country where the device is located. + type: String + - contextPath: Absolute.LocationReport.Country + description: The country where the device is located. + type: String + - contextPath: Absolute.LocationReport.LocationTechnology + description: The technology used to get the location. + type: String + - contextPath: Absolute.LocationReport.Accuracy + description: The estimated accuracy (in meters) of the technology used to locate the device. + type: Number + - contextPath: Absolute.LocationReport.LastUpdate + description: The date and time (in Unix epoch) when the device last changed its location. + type: Number + isfetch: false + runonce: false + script: '-' + type: python + subtype: python3 + dockerimage: demisto/python3:3.10.4.27798 +fromversion: 6.0.0 +tests: +- Absolute_TestPlaybook diff --git a/Packs/Absolute/Integrations/Absolute/Absolute_description.md b/Packs/Absolute/Integrations/Absolute/Absolute_description.md new file mode 100644 index 000000000000..e0c38d8c6f8d --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/Absolute_description.md @@ -0,0 +1,38 @@ +## Absolute + +To configure an instance of Absolute, you need to obtain the following information. + +* Server URL +* Token ID +* Secret Key + +## Get your Token ID and Secret Key + +### Token ID +* The token ID is a random GUIs string and is public information (like username). +* It is associated with the same role and device group as the Absolute user account. + +### Secret Key +The secret key is a random sequence of bits and is private and contains sensitive information. + +### Create a Token ID and Secret Key +1. In the Absolute console, click the **+** (in the quick access toolbar) > **API Token**. +2. On the **API Token Management** page, click the **Create token** button. The Create Token dialog box appears. +3. Enter a **Token name** and **Description**. +4. Click **Save** (The Token Created dialog box displays your generated token ID). +5. Download the token ID and secret key or view the secret key. +Note: If you close this dialog box before downloading or copying the secret key, you cannot retrieve it later. + +### Download the Token ID and Secret Key +1. Click **Download Token**. +2. Save the .token file. +3. Use a text editor to open and view the file. +4. To view the secret key: + 1. Click **View Secret Key**. The secret key is populated. + 2. Copy both values of the **Token ID** and **Secret key** to a text file and save the file. +5. Click **Close**. + +#### Notes: +1. On the **API Token Management** page, the new token is added to your list of tokens. +2. If a 401 error causes the API authentication to fail, you can enable authentication debugging from the Absolute console. +3. The secret key is comparable to a password. Keep it secure, and do not share it with anyone. diff --git a/Packs/Absolute/Integrations/Absolute/Absolute_image.png b/Packs/Absolute/Integrations/Absolute/Absolute_image.png new file mode 100644 index 0000000000000000000000000000000000000000..aa3c64f198b3305cdb0c45485c42de2ab3d6bd38 GIT binary patch literal 2040 zcmV}0g<_~i zyfCzgLJby)iU(Ri6a@si3e=XquK)Mu-`DAOcV9s;()?fYrEhlrnVp^goGFn)p-?Ck z3WY+UP$(1%g+ifFC=?2XLZMJ76bgmn{{<(N!1$8Fkuh?w6Y=USr*`<{0ZaFCqa$+` zvzB=$b9cxT=({SU?|0^6=0fJ*0sZZn*E6qX_GY$`F&{JMF_$x43jVHc%wfzS%rlu; z%s*tz+sqG``+Vbam@iuG*O+rD7}J<}@_Q5W7GM7}%+uxf8s>e>YnVlp8rah*%rfTV zvi>mCF~^eG|MAQ}nQNJyn9orZ#+K%HoUmlzx(Ou%UBklJR`(d@0WylYJz|UtrEBV<3r_h9VYE8_B+KGJd-*RcEHfrb!pPcPN?7Y{9&X zjE5Ww;BD~mJFI6J%;%ZsMU2a2K0x&wkytVrPl4rjO7YGMnTwdGQ1d}CnW%#(1SKaF z6o|>C`RV(y=@I~A4lR1P|KbhOeJQh-C5})unE4JxV<(xgzJrWGOkie9-#yGnm~mz< zv%fX&C+R~dM5vxh#t4pK-o$)E+jm-#dqBZ4L{1 zB)7E0v7rw#-}k-Tk4olC%=OYno*W^+k0s-ETbOO-JpfD$d1#)rOA^Z?I!W4Ft@-a} z9%r=?Mn^F>OBvE;5F=*?NZcqCkVeOp>_~Ne0n>qu_sw95QRKwVqWl zp9&igsNi;$>#lIf>20*obL<2XrWqEPTcAPR{ZX1>fdMxIp$zm7UHUkP{)WuYjD zTZ={|c&@bJbr&=DkSXdAcA+Rl1B5cH4WYh+HRrd?-vZtRS%fkekXN9cK}QD=o%{vu zQi@P;qav%QyiW#i_e9rIzUzEmnZ3JAy8Dn(rU!(SSyp?n$Q&$UGOw2#p>TxOjg}0& z4NAmEqWVQHD`(zp&5>!z!-L(B_u)uk=iFA*Owq`Lvv;){$XnH2nzfGO%$=RL3V9V9 zY#$rGBvUkC4tP-ykwLNaDFtsX&YkcqZ*z~Q`doS~b0u@8v@s_ND&%Mw&S_*qJe1+( z&lV#8I+@&GMfJHmN7hywu#T?Ou!h(|M+dOZ71S_2RYVPF;K5^7^v&XO8AqPPCONKK zzO(JlV(CUfG}sbH(Sv-5^QL_{a2Yksg*G661DSIhh#b7j>i5ob*nAXR@aR{`RJl+J zLTR2n^ME4dEHcJpdps0;WxyJc`*C?WkUvzQ2EnOesKxuE1|%23 zp_wwPvhvwDE=qQ$$EJ(-l1${uIO9sZ&&+5lm9aW_lqSMnrWfvaV{8!~5(F z!KUN(XB`Ct=XAfZmdQJC-8od&4@1Rm)mJiSPpbbev{T&=G!?yMt$t%caXUX~K+=QT z?91lR=M3@Mtbv&ehAoJT%xE$j4q&t91|69H!vi2)$i|wsPT>bLBS_ z=_v+)A>vjG`4~4)o|544$iZIpz%dI7+2DIG6wrYhDi;yqWs0akWqqxE^lt1vA#-bF z=Xlf%eW>Ag;kK-p4i9j-gCetwk1fLnBoz>gJGYYA2(}JqeP()%wzs$FcpsvEDm> zkoj@ss0o-m6#?XYT=GvMbHnDB!M7kCAZLdCBPM9xR5ET8$0d-o=y6L53LM8xSb|&U zY?@J6@{M%C61`;Jg}ic7_3-N+v~&AmhF7ktwoJ z#baY@L*|CpqbS2!8VW~P$3H$`00^bq1IC~_&!=c0pRVw|2dM|1n Wi3YN=6DfZH0000This device has been frozen by ' + 'company.', + 'CreatedBy': 'example1@test.com', + 'CreatedUTC': '2020-11-26T22:29:17.687+00:00', + 'ID': '1', + 'Name': 'On-demand Freeze message'}] + + +def test_device_unenroll_command(mocker, absolute_client): + from Absolute import device_unenroll_command + response = util_load_json('test_data/unenroll_device_response.json') + mocker.patch.object(absolute_client, 'api_request_absolute', return_value=response) + outputs = device_unenroll_command(args={'device_ids': "1,2"}, client=absolute_client).outputs + assert outputs == [{'DeviceUid': '1', + 'ESN': '2BU2PJD28VAA1UYL0008', + 'EligibleStatus': 0, + 'Serial': 'CNF83051BN', + 'SystemName': 'user1', + 'Username': 'example@test.com'}, + {'DeviceUid': '2', + 'ESN': '2BU2PJ545L0008', + 'EligibleStatus': 1, + 'Serial': 'CNF43051BN', + 'SystemName': 'user2', + 'Username': 'example2@test.com'}] + + +def test_list_device_freeze_message_command_no_id(mocker, absolute_client): + """ + Given: + - All relevant arguments for the command that is executed + + When: + - list_device_freeze_message command is executed with no message id + + Then: + - The http request is called with the right arguments + """ + from Absolute import list_device_freeze_message_command + http_request = mocker.patch.object(absolute_client, '_http_request', return_value=[]) + list_device_freeze_message_command(client=absolute_client, args={}) + assert http_request.call_args.kwargs['method'] == 'GET' + assert http_request.call_args.kwargs['url_suffix'] == '/v2/device-freeze/messages' + + +def test_delete_device_freeze_message_command(mocker, absolute_client): + """ + Given: + - All relevant arguments for the command that is executed + + When: + - delete_device_freeze_message_command command is executed + + Then: + - The http request is called with the right arguments + """ + from Absolute import delete_device_freeze_message_command + message_id = '1' + http_request = mocker.patch.object(absolute_client, '_http_request', return_value=[]) + delete_device_freeze_message_command(client=absolute_client, args={'message_id': message_id}) + assert http_request.call_args.kwargs['method'] == 'DELETE' + assert http_request.call_args.kwargs['url_suffix'] == f'/v2/device-freeze/messages/{message_id}' + + +def test_update_device_freeze_message_command(mocker, absolute_client): + """ + Given: + - All relevant arguments for the command that is executed + + When: + - update_device_freeze_message_command command is executed + + Then: + - The http request is called with the right arguments + """ + from Absolute import update_device_freeze_message_command + message_id = '1' + http_request = mocker.patch.object(absolute_client, 'api_request_absolute', return_value=[]) + args = {'message_id': message_id, 'html_message': 'text', 'message_name': 'name'} + update_device_freeze_message_command(client=absolute_client, args=args) + assert http_request.call_args.args == ('PUT', f'/v2/device-freeze/messages/{message_id}') + + +def test_create_device_freeze_message_command(mocker, absolute_client): + """ + Given: + - All relevant arguments for the command that is executed + + When: + - create_device_freeze_message_command command is executed + + Then: + - The http request is called with the right arguments + """ + from Absolute import create_device_freeze_message_command + http_request = mocker.patch.object(absolute_client, 'api_request_absolute', return_value={}) + args = {'html_message': 'text', 'message_name': 'name'} + create_device_freeze_message_command(client=absolute_client, args=args) + assert http_request.call_args.args == ('POST', '/v2/device-freeze/messages') + + +@pytest.mark.parametrize('field_name, list_of_values, query, expected_query', + [ + ("id", [], "query", "query"), + ("accountUid", ["1", "2"], "", + "substringof('1',accountUid) or substringof('2',accountUid)"), + ("accountUid", ["1", "2"], "deviceUID eq '1'", + "deviceUID eq '1' or substringof('1',accountUid) or substringof('2',accountUid)"), + ]) +def test_add_list_to_filter_string(field_name, list_of_values, query, expected_query): + from Absolute import add_list_to_filter_string + assert add_list_to_filter_string(field_name, list_of_values, query) == expected_query + + +@pytest.mark.parametrize('field_name, value, query, expected_query', + [ + ("id", "", "query", "query"), + ("accountUid", 1, "", "accountUid eq '1'"), + ("accountUid", 1, "deviceUID eq '1'", "deviceUID eq '1' or accountUid eq '1'"), + ]) +def test_add_value_to_filter_string(field_name, value, query, expected_query): + from Absolute import add_value_to_filter_string + assert add_value_to_filter_string(field_name, value, query) == expected_query + + +@pytest.mark.parametrize('args, change_device_name_to_system, expected_filter', + [ + ({'filter': "accountUid eq '1'"}, False, "$filter=accountUid eq '1'"), + ({'filter': "accountUid eq '1'", 'account_uids': '1'}, False, "$filter=accountUid eq '1'"), + ({'account_uids': '1,2'}, False, + "$filter=substringof('1',accountUid) or substringof('2',accountUid)"), + ({'account_uids': '1,2', 'device_names': "name1, name2"}, False, + "$filter=substringof('1',accountUid) or substringof('2',accountUid) or " + "substringof('name1',deviceName) or substringof('name2',deviceName)"), + ({'account_uids': '1,2', 'device_names': "name1, name2"}, True, + "$filter=substringof('1',accountUid) or substringof('2',accountUid) or " + "substringof('name1',systemName) or substringof('name2',systemName)"), + ({'agent_status': 'Active', 'device_names': "name1, name2"}, True, + "$filter=substringof('name1',systemName) or substringof('name2',systemName) " + "or agentStatus eq 'A'"), + ]) +def test_create_filter_query_from_args(args, change_device_name_to_system, expected_filter): + from Absolute import create_filter_query_from_args + assert create_filter_query_from_args(args, change_device_name_to_system) == expected_filter + + +@pytest.mark.parametrize('return_fields, query, expected_query', + [ + ("", "", ""), + ("", "$filter=accountUid eq '1'", "$filter=accountUid eq '1'"), + ("accountUid", "$filter=accountUid eq '1'", "$filter=accountUid eq" + " '1'&$select=accountUid"), + ("deviceUid", "$filter=accountUid eq '1'", "$filter=accountUid eq '1'&$select=deviceUid"), + ("deviceUid,accountUid", "$filter=accountUid eq '1'", + "$filter=accountUid eq '1'&$select=deviceUid,accountUid"), + ("deviceUid,accountUid", "", "$select=deviceUid,accountUid"), + ]) +def test_parse_return_fields(return_fields, query, expected_query): + from Absolute import parse_return_fields + assert parse_return_fields(return_fields, query) == expected_query + + +@pytest.mark.parametrize('page, limit, query, expected_query', + [ + (0, 50, "", "$skip=0&$top=50"), + (0, 50, "$filter=accountUid eq '1'&$select=deviceUid", + "$filter=accountUid eq '1'&$select=deviceUid&$skip=0&$top=50"), + ]) +def test_parse_paging(page, limit, query, expected_query): + from Absolute import parse_paging + assert parse_paging(page, limit, query) == expected_query + + +def test_get_device_location_command(mocker, absolute_client): + from Absolute import get_device_location_command + response = util_load_json('test_data/device_location_get.json') + mocker.patch.object(absolute_client, 'api_request_absolute', return_value=response) + outputs = get_device_location_command(args={'device_ids': "1,2"}, client=absolute_client).outputs + assert outputs == [{'Accuracy': 10, + 'City': 'TLV', + 'Coordinates': [-123.13202, 49.288162], + 'Country': 'Israel', + 'CountryCode': 'IL', + 'ID': '1', + 'LastUpdate': 1605747972853, + 'LocationTechnology': 'gps', + 'State': 'Israel'}, + {'Accuracy': 15, + 'City': 'Jerusalem', + 'Coordinates': [-124.1, 59.2], + 'Country': 'Israel', + 'CountryCode': 'IL', + 'ID': '2', + 'LastUpdate': 1605747972853, + 'LocationTechnology': 'gps', + 'State': 'Israel'}] diff --git a/Packs/Absolute/Integrations/Absolute/Pipfile b/Packs/Absolute/Integrations/Absolute/Pipfile new file mode 100644 index 000000000000..3523d3b6b93b --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/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/Absolute/Integrations/Absolute/Pipfile.lock b/Packs/Absolute/Integrations/Absolute/Pipfile.lock new file mode 100644 index 000000000000..6bdb9313414e --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/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/Absolute/Integrations/Absolute/README.md b/Packs/Absolute/Integrations/Absolute/README.md new file mode 100644 index 000000000000..9c91465df698 --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/README.md @@ -0,0 +1,977 @@ +Absolute is an adaptive endpoint security solution that delivers device security, data security, and asset management of endpoints. +This integration was integrated and tested with the API version 1.7 of Absolute. + +## Configure Absolute on Cortex XSOAR + +1. Navigate to **Settings** > **Integrations** > **Servers & Services**. +2. Search for Absolute. +3. Click **Add instance** to create and configure a new integration instance. + + | **Parameter** | **Description** | **Required** | + | --- | --- | --- | + | Your Absolute server URL | | True | + | Token ID | Token ID and Secret Key. | True | + | Secret Key | | 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. +### absolute-custom-device-field-list +*** +Returns a list of custom device fields associated with the given device_id, based on the authorization token. + + +#### Base Command + +`absolute-custom-device-field-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| device_id | The system unique identifier of the device. | Required | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.CustomDeviceField.DeviceUID | String | The system-defined unique identifier of the device. | +| Absolute.CustomDeviceField.ESN | String | The unique ESN \(identifier\) assigned to the Absolute agent that is installed on a device. | +| Absolute.CustomDeviceField.CDFValues.CDFUID | String | The unique identifier of the custom device field. | +| Absolute.CustomDeviceField.CDFValues.FieldKey | String | The unique identifier of the custom device field in the classic version of Absolute. | +| Absolute.CustomDeviceField.CDFValues.FieldName | String | The name assigned to the custom device field. | +| Absolute.CustomDeviceField.CDFValues.CategoryCode | String | The type of custom device field. Possible values are: PREDEFINED, ESNCOLUMN, UDF. | +| Absolute.CustomDeviceField.CDFValues.FieldValue | String | The current value of the custom device field. | +| Absolute.CustomDeviceField.CDFValues.Type | String | The data type of the field value. Possible values are: Text, Date, Dropdown. | + +#### Command example +```!absolute-custom-device-field-list device_id=1234``` +#### Context Example +```json +{ + "Absolute": { + "CustomDeviceField": { + "CDFValues": [ + { + "CDFUID": "4m9fUCZqTYec1bJgDSNg", + "CategoryCode": "ESNCOLUMN", + "FieldKey": 1, + "FieldName": "Asset Number", + "FieldValue": "aa", + "Type": "Text" + }, + { + "CDFUID": "2iS3ryiSvSDsksJ289vtQ", + "CategoryCode": "UDF", + "FieldKey": 30, + "FieldName": "Custom2", + "FieldValue": "TPB", + "Type": "Text" + } + ], + "DeviceUID": "1234", + "ESN": "D0004" + } + } +} +``` + +#### Human Readable Output + +>### Absolute Custom device field list +>|CDF ID|Field Value|Filed Name| +>|---|---|---| +>| 4m9fUCZqTYec1bJgDSNg | Asset Number | Asset Number | +>| 2iS3ryiSvSDsksJ289vtQ | Custom2 | Custom2 | + + +### absolute-custom-device-field-update +*** +Updates the value of the included custom device fields for the given device_id. + + +#### Base Command + +`absolute-custom-device-field-update` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| device_id | The system unique identifier of the device. | Required | +| cdf_uid | The unique identifier of the custom device field. Note: In order to get this value, use the "absolute-custom-device-field-list" command. | Required | +| value | The new value of the custom device field to be set. | Required | + + +#### Context Output + +There is no context output for this command. +#### Command example +```!absolute-custom-device-field-update device_id=1234 cdf_uid=4m9fUCZqTYec1bJgDSNg value="test2"``` +#### Human Readable Output + +>Device 1234 with value test2 was updated successfully. + +### absolute-device-freeze-request +*** +Creates a new Freeze request for the devices specified in the device_ids argument. + + +#### Base Command + +`absolute-device-freeze-request` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| device_ids | A comma-separated list of the unique identifiers of devices included in the request. The recommendation is to use up to 10,000 devices per request. | Required | +| request_name | The user-defined name for the Freeze request. The name should be a non-unique string and has 1-250 characters. | Required | +| html_message | The user-defined, HTML coded message shown on devices when the Freeze is applied. The message should be in a non-unique HTML format and has 1-4000 characters. | Required | +| message_name | The user-defined name for the Freeze message. | Required | +| device_freeze_type | The type of Freeze. You cannot freeze a device that has been reported Stolen in the Absolute console.
- OnDemand: Freezes a device on its next connection to the Absolute Monitoring Center, which is typically within 15 minutes. This applies for all supported operating systems.
- Scheduled: Freezes a device on its next connection to the Absolute Monitoring Center on or after a specified date and time. This applies to Windows and Mac devices. The scheduled freeze date is specified in the scheduled_freeze_date argument. Scheduled Freeze requests are only supported on Windows and Mac devices with an active Absolute agent that is regularly connecting to the Absolute Monitoring Center.
- Offline: Freezes a device if it has been offline for a specified period of time. Applies to Windows and Mac devices. Offline period is specified in the offline_time_seconds arguments. Offline freeze is not available if your Absolute account has been migrated to Offline Freeze Rules. For more information, see the console Help.
Possible values are: OnDemand, Scheduled, Offline. | Required | +| scheduled_freeze_date | The date and time (in UTC) when the device should be frozen in ISO 8601 format: YYYY-MM-DDThh:mm:ss.SSSZ. Required if device_freeze_type is Scheduled. For example, 2022-01-01T00:00:00.000Z. | Optional | +| offline_time_seconds | The length of time (in seconds) that a device can be offline before the device is frozen. Required if device_freeze_type is Offline. Must be between 1200 seconds (20 minutes) and 172800000 seconds (2000 days). Default value is 30 days. Default is 22592000. | Optional | +| passcode_type | The type of passcode to unfreeze a device.
- UserDefined: Manually set the passcode in passcode. You must specify the passcode argument.
- RandomForEach: A unique passcode is randomly generated for each device. You must specify the passcode_length argument.
- RandomForAll: A passcode is randomly generated and is the same for all devices. You must specify the passcode_length argument. Possible values are: UserDefined, RandomForEach, RandomForAll. | Required | +| passcode | The passcode used to unfreeze the devices. Required if passcode_type is UserDefined. A valid passcode is a number that has 4-8 characters. For example, 12345678. | Optional | +| passcode_length | The length of the passcode when it is randomly generated. Required if passcode_type is RandomForEach or RandomForAll. A valid passcode is a number from 4-8. For example, 8. | Optional | +| notification_emails | A comma-separated list of user-entered email addresses that will receive an email notification when the status of the Freeze request changes. The API supports up to 10 email addresses. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.FreezeRequest.RequestUID | String | The system-defined, unique identifier of the Freeze request. | +| Absolute.FreezeRequest.SucceededDeviceUIDs | Unknown | An array of the unique devices identifiers that succeeded in creating a Freeze request. | +| Absolute.FreezeRequest.Errors.detail.deviceUids | Unknown | An array of the unique identifiers of devices for the Freeze request error. | +| Absolute.FreezeRequest.Errors.message | String | The reason for the Freeze failure. | +| Absolute.FreezeRequest.Errors.messageKey | String | The reference key for the error message. | + +#### Command example +```!absolute-device-freeze-request device_ids=123456 device_freeze_type=Scheduled html_message="test" message_name="new name" request_name="name1" scheduled_freeze_date=2022-04-03T13:30:00.000Z passcode_type=RandomForEach passcode_length=5``` +#### Context Example +```json +{ + "Absolute": { + "FreezeRequest": { + "RequestUID": "2b62b290-d590-4237-8ba0-57e4779b9f1c", + "SucceededDeviceUIDs": [ + "123456" + ] + } + } +} +``` + +#### Human Readable Output + +>### Absolute device freeze requests results +>|RequestUID|SucceededDeviceUIDs| +>|---|---| +>| 2b62b290-d590-4237-8ba0-57e4779b9f1c | 123456 | + + +### absolute-device-remove-freeze-request +*** +Creates a new Remove Freeze request for one or more devices, regardless of their Freeze status. You can submit Remove Freeze requests to perform the following actions: unfreeze frozen devices, remove newly submitted Freeze requests, or remove outstanding Scheduled and Offline Freeze requests. + + +#### Base Command + +`absolute-device-remove-freeze-request` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| device_ids | A comma-separated list of the unique identifiers of devices included in the request. The recommendation is to use up to 10,000 devices per request. | Required | +| remove_scheduled | Whether to remove only a Scheduled Freeze request. Note: When setting to true, if the Freeze request is a Scheduled Freeze request, the Freeze request is removed. Otherwise, when setting to false, if the Freeze request is not a Scheduled Freeze request, the Freeze request is not removed. Possible values are: true, false. | Optional | +| remove_offline | Whether to remove only an Offline Freeze request. Note: When setting to true, if the Freeze request is an Offline Freeze request, the Freeze request is removed. Otherwise, when setting to false, if the Freeze request is not an Offline Freeze request, the Freeze request is not removed. Possible values are: true, false. | Optional | + + +#### Context Output + +There is no context output for this command. +#### Command example +```!absolute-device-remove-freeze-request device_ids=123456 remove_scheduled=true``` +#### Human Readable Output + +>Successfully removed freeze request for devices ids: 123456. + +### absolute-device-freeze-request-get +*** +Gets detailed information about the Freeze request specified by request_uid. + + +#### Base Command + +`absolute-device-freeze-request-get` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| request_uid | The system-defined, unique identifier of the Freeze request. | Required | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.FreezeRequestDetail.ID | String | The system-defined, unique identifier of the Freeze request. | +| Absolute.FreezeRequestDetail.AccountUid | String | The system-defined, unique identifier associated with this Absolute account. | +| Absolute.FreezeRequestDetail.ActionRequestUid | String | The system-defined, unique identifier of the Freeze request \(the same as ID\). | +| Absolute.FreezeRequestDetail.DeviceUid | String | The system-defined, unique identifier of the device. | +| Absolute.FreezeRequestDetail.Statuses.actionUid | String | The system-defined, unique identifier of the Freeze action. | +| Absolute.FreezeRequestDetail.Statuses.statusUid | String | The system-defined, unique identifier of the Freeze status. | +| Absolute.FreezeRequestDetail.Statuses.messageKey | String | The reference key for the error message or the info message. Error messages start with 'dds'. Info messages start with 'ddsui'. | +| Absolute.FreezeRequestDetail.Statuses.messageParams | Unknown | A list of strings describing the error message when the status is LaunchFailed. If the status isn't LaunchFailed, messageParams is empty. | +| Absolute.FreezeRequestDetail.Statuses.message | String | The message for the status change that occurred. | +| Absolute.FreezeRequestDetail.Statuses.updatedBy | String | The last entity to update the Freeze request. | +| Absolute.FreezeRequestDetail.Statuses.updatedUtc | Date | The time \(in Unix epoch\) when the Freeze request was last updated. | +| Absolute.FreezeRequestDetail.Statuses.triggerActionUid | String | The system-defined, unique identifier of a new Freeze request that replaces another Freeze request of the same type. | +| Absolute.FreezeRequestDetail.Statuses.eventType | String | Device freeze type event. | +| Absolute.FreezeRequestDetail.Statuses.ackClientTS | Number | The acknowledgment timestamp \(in Unix epoch local time\) when the request was downloaded on the device. | +| Absolute.FreezeRequestDetail.Statuses.ackClientUtc | Number | The acknowledgment timestamp \(in Unix epoch UTC\) when the request was downloaded to the device. | +| Absolute.FreezeRequestDetail.Statuses.instruction | String | All action instructions which are sent from the device DFZ agent component. | +| Absolute.FreezeRequestDetail.Statuses.scheduledFreezeDateUTC | Number | The date and time \(in Unix epoch\) when a Scheduled Freeze request was scheduled to be performed. | +| Absolute.FreezeRequestDetail.Configuration.messageName | String | The user-defined name for the Freeze message. | +| Absolute.FreezeRequestDetail.Configuration.htmlClear | String | The user-defined, HTML coded message shown on the device when the Freeze is applied \(the same as Configuration.freezeMessage except it contains the HTML tags\). | +| Absolute.FreezeRequestDetail.Configuration.passcodeClear | String | The passcode that can be used to unfreeze the device. | +| Absolute.FreezeRequestDetail.Configuration.passcodeOption | String | The type of passcode to unfreeze a device. | +| Absolute.FreezeRequestDetail.Configuration.freezeMessage | String | The content of the Freeze message without the HTML tags. | +| Absolute.FreezeRequestDetail.Configuration.freezeId | String | The user-friendly identifier of the request that is displayed in the event history in the Absolute console \(same as EventHistoryId\). | +| Absolute.FreezeRequestDetail.Configuration.configurationUid | String | The system-defined unique identifier assigned to the Freeze configuration. | +| Absolute.FreezeRequestDetail.Configuration.action | String | The type of action being performed on the device. | +| Absolute.FreezeRequestDetail.Configuration.type | String | The type of Freeze. | +| Absolute.FreezeRequestDetail.Configuration.passcodeLength | Number | The length of the device unfreeze passcode when it is randomly generated. | +| Absolute.FreezeRequestDetail.Configuration.passcodeSalt | String | The salt used for hashing the passcode before the passcode is sent to the device. | +| Absolute.FreezeRequestDetail.Configuration.passcodeHashed | String | The hashed value of the passcode. | +| Absolute.FreezeRequestDetail.Configuration.html | String | The encoded value of Configuration.htmlClear. | +| Absolute.FreezeRequestDetail.Configuration.disableRemoteLogin | Boolean | Whether remote login is disabled on the device. | +| Absolute.FreezeRequestDetail.Configuration.disableFileSharing | Boolean | Whether file sharing is disabled on the device. | +| Absolute.FreezeRequestDetail.Configuration.Conditions.secondsUntilFreeze | Number | The amount of time \(in seconds\) a device can be offline before the device is frozen. | +| Absolute.FreezeRequestDetail.Configuration.Conditions.scheduledFreezeDate | Date | The date and time \(in UTC\) that a Scheduled Freeze request is scheduled to be performed. | +| Absolute.FreezeRequestDetail.Configuration.issuedUtc | Date | The date and time \(in Unix epoch\) when the Freeze request was created. | +| Absolute.FreezeRequestDetail.Configuration.preLoginEnabled | Boolean | Whether pre-login is enabled on the device. | +| Absolute.FreezeRequestDetail.Configuration.serviceControlList | String | List of service controls that the server sends to the device. | +| Absolute.FreezeRequestDetail.Name | String | The user-defined name for the Freeze request. | +| Absolute.FreezeRequestDetail.Requester | String | The user ID of the entity that created the Freeze request. | +| Absolute.FreezeRequestDetail.RequesterUid | String | The system-defined unique identifier of the user who created the Freeze request. | +| Absolute.FreezeRequestDetail.CreatedUTC | Date | The date and time \(in Unix epoch\) when the Freeze request was created. | +| Absolute.FreezeRequestDetail.ChangedUTC | Date | The date and time \(in Unix epoch\) when the Freeze request was last modified. | +| Absolute.FreezeRequestDetail.NotificationEmails | Unknown | An array of user-entered email addresses that will receive an email notification when the status of the Freeze request changes. Supports up to 10 email addresses. | +| Absolute.FreezeRequestDetail.EventHistoryId | String | The user-friendly identifier of the request that is displayed in the event history in the Absolute console \(same as freezeId\). | +| Absolute.FreezeRequestDetail.PolicyGroupUid | String | The system-defined unique identifier of the policy group that the device belongs to. | +| Absolute.FreezeRequestDetail.PolicyConfigurationVersion | Number | The version of the configuration for the policy. | +| Absolute.FreezeRequestDetail.FreezePolicyUid | String | The unique identifier of the Freeze policy. | +| Absolute.FreezeRequestDetail.Downloaded | Boolean | Whether the Freeze request has been downloaded to the device. | +| Absolute.FreezeRequestDetail.IsCurrent | Boolean | Internal flag. | + +#### Command example +```!absolute-device-freeze-request-get request_uid=c638c2dc-1dd1-4cfa-8708-46f368012398``` +#### Context Example +```json +{ + "Absolute": { + "FreezeRequestDetail": { + "AccountUid": "accountID", + "ActionRequestUid": "c638c2dc-1dd1-4cfa-8708-46f368012398", + "ChangedBy": null, + "ChangedUTC": "2022-03-29T10:30:55.462+00:00", + "Configuration": { + "action": "DFZ", + "conditions": [ + { + "scheduledFreezeDate": "2022-03-29T10:30:22.000+00:00" + } + ], + "configurationUid": "c61b0cb7-3846-4d1e-9e78-641084b7747a", + "disableFileSharing": true, + "disableRemoteLogin": true, + "forceReboot": false, + "freezeId": "DeviceFreeze-0010", + "freezeMessage": "test", + "htmlClear": "

DeviceFreeze-0010


test", + "issuedUTC": "2022-03-29T10:30:24.268+00:00", + "messageName": "new name", + "passcodeClear": "26148", + "passcodeHashed": "c5pr+oaojn37SFZJ3uokRe0Uy/+kAhzPNv6TyrCzXOdL1vu/KyoFF7T6rQfLK6ej2jYWXPGRzxWCfrS9f/S8JA==", + "passcodeLength": 5, + "passcodeOption": "RandomForEach", + "passcodeSalt": "/4VA8uE3DUv04mWy9iGkZp5rL3zDwtEP/YsqAvL190VIn9bhPZUzYXozoSSEPro0tVSVMtG9Rfssqpy2yvsm6g==", + "preLoginEnabled": true, + "type": "Scheduled" + }, + "Content": null, + "CreatedBy": null, + "CreatedUTC": "2022-03-29T10:30:24.279+00:00", + "DeviceUid": "123456", + "Downloaded": false, + "EventHistoryId": "DeviceFreeze-0010", + "FreezePolicyUid": null, + "ID": "fa72b6ed-62f4-40bd-b581-ef5c114efb8e", + "IsCurrent": false, + "Name": "name1", + "NotificationEmails": [], + "PolicyConfigurationVersion": 0, + "PolicyGroupUid": null, + "Requester": "example@test.com", + "RequesterUid": "778f8cce-8cc6-4de1-b025-e0538f97e072", + "Statuses": [ + { + "ackClientTS": 0, + "ackClientUTC": 1, + "eventType": "Remove", + "scheduledFreezeDateUTC": 0, + "status": "Removed", + "statusUid": "9e413f56-8b2d-4605-9527-536427b9ad02", + "updatedBy": "example@test.com", + "updatedUTC": "2022-03-29T10:30:55.462+00:00" + }, + { + "ackClientTS": 0, + "ackClientUTC": 0, + "scheduledFreezeDateUTC": 0, + "status": "FreezeRequested", + "updatedBy": "example@test.com", + "updatedUTC": "2022-03-29T10:30:24.268+00:00" + } + ] + } + } +} +``` + +#### Human Readable Output + +>### Absolute Freeze request details for: c638c2dc-1dd1-4cfa-8708-46f368012398 +>|ID|Name|AccountUid|ActionRequestUid|EventHistoryId|CreatedUTC|ChangedUTC|Requester| +>|---|---|---|---|---|---|---|---| +>| fa72b6ed-62f4-40bd-b581-ef5c114efb8e | name1 | accountID | c638c2dc-1dd1-4cfa-8708-46f368012398 | DeviceFreeze-0010 | 2022-03-29T10:30:24.279+00:00 | 2022-03-29T10:30:55.462+00:00 | example@test.com | + + +### absolute-device-freeze-message-list +*** +Gets all the Freeze messages that are configured for the account by the given message_id. If message_id is not given all the messages will be returned. + + +#### Base Command + +`absolute-device-freeze-message-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| message_id | The system-defined, unique identifier of the Freeze message. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.FreezeMessage.ID | String | The system-defined, unique identifier of the Freeze message. | +| Absolute.FreezeMessage.Name | String | The user-defined name for the Freeze message. | +| Absolute.FreezeMessage.Content | String | The user-defined, HTML coded message that shows on a device when a Freeze is applied. | +| Absolute.FreezeMessage.CreatedBy | String | The username of the entity that created the Freeze message. | +| Absolute.FreezeMessage.ChangedBy | String | The username of the entity that last updated the Freeze message. | +| Absolute.FreezeMessage.CreatedUTC | String | The date and time when the Freeze message was created. | +| Absolute.FreezeMessage.ChangedUTC | String | The date and time when the Freeze message was last modified. | + +#### Command example +```!absolute-device-freeze-message-list``` +#### Context Example +```json +{ + "Absolute": { + "FreezeMessage": { + "ChangedBy": "778f8cce-8cc6-4de1-b025-e0538f97e072", + "ChangedUTC": "2022-04-03T07:45:01.487+00:00", + "Content": "some text- new", + "CreatedBy": "example@test.com", + "CreatedUTC": "2022-04-03T07:45:01.487+00:00", + "ID": "711b5da9-3867-473f-9d8f-9aba3de42b7a", + "Name": "name" + } + } +} +``` + +#### Human Readable Output + +>### Absolute Device freeze message details: +>|ID|Name|CreatedUTC|ChangedUTC|ChangedBy|CreatedBy| +>|---|---|---|---|---|---| +>| 711b5da9-3867-473f-9d8f-9aba3de42b7a | name | 2022-04-03T07:45:01.487+00:00 | 2022-04-03T07:45:01.487+00:00 | 778f8cce-8cc6-4de1-b025-e0538f97e072 | example@test.com | + + +### absolute-device-freeze-message-create +*** +Creates a new Freeze message for the account. + + +#### Base Command + +`absolute-device-freeze-message-create` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| html_message | The user-defined, HTML coded message that shows on a device when a Device Freeze is applied. Should be in HTML format with 1-4000 characters. | Required | +| message_name | The user-defined name for the Device Freeze message. The name should be a string with 1-255 characters. | Required | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.FreezeMessage.ID | String | The system-defined, unique identifier of the Freeze message. | + +#### Command example +```!absolute-device-freeze-message-create html_message="some text" message_name="name name"``` +#### Context Example +```json +{ + "Absolute": { + "FreezeMessage": { + "ID": "bdaf3a55-411a-4393-a0bf-7340f38fbc68" + } + } +} +``` + +#### Human Readable Output + +>Absolute New freeze message was created with ID: bdaf3a55-411a-4393-a0bf-7340f38fbc68 + +### absolute-device-freeze-message-update +*** +Updates the content of an existing Freeze message. + + +#### Base Command + +`absolute-device-freeze-message-update` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| html_message | The user-defined, HTML coded message that shows on a device when a Device Freeze is applied. Should be in HTML format with 1-4000 characters. | Required | +| message_name | The user-defined name for the Device Freeze message. The name should be a string with 1-255 characters. | Required | +| message_id | The system-defined, unique identifier of the Freeze message. | Required | + + +#### Context Output + +There is no context output for this command. +#### Command example +```!absolute-device-freeze-message-update html_message="new mesg" message_id=711b5da9-3867-473f-9d8f-9aba3de42b7a message_name="name-new"``` +#### Human Readable Output + +>Absolute Freeze message: 711b5da9-3867-473f-9d8f-9aba3de42b7a was updated successfully + +### absolute-device-freeze-message-delete +*** +Deletes an existing Freeze message for the account. + + +#### Base Command + +`absolute-device-freeze-message-delete` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| message_id | The system-defined, unique identifier of the Freeze message. | Required | + + +#### Context Output + +There is no context output for this command. +#### Command example +```!absolute-device-freeze-message-delete message_id="711b5da9-3867-473f-9d8f-9aba3de42b7a"``` +#### Human Readable Output + +>Absolute Freeze message: 711b5da9-3867-473f-9d8f-9aba3de42b7a was deleted successfully + +### absolute-device-unenroll +*** +Initiates an unenroll request on a list of eligible devices. + + +#### Base Command + +`absolute-device-unenroll` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| device_ids | A comma-separated list of device UIDs that should be unenrolled. | Required | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.DeviceUnenroll.DeviceUid | String | The unique GUID identifier of the device. | +| Absolute.DeviceUnenroll.SystemName | String | The name assigned to the device. | +| Absolute.DeviceUnenroll.Username | String | The unique user name of the user who was logged into the device at the time of the agent call. | +| Absolute.DeviceUnenroll.EligibleStatus | Number | The eligibility status of the device. Possible vales are: 0 for eligible, 1 for inactive or disabled, and 2 for stolen. | +| Absolute.DeviceUnenroll.Serial | String | The identification number that is assigned to the device by the device manufacturer. | +| Absolute.DeviceUnenroll.ESN | String | The unique Electronic SerialNumber \(ESN\) that is assigned to the agent installed on the device. | + +#### Command example +```!absolute-device-unenroll device_ids="1"``` +#### Context Example +```json +{ + "Absolute": { + "DeviceUnenroll": [ + { + "DeviceUid": "1", + "ESN": "2BU2PJD28VAA1UYL0008", + "EligibleStatus": 0, + "Serial": "CNF83051BN", + "SystemName": "user1", + "Username": "example@test.com" + }, + { + "DeviceUid": "2", + "ESN": "2BU2PJ545L0008", + "EligibleStatus": 1, + "Serial": "CNF43051BN", + "SystemName": "user2", + "Username": "example2@test.com" + } + ] + } +} +``` + +#### Human Readable Output + +>### Absolute unenroll devices: +>|DeviceUid|ESN|EligibleStatus|Serial|SystemName|Username| +>|---|---|---|---|---|---| +>| 1 | 2BU2PJD28VAA1UYL0008 | 0 | CNF83051BN | user1 | example@test.com | +>| 2 | 2BU2PJ545L0008 | 1 | CNF43051BN | user2 | example2@test.com | + + +### absolute-device-application-list +*** +Gets a list of device records and the corresponding software application data for each device on the account that you have access to or that meets the given filter. + + +#### Base Command + +`absolute-device-application-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| filter | The query by which to filter the device applications. If this argument is set, it overrides the others. For example, appName eq 'someName' or availableVirtualMemoryBytes lt 1073741824. | Optional | +| return_fields | A comma-separated list of all specific values to return. If not set, all possible values will be returned. | Optional | +| account_uids | A comma-separated list of the unique ID associated with this Absolute accounts. | Optional | +| device_ids | A comma-separated list of the system-defined unique identifier of the devices. | Optional | +| device_names | A comma-separated list of the devices names. | Optional | +| app_names | A comma-separated list of the applications names. | Optional | +| app_publishers | A comma-separated list of the name of the software publishers of the application. | Optional | +| user_names | A comma-separated list of the user names of the users logged in to the device. | Optional | +| os | A comma-separated list of the operating systems that are installed on the device. | Optional | +| esn | A comma-separated list of the system-defined unique Electronic Serial Numbers (ESN) assigned to the Absolute agent installed on the device. | Optional | +| limit | Maximum number of results to return. The default is 50. Default is 50. | Optional | +| page | The page number of the results to retrieve. Minimum value is 0. Default is 0. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.DeviceApplication.DeviceAppId | String | The unique ID of the application. | +| Absolute.DeviceApplication.DeviceUid | String | The system-defined unique identifier of the device. | +| Absolute.DeviceApplication.AccountUid | String | The unique ID associated with this Absolute account. | +| Absolute.DeviceApplication.AppId | String | The identifier of the application. | +| Absolute.DeviceApplication.AppName | String | The name of the application. | +| Absolute.DeviceApplication.AppPublisher | String | The name of the software publisher of the application. | +| Absolute.DeviceApplication.AppOriginalPublisher | String | The original name of the software publisher of the application. | +| Absolute.DeviceApplication.AppVersion | String | The version of the application. | +| Absolute.DeviceApplication.Ens | String | The system-defined unique Electronic Serial Number \(ESN\) assigned to the Absolute agent installed on the device. | +| Absolute.DeviceApplication.DeviceName | String | The name of the device. | +| Absolute.DeviceApplication.DeviceSerialNumber | String | The identification number that is assigned to the device by the device manufacturer. | +| Absolute.DeviceApplication.UserName | String | Includes the device name and the username of the user logged in to the device at the time of the agent call. | +| Absolute.DeviceApplication.InstallPath | String | The location where the application is installed. | +| Absolute.DeviceApplication.InstallDate | Date | The date \(in Unix epoch time\) when the application was installed. | +| Absolute.DeviceApplication.FirstDetectUtc | Date | The date and time \(in Unix epoch time\) when the indicated version of the application was first detected on the device. | +| Absolute.DeviceApplication.OsName | String | The operating system that is installed on the device. | +| Absolute.DeviceApplication.LastScanTimeUtc | Date | The date and time \(in Unix epoch time\) of the most recent installed software \(SNG\) scan. | + +#### Command example +```!absolute-device-application-list device_ids=1234 filter="appName eq 'Notepad++' or appName eq 'Settings'"``` +#### Context Example +```json +{ + "Absolute": { + "DeviceApplication": [ + { + "AccountUid": "accountID", + "AppId": "U2V0dGluZ3N8fE1pY3Jvc29mdHx8MTAuMC4yLjEwMDA=", + "AppName": "Settings", + "AppOriginalName": "Settings", + "AppOriginalPublisher": "Microsoft Corporation", + "AppOriginalVersion": "10.0.2.1000", + "AppPublisher": "Microsoft", + "AppVersion": "10.0.2.1000", + "DeviceAppId": "123456_24222cfe5ccbe45e6d5a78faa58cd977921b4c1dd552884ec38653934c3b75f9", + "DeviceName": "ABSOLUTE-ASSET-", + "DeviceSerialNumber": "GoogleCloud-B8736A4405BF0E968020BCBC46EDA096", + "DeviceUid": "123456", + "Esn": "D0001", + "FirstDetectUtc": 1648601001193, + "InstallDate": 1536995941018, + "InstallPath": "C:\\Windows\\ImmersiveControlPanel", + "LastScanTimeUtc": 1648627356120, + "OsName": "Microsoft Windows Server 2019 Datacenter" + }, + { + "AccountUid": "accountID", + "AppId": "Tm90ZXBhZCsrfHxOb3RlUGFkfHw4LjMuMw==", + "AppName": "Notepad++", + "AppOriginalName": "Notepad++ (64-bit x64)", + "AppOriginalPublisher": "Notepad++ Team", + "AppOriginalVersion": "8.3.3", + "AppPublisher": "NotePad", + "AppVersion": "8.3.3", + "DeviceAppId": "1234_3653d2a872cd1208dfc4845a20670a6c9364a626cd6c987cd5e916ca71f38105", + "DeviceName": "ABSOLUTE-ASSET-", + "DeviceSerialNumber": "GoogleCloud-6420CF930DEE84DE8497CF40F0D56AFA", + "DeviceUid": "1234", + "Esn": "D0004", + "FirstDetectUtc": 1648027180153, + "InstallDate": 1648026266334, + "InstallPath": "C:\\Program Files\\Notepad++", + "LastScanTimeUtc": 1648894013571, + "OsName": "Microsoft Windows Server 2022 Datacenter" + }, + { + "AccountUid": "accountID", + "AppId": "U2V0dGluZ3N8fE1pY3Jvc29mdHx8MTAuMC40LjEwMDA=", + "AppName": "Settings", + "AppOriginalName": "Settings", + "AppOriginalPublisher": "Microsoft Corporation", + "AppOriginalVersion": "10.0.4.1000", + "AppPublisher": "Microsoft", + "AppVersion": "10.0.4.1000", + "DeviceAppId": "1234_f3ef442d95c3b7155fe9b138384bda2219afb3048c2a9466f1174fc1488ca671", + "DeviceName": "ABSOLUTE-ASSET-", + "DeviceSerialNumber": "GoogleCloud-6420CF930DEE84DE8497CF40F0D56AFA", + "DeviceUid": "1234", + "Esn": "D0004", + "FirstDetectUtc": 1648027180153, + "InstallDate": 1620462024187, + "InstallPath": "C:\\Windows\\ImmersiveControlPanel", + "LastScanTimeUtc": 1648894013571, + "OsName": "Microsoft Windows Server 2022 Datacenter" + } + ] + } +} +``` + +#### Human Readable Output + +>### Absolute device applications list: +>|AccountUid|AppId|AppName|AppOriginalName|AppOriginalPublisher|AppOriginalVersion|AppPublisher|AppVersion|DeviceAppId|DeviceName|DeviceSerialNumber|DeviceUid|Esn|FirstDetectUtc|InstallDate|InstallPath|LastScanTimeUtc|OsName| +>|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| +>| accountID | U2V0dGluZ3N8fE1pY3Jvc29mdHx8MTAuMC4yLjEwMDA= | Settings | Settings | Microsoft Corporation | 10.0.2.1000 | Microsoft | 10.0.2.1000 | 123456_24222cfe5ccbe45e6d5a78faa58cd977921b4c1dd552884ec38653934c3b75f9 | ABSOLUTE-ASSET- | GoogleCloud-B8736A4405BF0E968020BCBC46EDA096 | 123456 | D0001 | 1648601001193 | 1536995941018 | C:\Windows\ImmersiveControlPanel | 1648627356120 | Microsoft Windows Server 2019 Datacenter | +>| accountID | Tm90ZXBhZCsrfHxOb3RlUGFkfHw4LjMuMw== | Notepad++ | Notepad++ (64-bit x64) | Notepad++ Team | 8.3.3 | NotePad | 8.3.3 | 1234_3653d2a872cd1208dfc4845a20670a6c9364a626cd6c987cd5e916ca71f38105 | ABSOLUTE-ASSET- | GoogleCloud-6420CF930DEE84DE8497CF40F0D56AFA | 1234 | D0004 | 1648027180153 | 1648026266334 | C:\Program Files\Notepad++ | 1648894013571 | Microsoft Windows Server 2022 Datacenter | +>| accountID | U2V0dGluZ3N8fE1pY3Jvc29mdHx8MTAuMC40LjEwMDA= | Settings | Settings | Microsoft Corporation | 10.0.4.1000 | Microsoft | 10.0.4.1000 | 1234_f3ef442d95c3b7155fe9b138384bda2219afb3048c2a9466f1174fc1488ca671 | ABSOLUTE-ASSET- | GoogleCloud-6420CF930DEE84DE8497CF40F0D56AFA | 1234 | D0004 | 1648027180153 | 1620462024187 | C:\Windows\ImmersiveControlPanel | 1648894013571 | Microsoft Windows Server 2022 Datacenter | +>Above results are with page number: 0 and with size: 50. + +### absolute-device-list +*** +Gets a list of device records and their corresponding data that meets the required filter for all devices in your account, based on your authorization token. + + +#### Base Command + +`absolute-device-list` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| filter | The query by which to filter all the devices managed by the account. If this argument is set, it overrides the others. For example, agentStatus eq 'A' or lastConnectedUtc lt datetime'2021-01-01T00:00:00Z'. | Optional | +| agent_status | The status of the Absolute agent on the device. Possible values are: Active, Disabled, Inactive. | Optional | +| os_name | Short description of the operating system expressed as a one-line string that includes the version of the operating system. | Optional | +| os_version | The version of the operating system. | Optional | +| manufacturer | The manufacturer of the device. | Optional | +| model | The product name from the manufacturer. | Optional | +| user_names | A comma-separated list of the usernames of the users who were logged in to the device at the time of the most recent agent call. If no user was logged in during the last agent call, the last detected username is used. | Optional | +| limit | Maximum number of results to return. Default is 50. | Optional | +| page | The page number of the results to retrieve. Minimum value is 0. Default is 0. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.Device.Id | String | The unique identifier assigned to the device. | +| Absolute.Device.Esn | String | The unique ESN \(Absolute Identifier\) assigned to the agent installed on the device. | +| Absolute.Device.LastConnectedUtc | Number | The date and time \(in Unix epoch\) when the device last connected to the Absolute Monitoring Center. | +| Absolute.Device.SystemName | String | The name assigned to the device. | +| Absolute.Device.FullSystemName | String | The full name assigned to the device consisting of the system name and the domain name. | +| Absolute.Device.AgentStatus | String | The status of the Absolute agent on the device. | +| Absolute.Device.osName | String | Short description of the operating system expressed as a one-line string that includes the version of the operating system. | +| Absolute.Device.SystemManufacturer | String | The manufacturer of the device. | +| Absolute.Device.SystemModel | String | The product name from the manufacturer. | +| Absolute.Device.SystemType | String | The system running on the Windows-based computer. | +| Absolute.Device.Serial | String | The manufacturer-defined unique identifier assigned to the device. May correspond to the serial number of the BIOS, the motherboard, or the chassis, depending on the manufacturer. | +| Absolute.Device.LocalIp | String | Last known local IP address of this device. | +| Absolute.Device.PublicIp | String | Last known public IP address of this device. | +| Absolute.Device.EncryptionStatus | String | The summarized encryption status of the device. | + +#### Command example +```!absolute-device-list os_name="Microsoft Windows Server 2019 Datacenter"``` +#### Context Example +```json +{ + "Absolute": { + "Device": { + "AgentStatus": "A", + "Esn": "D0001", + "FullSystemName": "ABSOLUTE-ASSET-.WORKGROUP", + "Id": "123456", + "LastConnectedUtc": 1648971645189, + "LocalIp": "127.0.0.1", + "PublicIp": "127.0.0.1", + "Serial": "GoogleCloud-B8736A4405BF0E968020BCBC46EDA096", + "SystemManufacturer": "Google", + "SystemModel": "GOOGLE COMPUTE ENGINE", + "SystemName": "ABSOLUTE-ASSET-", + "SystemType": "x64-based PC", + "osName": "Microsoft Windows Server 2019 Datacenter" + } + } +} +``` + +#### Human Readable Output + +>### Absolute devices list: +>|AgentStatus|Esn|FullSystemName|Id|LastConnectedUtc|LocalIp|PublicIp|Serial|SystemManufacturer|SystemModel|SystemName|SystemType|osName| +>|---|---|---|---|---|---|---|---|---|---|---|---|---| +>| A | D0001 | ABSOLUTE-ASSET-.WORKGROUP | 123456 | 1648971645189 | 127.0.0.1 | 127.0.0.1 | GoogleCloud-B8736A4405BF0E968020BCBC46EDA096 | Google | GOOGLE COMPUTE ENGINE | ABSOLUTE-ASSET- | x64-based PC | Microsoft Windows Server 2019 Datacenter | +>Above results are with page number: 0 and with size: 50. + +### absolute-device-get +*** +Gets a list of device records and their corresponding data that meets the required fields for all devices in your account. + + +#### Base Command + +`absolute-device-get` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| fields | A comma-separated list of all specific values to return. | Optional | +| device_ids | A comma-separated list of the system-defined unique identifier of the devices. | Optional | +| device_names | A comma-separated list of the devices names. | Optional | +| local_ips | A comma-separated list of the last known local IP addresses of a device. | Optional | +| public_ips | A comma-separated list of the last known public IP addresses of a device. | Optional | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.Device.Id | String | The unique identifier assigned to the device. | +| Absolute.Device.Esn | String | The unique ESN \(Absolute Identifier\) assigned to the agent installed on the device. | +| Absolute.Device.Domain | String | The name of the Windows domain to which this device belongs. | +| Absolute.Device.LastConnectedUtc | Number | The date and time \(in Unix epoch\) when the device last connected to the Absolute Monitoring Center. | +| Absolute.Device.SystemName | String | The name assigned to the device. | +| Absolute.Device.FullSystemName | String | The full name assigned to the device consisting of the system name and the domain name. | +| Absolute.Device.AgentStatus | String | The status of the Absolute agent on the device. | +| Absolute.Device.Os.name | String | Short description of the operating system expressed as a one-line string that includes the version of the operating system. | +| Absolute.Device.Os.version | String | The version of the operating system. | +| Absolute.Device.Os.currentBuild | String | The current build number of the operating system. | +| Absolute.Device.Os.architecture | String | The architecture of the operating system. | +| Absolute.Device.Os.installDate | Number | The date and time \(in Unix epoch\) when the operating system was installed. | +| Absolute.Device.Os.productKey | String | The product key of the operating system. | +| Absolute.Device.Os.serialNumber | String | The serial identification number of the operating system. | +| Absolute.Device.Os.lastBootTime | Number | The date and time \(in Unix epoch\) when the operating system was last restarted. | +| Absolute.Device.Bios.id | String | The unique identifier of this BIOS given by the manufacturer. | +| Absolute.Device.Bios.serialNumber | String | The serial number assigned to the BIOS. | +| Absolute.Device.Bios.smBiosVersion | String | The major version number of the BIOS, as reported by SMBIOS. | +| Absolute.Device.Bios.version | String | The version of the BIOS, as reported by SMBIOS. | +| Absolute.Device.Bios.versionDate | String | A substring of the manufacturer of the BIOS \+ the version of the BIOS version, as reported by SMBIOS \+ the release date of the Window BIOS. | +| Absolute.Device.SystemManufacturer | String | The manufacturer of the device. | +| Absolute.Device.SystemModel | String | The product name from the manufacturer. | +| Absolute.Device.SystemType | String | The system running on the Windows-based computer. | +| Absolute.Device.Serial | String | The manufacturer-defined unique identifier assigned to the device. May correspond to the serial number of the BIOS, the motherboard, or the chassis, depending on the manufacturer. | +| Absolute.Device.LocalIp | String | Last known local IP address of this device. | +| Absolute.Device.PublicIp | String | Last known public IP address of this device. | +| Absolute.Device.EncryptionStatus | String | The summarized encryption status of the device. | +| Absolute.Device.Username | String | The unique username of the user that was logged in to the device at the time of the most recent agent call. | +| Absolute.Device.PolicyGroupUid | String | The unique identifier of the policy group that the device belongs to. | +| Absolute.Device.PolicyGroupName | String | The name of the policy group that the device belongs to. | +| Absolute.Device.IsStolen | String | Indicates whether this device was reported as stolen. | +| Absolute.Device.DeviceStatus.type | String | The status of the device. Possible values are STOLEN or MISSING. | +| Absolute.Device.DeviceStatus.reported | Number | The data and time \(in Unix epoch\) when the device was reported missing or stolen. | +| Absolute.Device.NetworkAdapters.networkSSID | String | The Service Set Identifier \(SSID\) of the connected Wi-Fi adapter. | + +#### Command example +```!absolute-device-get device_names="ABSOLUTE-ASSET-"``` +#### Context Example +```json +{ + "Absolute": { + "Device": [ + { + "AgentStatus": "A", + "Bios": { + "id": "Google - 1 Google ", + "serialNumber": "GoogleCloud-B8736A4405BF0E968020BCBC46EDA096", + "smBiosVersion": "2.4", + "version": "Google - 1 Google ", + "versionDate": "Google Google, 01/01/2011" + }, + "Domain": "WORKGROUP", + "Esn": "D0001", + "FullSystemName": "ABSOLUTE-ASSET-.WORKGROUP", + "Id": "123456", + "LastConnectedUtc": 1648971645189, + "LocalIp": "127.0.0.1", + "NetworkAdapters": [ + {}, + {} + ], + "Os": { + "architecture": "64-bit", + "currentBuild": "17763", + "installDate": 1643800616000, + "lastBootTime": 1646884562500, + "name": "Microsoft Windows Server 2019 Datacenter", + "productKey": "WMDGN-G9PQG-XVVXX-R3X43-63DFG", + "serialNumber": "00430-00000-00000-AA691", + "version": "10.0.17763" + }, + "PolicyGroupName": "Global Policy Group", + "PublicIp": "127.0.0.1", + "Serial": "GoogleCloud-B8736A4405BF0E968020BCBC46EDA096", + "SystemManufacturer": "Google", + "SystemModel": "GOOGLE COMPUTE ENGINE", + "SystemName": "ABSOLUTE-ASSET-", + "SystemType": "x64-based PC", + "Username": "Administrator" + }, + { + "AgentStatus": "A", + "Bios": { + "id": "Google - 1 Google ", + "serialNumber": "GoogleCloud-6420CF930DEE84DE8497CF40F0D56AFA", + "smBiosVersion": "2.4", + "version": "Google - 1 Google ", + "versionDate": "Google Google, 01/01/2011" + }, + "Domain": "WORKGROUP", + "Esn": "D0004", + "FullSystemName": "ABSOLUTE-ASSET-.WORKGROUP", + "Id": "1234", + "LastConnectedUtc": 1648971873079, + "LocalIp": "127.0.0.1", + "NetworkAdapters": [ + {}, + {} + ], + "Os": { + "architecture": "64-bit", + "currentBuild": "20348", + "installDate": 1648025097000, + "lastBootTime": 1648025060499, + "name": "Microsoft Windows Server 2022 Datacenter", + "productKey": "WX4NM-KYWYW-QJJR4-XV3QB-6VM33", + "serialNumber": "00454-60000-00001-AA937", + "version": "10.0.20348" + }, + "PolicyGroupName": "Global Policy Group", + "PublicIp": "127.0.0.1", + "Serial": "GoogleCloud-6420CF930DEE84DE8497CF40F0D56AFA", + "SystemManufacturer": "Google", + "SystemModel": "GOOGLE COMPUTE ENGINE", + "SystemName": "ABSOLUTE-ASSET-", + "SystemType": "x64-based PC", + "Username": "Administrator" + } + ] + } +} +``` + +#### Human Readable Output + +>### Absolute devices list: +>|AgentStatus|Bios|Domain|Esn|FullSystemName|Id|LastConnectedUtc|LocalIp|NetworkAdapters|Os|PolicyGroupName|PublicIp|Serial|SystemManufacturer|SystemModel|SystemName|SystemType|Username| +>|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| +>| A | id: Google - 1 Google
serialNumber: GoogleCloud-B8736A4405BF0E968020BCBC46EDA096
version: Google - 1 Google
versionDate: Google Google, 01/01/2011
smBiosVersion: 2.4 | WORKGROUP | D0001 | ABSOLUTE-ASSET-.WORKGROUP | 123456 | 1648971645189 | 127.0.0.1 | {},
{} | architecture: 64-bit
installDate: 1643800616000
lastBootTime: 1646884562500
name: Microsoft Windows Server 2019 Datacenter
productKey: WMDGN-G9PQG-XVVXX-R3X43-63DFG
serialNumber: 00430-00000-00000-AA691
version: 10.0.17763
currentBuild: 17763 | Global Policy Group | 127.0.0.1 | GoogleCloud-B8736A4405BF0E968020BCBC46EDA096 | Google | GOOGLE COMPUTE ENGINE | ABSOLUTE-ASSET- | x64-based PC | Administrator | +>| A | id: Google - 1 Google
serialNumber: GoogleCloud-6420CF930DEE84DE8497CF40F0D56AFA
version: Google - 1 Google
versionDate: Google Google, 01/01/2011
smBiosVersion: 2.4 | WORKGROUP | D0004 | ABSOLUTE-ASSET-.WORKGROUP | 1234 | 1648971873079 | 127.0.0.1 | {},
{} | architecture: 64-bit
installDate: 1648025097000
lastBootTime: 1648025060499
name: Microsoft Windows Server 2022 Datacenter
productKey: WX4NM-KYWYW-QJJR4-XV3QB-6VM33
serialNumber: 00454-60000-00001-AA937
version: 10.0.20348
currentBuild: 20348 | Global Policy Group | 127.0.0.1 | GoogleCloud-6420CF930DEE84DE8497CF40F0D56AFA | Google | GOOGLE COMPUTE ENGINE | ABSOLUTE-ASSET- | x64-based PC | Administrator | + + +### absolute-device-location-get +*** +Gets a list of devices geo locations records and their corresponding data that meets the required devices IDs. + + +#### Base Command + +`absolute-device-location-get` +#### Input + +| **Argument Name** | **Description** | **Required** | +| --- | --- | --- | +| device_ids | A comma-separated list of the system-defined unique identifier of the devices. | Required | + + +#### Context Output + +| **Path** | **Type** | **Description** | +| --- | --- | --- | +| Absolute.LocationReport.Coordinates | Unknown | A comma-separated list where the first number is the estimated latitude and the second number is the estimated longitude \(in degrees\) where the device is located. | +| Absolute.LocationReport.ID | String | The system-defined unique identifier of the device. | +| Absolute.LocationReport.City | String | The city where the device is located. | +| Absolute.LocationReport.State | String | The state or province where the device is located. | +| Absolute.LocationReport.CountryCode | String | The country code for the country where the device is located. | +| Absolute.LocationReport.Country | String | The country where the device is located. | +| Absolute.LocationReport.LocationTechnology | String | The technology used to get the location. | +| Absolute.LocationReport.Accuracy | Number | The estimated accuracy \(in meters\) of the technology used to locate the device. | +| Absolute.LocationReport.LastUpdate | Number | The date and time \(in Unix epoch\) when the device last changed its location. | + +#### Command example +```!absolute-device-location-get device_ids=1234``` +#### Human Readable Output + +>No device locations found in Absolute for the given filters: {'device_ids': '1234'} + + +### Creating a filtering and sorting query +The following commands have the option to insert a **filter** argument: +- ***absolute-device-application-list*** +- ***absolute-device-list*** + +Absolute uses a subset of query options from Open Data Protocol (OData) for filtering and sorting. +OData version 1 and 2 are supported. OData query parameters must be alphabetized and URI encoded. +For more information about OData, see: https://www.odata.org/documentation. + +A few examples of creating a query (i.e., passing a filter argument): +- Using the eq operator + - Get a list of all devices with an active status: agentStatus eq 'A' + - Get a list of all devices that are currently frozen: dfStatus.statusCode eq 'FRZN' + - Get a list of all devices that have 1734 in their ESN (Identifier): substringof('1734',esn) eq true +- Using the ne operator + - Get a list of all devices that are not active: agentStatus ne 'A' +- Using the gt operator + - Get a list of all devices with greater than 1 GB (1073741824 bytes) of available physical: availablePhysicalRamBytes gt 1073741824 +- Using the or operator: + - Get a list of all devices with less than 1 GB (1073741824 bytes) of available physical ram or less than 1 GB (1073741824 bytes) of available virtual raml: availablePhysicalMemroyBytes lt 1073741824 or availableVirtualMemoryBytes lt 1073741824 + +For more examples and explanations, see the [Absolute docs](https://www.absolute.com/media/2221/abt-api-working-with-absolute.pdf) (from page 10). diff --git a/Packs/Absolute/Integrations/Absolute/command_examples b/Packs/Absolute/Integrations/Absolute/command_examples new file mode 100644 index 000000000000..77a4b19953d8 --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/command_examples @@ -0,0 +1,14 @@ +!absolute-custom-device-field-list device_id=e93f2464-2766-4a6b-8f00-66c8fb13e23a +!absolute-custom-device-field-update device_id=e93f2464-2766-4a6b-8f00-66c8fb13e23a cdf_uid=4m9fUCZqTYec1bJgDSNg value="test2" +!absolute-device-freeze-request device_ids=c62aaac3-e698-4c0e-9ce7-31ab3fa09fea device_freeze_type=Scheduled html_message="test" message_name="new name" request_name="name1" scheduled_freeze_date=2022-04-03T13:30:00.000Z passcode_type=RandomForEach passcode_length=5 +!absolute-device-remove-freeze-request device_ids=c62aaac3-e698-4c0e-9ce7-31ab3fa09fea remove_scheduled=true +!absolute-device-freeze-request-get request_uid=c638c2dc-1dd1-4cfa-8708-46f368012398 +!absolute-device-freeze-message-list +!absolute-device-freeze-message-create html_message="some text" message_name="name name" +!absolute-device-freeze-message-update html_message="new mesg" message_id=711b5da9-3867-473f-9d8f-9aba3de42b7a message_name="name-new" +!absolute-device-freeze-message-delete message_id="711b5da9-3867-473f-9d8f-9aba3de42b7a" +!absolute-device-unenroll device_ids="1" +!absolute-device-application-list device_ids=e93f2464-2766-4a6b-8f00-66c8fb13e23a filter="appName eq 'Notepad++' or appName eq 'Settings'" +!absolute-device-list os_name="Microsoft Windows Server 2019 Datacenter" +!absolute-device-get device_names="ABSOLUTE-ASSET-" +!absolute-device-location-get device_ids=e93f2464-2766-4a6b-8f00-66c8fb13e23a \ No newline at end of file diff --git a/Packs/Absolute/Integrations/Absolute/test_data/custom_device_field_list_response.json b/Packs/Absolute/Integrations/Absolute/test_data/custom_device_field_list_response.json new file mode 100644 index 000000000000..6c36a75b8944 --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/test_data/custom_device_field_list_response.json @@ -0,0 +1,22 @@ +{ + "deviceUid": "02b9daa4-8e60-4640-8b15-76d41ecf6a94", + "esn": "2DE05RUEG0AA1V7S0003", + "cdfValues": [ + { + "cdfUid": "njazpLrEQwqeFDqk4yQCfg", + "fieldKey": 1, + "fieldName": "Asset Number", + "categoryCode": "ESNCOLUMN", + "fieldValue": "No Asset Tag", + "type": "Text" + }, + { + "cdfUid": "7PwIrjEXTAqvpb5WdV2w", + "fieldKey": 3, + "fieldName": "Assigned Username", + "categoryCode": "ESNCOLUMN", + "fieldValue": "", + "type": "Text" + } + ] +} \ No newline at end of file diff --git a/Packs/Absolute/Integrations/Absolute/test_data/custom_get_device_freeze_request_response.json b/Packs/Absolute/Integrations/Absolute/test_data/custom_get_device_freeze_request_response.json new file mode 100644 index 000000000000..e653abcaec62 --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/test_data/custom_get_device_freeze_request_response.json @@ -0,0 +1,82 @@ +[ + { + "id": "1", + "accountUid": "e7a9fb73-44b0-4f5d-990b-39ff884425eb", + "actionRequestUid": "e416f97e-dc43-4ed0-88c3-b33ea66c660f", + "deviceUid": "56be8d1f-2eb8-4e9b-bbd6-1aab032abcde", + "name": "On-demand Freeze request", + "statuses": [ + { + "actionUid": null, + "statusUid": "5336db35-ae66-435e-a29d-41ef2f10a86c", + "status": "Launching", + "messageKey": null, + "messageParams": null, + "message": null, + "updatedBy": "example@test.com", + "updatedUTC": "2021-11-03T07:33:55.966+00:00", + "triggerActionUid": null, + "eventType": null, + "ackClientTS": 1548265912126, + "ackClientUTC": 1548294712126, + "instruction": "", + "scheduledFreezeDateUTC": 0 + }, + { + "actionUid": null, + "statusUid": null, + "status": "FreezeRequested", + "messageKey": null, + "messageParams": null, + "message": null, + "updatedBy": "example@test.com", + "updatedUTC": 1548294707085, + "triggerActionUid": null, + "eventType": null, + "ackClientTS": 0, + "ackClientUTC": 0, + "instruction": null, + "scheduledFreezeDateUTC": 0 + } + ], + "configuration": { + "messageName": "On-demand Freeze message", + "htmlClear": "some html", + "passcodeClear": "12345678", + "passcodeOption": "RandomForEach", + "freezeMessage": "This device has been frozen by a Company", + "freezeId": "DeviceFreeze-0864", + "configurationUid": "c132d6aa-03b5-483d-89ab-77f45f7346cc", + "action": "DFZ", + "type": "OnDemand", + "passcodeLength": 8, + "passcodeSalt": "P0efY", + "passcodeHashed": "+AG=", + "html": null, + "disableRemoteLogin": true, + "disableFileSharing": true, + "forceReboot": false, + "conditions": [ + {} + ], + "issuedUTC": "2021-11-03T07:33:55.966+00:00", + "preLoginEnabled": true, + "serviceControlList": null + }, + "requester": "example@test.com", + "requesterUid": "1abc2de3-fa45-67b8-9cde-0f12a34bc567", + "customAttributes": null, + "createdUTC": "2021-11-03T07:33:56.004+00:00", + "changedUTC": "2021-11-03T07:33:55.966+00:00", + "notificationEmails": [ + "example1@test.com", + "example2@test.com" + ], + "eventHistoryId": "DeviceFreeze-0864", + "policyGroupUid": null, + "policyConfigurationVersion": 0, + "freezePolicyUid": null, + "downloaded": false, + "isCurrent": true + } +] \ No newline at end of file diff --git a/Packs/Absolute/Integrations/Absolute/test_data/device_freeze_message_list_response.json b/Packs/Absolute/Integrations/Absolute/test_data/device_freeze_message_list_response.json new file mode 100644 index 000000000000..dfea708bd03e --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/test_data/device_freeze_message_list_response.json @@ -0,0 +1,11 @@ +[ + { + "id": "1", + "name": "On-demand Freeze message", + "content": "This device has been frozen by company.", + "createdBy": "example1@test.com", + "changedBy": "example2@test.com", + "createdUTC": "2020-11-26T22:29:17.687+00:00", + "changedUTC": "2020-12-14T09:14:52.148+00:00" + } +] \ No newline at end of file diff --git a/Packs/Absolute/Integrations/Absolute/test_data/device_location_get.json b/Packs/Absolute/Integrations/Absolute/test_data/device_location_get.json new file mode 100644 index 000000000000..10fc7ceb21ce --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/test_data/device_location_get.json @@ -0,0 +1,52 @@ +[ + { + "id": "1", + "geoData": { + "location": { + "point": { + "x": -123.13202, + "y": 49.288162, + "type": "Point", + "coordinates": [ + -123.13202, + 49.288162 + ] + }, + "geoAddress": { + "city": "TLV", + "state": "Israel", + "countryCode": "IL", + "country": "Israel" + }, + "locationTechnology": "gps", + "accuracy": 10, + "lastUpdate": 1605747972853 + } + } + }, + { + "id": "2", + "geoData": { + "location": { + "point": { + "x": -124.1, + "y": 59.2, + "type": "Point", + "coordinates": [ + -124.1, + 59.2 + ] + }, + "geoAddress": { + "city": "Jerusalem", + "state": "Israel", + "countryCode": "IL", + "country": "Israel" + }, + "locationTechnology": "gps", + "accuracy": 15, + "lastUpdate": 1605747972853 + } + } + } +] \ No newline at end of file diff --git a/Packs/Absolute/Integrations/Absolute/test_data/unenroll_device_response.json b/Packs/Absolute/Integrations/Absolute/test_data/unenroll_device_response.json new file mode 100644 index 000000000000..4b5e960ad35c --- /dev/null +++ b/Packs/Absolute/Integrations/Absolute/test_data/unenroll_device_response.json @@ -0,0 +1,18 @@ +[ + { + "deviceUid": "1", + "systemName": "user1", + "username": "example@test.com", + "eligibleStatus": 0, + "serial": "CNF83051BN", + "esn": "2BU2PJD28VAA1UYL0008" + }, + { + "deviceUid": "2", + "systemName": "user2", + "username": "example2@test.com", + "eligibleStatus": 1, + "serial": "CNF43051BN", + "esn": "2BU2PJ545L0008" + } +] \ No newline at end of file diff --git a/Packs/Absolute/README.md b/Packs/Absolute/README.md new file mode 100644 index 000000000000..391ed68d202c --- /dev/null +++ b/Packs/Absolute/README.md @@ -0,0 +1,42 @@ +Absolute enables you to manage and secure your data, devices, and applications with an unbreakable connection to every endpoint. Your sensitive data remains protected, even when accessed from outside your network. + +## What does this pack do? +- Get or update a list of custom device fields. +- Create or remove a Freeze request for one or more devices. +- Get detailed information about a Freeze request. +- Get, create, update, or delete a Freeze message. +- Initiate an un-enroll request on a list of eligible devices. +- Get a list of device records and the corresponding software application data for a device. +- Get a list of devices' geo location records and their corresponding data. + +## Prerequisites + +To configure an instance of Absolute, you need to obtain the following information. + +* Server URL +* Token ID + * A random GUI string with its public information (like username). + * It is associated with the same role and device group as the Absolute user account. +* Secret Key - A random sequence of bits and is private and contains sensitive information. + +### Create a Token ID and Secret Key +1. In the Absolute console, click the **+** (in the quick access toolbar) > **API Token**. +2. On the **API Token Management** page, click the **Create token** button. The Create Token dialog box appears. +3. Enter a **Token name** and **Description**. +4. Click **Save** (The Token Created dialog box displays your generated token ID). +5. Download the token ID and secret key or view the secret key. +Note: If you close this dialog box before downloading or copying the secret key, you cannot retrieve it later. + +### Download the Token ID and Secret Key +1. Click **Download Token**. +2. Save the .token file. +3. Use a text editor to open and view the file. +4. To view the secret key: + 1. Click **View Secret Key**. The secret key is populated. + 2. Copy both values of the **Token ID** and **Secret key** to a text file and save the file. +5. Click **Close**. + +### Notes: +- On the **API Token Management** page, the new token is added to your list of tokens. +- If a 401 error causes the API authentication to fail, you can enable authentication debugging from the Absolute console. +- The secret key is comparable to a password. Keep it secure, and do not share it with anyone. diff --git a/Packs/Absolute/TestPlaybooks/playbook-Absolute.yml b/Packs/Absolute/TestPlaybooks/playbook-Absolute.yml new file mode 100644 index 000000000000..a483dca1d03a --- /dev/null +++ b/Packs/Absolute/TestPlaybooks/playbook-Absolute.yml @@ -0,0 +1,668 @@ +id: Absolute_TestPlaybook +name: Absolute_TestPlaybook +version: -1 +fromversion: 6.0.0 +starttaskid: '0' +tasks: + "0": + id: "0" + taskid: 9858de99-b443-465e-843c-599efcd51ae3 + type: start + task: + id: 9858de99-b443-465e-843c-599efcd51ae3 + version: -1 + name: "" + iscommand: false + brand: "" + nexttasks: + '#none#': + - "1" + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 50 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "1": + id: "1" + taskid: 7eb95a5a-d34e-4304-8b1f-70d40c419b0a + type: regular + task: + id: 7eb95a5a-d34e-4304-8b1f-70d40c419b0a + version: -1 + name: DeleteContext + script: DeleteContext + type: regular + iscommand: true + brand: "" + nexttasks: + '#none#': + - "4" + scriptarguments: + all: + simple: "yes" + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 195 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "2": + id: "2" + taskid: 4fb4f29c-b8e7-4ec8-80b3-717d6e1594e1 + type: regular + task: + id: 4fb4f29c-b8e7-4ec8-80b3-717d6e1594e1 + version: -1 + name: absolute-custom-device-field-list + script: Absolute|||absolute-custom-device-field-list + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "3" + scriptarguments: + device_id: + simple: e93f2464-2766-4a6b-8f00-66c8fb13e23a + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 545 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "3": + id: "3" + taskid: 0f7429f4-7c8e-4804-8349-342720f2a18c + type: condition + task: + id: 0f7429f4-7c8e-4804-8349-342720f2a18c + version: -1 + name: Verify Outputs + type: condition + iscommand: false + brand: "" + nexttasks: + "yes": + - "5" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: isEqualString + left: + value: + simple: Absolute.CustomDeviceField.DeviceUID + iscontext: true + right: + value: + simple: e93f2464-2766-4a6b-8f00-66c8fb13e23a + - - operator: isEqualString + left: + value: + simple: Absolute.CustomDeviceField.ESN + iscontext: true + right: + value: + simple: 1G3H437HW9AA48ND0004 + - - operator: in + left: + value: + simple: TPB + right: + value: + simple: Absolute.CustomDeviceField.CDFValues.FieldValue + iscontext: true + view: |- + { + "position": { + "x": 50, + "y": 720 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "4": + id: "4" + taskid: 49d61447-a44c-46d1-8005-c37a6dc24759 + type: regular + task: + id: 49d61447-a44c-46d1-8005-c37a6dc24759 + version: -1 + name: absolute-custom-device-field-update + script: Absolute|||absolute-custom-device-field-update + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "2" + scriptarguments: + cdf_uid: + simple: 2iS3ryiSvSDsksJ289vtQ + device_id: + simple: e93f2464-2766-4a6b-8f00-66c8fb13e23a + value: + simple: TPB + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 370 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "5": + id: "5" + taskid: 4667f58c-5ccc-4db3-868f-8382e8bb6ee8 + type: regular + task: + id: 4667f58c-5ccc-4db3-868f-8382e8bb6ee8 + version: -1 + name: absolute-device-freeze-request + script: Absolute|||absolute-device-freeze-request + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "27" + scriptarguments: + device_freeze_type: + simple: Scheduled + device_ids: + simple: e93f2464-2766-4a6b-8f00-66c8fb13e23a + html_message: + simple: TPB-freeze + message_name: + simple: TPB-freeze + passcode_length: + simple: "5" + passcode_type: + simple: RandomForEach + request_name: + simple: TPB-freeze + scheduled_freeze_date: + simple: "2089-04-01T11:32:00.000Z" + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 895 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "7": + id: "7" + taskid: e0bbb8c6-a888-4732-8ccd-f6832a88bd3b + type: regular + task: + id: e0bbb8c6-a888-4732-8ccd-f6832a88bd3b + version: -1 + name: absolute-device-remove-freeze-request + script: Absolute|||absolute-device-remove-freeze-request + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "8" + scriptarguments: + device_ids: + simple: e93f2464-2766-4a6b-8f00-66c8fb13e23a + remove_offline: + simple: "false" + remove_scheduled: + simple: "false" + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 1245 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "8": + id: "8" + taskid: ea752965-35b5-4c37-85a4-630d0f39708b + type: regular + task: + id: ea752965-35b5-4c37-85a4-630d0f39708b + version: -1 + name: absolute-device-freeze-request-get + script: Absolute|||absolute-device-freeze-request-get + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "10" + scriptarguments: + request_uid: + simple: ${Absolute.FreezeRequest.RequestUID} + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 1420 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "10": + id: "10" + taskid: 67a7d73d-9b1a-4d20-8ef1-820e05147045 + type: regular + task: + id: 67a7d73d-9b1a-4d20-8ef1-820e05147045 + version: -1 + name: absolute-device-freeze-message-list + script: Absolute|||absolute-device-freeze-message-list + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "12" + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 1595 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "12": + id: "12" + taskid: c3b25283-0c7b-46a5-8d3d-27b0e0a5a707 + type: regular + task: + id: c3b25283-0c7b-46a5-8d3d-27b0e0a5a707 + version: -1 + name: absolute-device-freeze-message-create + script: Absolute|||absolute-device-freeze-message-create + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "13" + scriptarguments: + html_message: + simple: TPB message + message_name: + simple: TPB message + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 1770 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "13": + id: "13" + taskid: 306504b4-64de-444d-8e30-8103c8d14baa + type: condition + task: + id: 306504b4-64de-444d-8e30-8103c8d14baa + version: -1 + name: Verify Outputs + type: condition + iscommand: false + brand: "" + nexttasks: + "yes": + - "14" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: isNotEmpty + left: + value: + simple: Absolute.FreezeMessage.ID + iscontext: true + right: + value: {} + view: |- + { + "position": { + "x": 50, + "y": 1945 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "14": + id: "14" + taskid: 38444ac6-6373-4cff-87c6-d08ba28c2d47 + type: regular + task: + id: 38444ac6-6373-4cff-87c6-d08ba28c2d47 + version: -1 + name: absolute-device-freeze-message-update + script: Absolute|||absolute-device-freeze-message-update + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "15" + scriptarguments: + html_message: + simple: TPB-new + message_id: + simple: ${Absolute.FreezeMessage.ID} + message_name: + simple: TPB-new + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 2120 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "15": + id: "15" + taskid: 00a027d1-86e8-4095-8759-bd8eb841ff90 + type: regular + task: + id: 00a027d1-86e8-4095-8759-bd8eb841ff90 + version: -1 + name: absolute-device-freeze-message-delete + script: Absolute|||absolute-device-freeze-message-delete + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "18" + scriptarguments: + message_id: + simple: ${Absolute.FreezeMessage.ID} + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 2295 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "18": + id: "18" + taskid: 55dfb548-47f3-4212-8c3b-9e516274a4b8 + type: regular + task: + id: 55dfb548-47f3-4212-8c3b-9e516274a4b8 + version: -1 + name: absolute-device-application-list + script: Absolute|||absolute-device-application-list + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "20" + scriptarguments: + filter: + simple: appName eq 'Notepad++' + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 2470 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "20": + id: "20" + taskid: c4e236a4-1b2e-4dc6-8e77-0f426fc74f22 + type: regular + task: + id: c4e236a4-1b2e-4dc6-8e77-0f426fc74f22 + version: -1 + name: absolute-device-list + script: Absolute|||absolute-device-list + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "22" + scriptarguments: + agent_status: + simple: Active + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 2645 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "22": + id: "22" + taskid: b352a519-b8c3-42f8-8ddb-47b53cae882c + type: regular + task: + id: b352a519-b8c3-42f8-8ddb-47b53cae882c + version: -1 + name: absolute-device-get + script: Absolute|||absolute-device-get + type: regular + iscommand: true + brand: Absolute + nexttasks: + '#none#': + - "26" + scriptarguments: + device_ids: + simple: e93f2464-2766-4a6b-8f00-66c8fb13e23a + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 2820 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "26": + id: "26" + taskid: 08f178bf-b7dd-4c94-8bab-b385bc4fff09 + type: title + task: + id: 08f178bf-b7dd-4c94-8bab-b385bc4fff09 + version: -1 + name: Test Done + type: title + iscommand: false + brand: "" + separatecontext: false + view: |- + { + "position": { + "x": 50, + "y": 2995 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false + "27": + id: "27" + taskid: 4ba60e17-3304-411a-88a9-a77021aad4a7 + type: condition + task: + id: 4ba60e17-3304-411a-88a9-a77021aad4a7 + version: -1 + name: Verify Outputs + type: condition + iscommand: false + brand: "" + nexttasks: + "yes": + - "7" + separatecontext: false + conditions: + - label: "yes" + condition: + - - operator: in + left: + value: + simple: e93f2464-2766-4a6b-8f00-66c8fb13e23a + right: + value: + simple: Absolute.FreezeRequest.SucceededDeviceUIDs + iscontext: true + - - operator: isNotEmpty + left: + value: + simple: Absolute.FreezeRequest.RequestUID + iscontext: true + view: |- + { + "position": { + "x": 50, + "y": 1070 + } + } + note: false + timertriggers: [] + ignoreworker: false + skipunavailable: false + quietmode: 0 + isoversize: false + isautoswitchedtoquietmode: false +view: |- + { + "linkLabelsPosition": {}, + "paper": { + "dimensions": { + "height": 3010, + "width": 380, + "x": 50, + "y": 50 + } + } + } +inputs: [] +outputs: [] diff --git a/Packs/Absolute/pack_metadata.json b/Packs/Absolute/pack_metadata.json new file mode 100644 index 000000000000..30863856fd33 --- /dev/null +++ b/Packs/Absolute/pack_metadata.json @@ -0,0 +1,19 @@ +{ + "name": "Absolute", + "description": "Absolute is an adaptive endpoint security solution that delivers device security, data security and asset management of endpoints", + "support": "xsoar", + "currentVersion": "1.0.0", + "author": "Cortex XSOAR", + "url": "https://www.paloaltonetworks.com/cortex", + "email": "", + "categories": [ + "Endpoint" + ], + "tags": [], + "useCases": [], + "keywords": [], + "marketplaces": [ + "xsoar", + "marketplacev2" + ] +} \ No newline at end of file diff --git a/Tests/conf.json b/Tests/conf.json index 52b8a0ccd5bc..24fcb6505928 100644 --- a/Tests/conf.json +++ b/Tests/conf.json @@ -257,6 +257,11 @@ "playbookID": "Zimperium_Test", "fromversion": "5.0.0" }, + { + "integrations": "Absolute", + "playbookID": "Absolute_TestPlaybook", + "fromversion": "6.0.0" + }, { "integrations": "ServiceDeskPlus", "playbookID": "Service Desk Plus Test",