From ebf2b992742cf9f2488ba37a720902857ea9e8e8 Mon Sep 17 00:00:00 2001 From: Emanuela Mitreva Date: Tue, 9 Mar 2021 20:35:18 +0200 Subject: [PATCH 01/20] CBAPI-2022: Fix bugs and improve unit test coverage --- src/cbc_sdk/platform/processes.py | 27 +- .../unit/fixtures/platform/mock_process.py | 688 +++++++++++++++++- .../unit/platform/test_platform_process.py | 207 +++++- 3 files changed, 874 insertions(+), 48 deletions(-) diff --git a/src/cbc_sdk/platform/processes.py b/src/cbc_sdk/platform/processes.py index baf473ec9..d3ea5444f 100644 --- a/src/cbc_sdk/platform/processes.py +++ b/src/cbc_sdk/platform/processes.py @@ -683,8 +683,10 @@ def _get_query_parameters(self): query = self._query_builder._collapse() if self._query_builder._process_guid is not None: args["process_guid"] = self._query_builder._process_guid - elif self._model_unique_id is not None: - args["process_guid"] = self._model_unique_id + elif 'process_guid:' in query: + q = query.split('process_guid:', 1)[1].split(' ', 1)[0] + args["process_guid"] = q + if 'parent_guid:' in query: # extract parent_guid from where() clause parent_guid = query.split('parent_guid:', 1)[1].split(' ', 1)[0] @@ -728,27 +730,6 @@ def _still_querying(self): return False - def _count(self): - if self._count_valid: - return self._total_results - - while self._still_querying(): - time.sleep(.5) - - if self._timed_out: - raise TimeoutError(message="user-specified timeout exceeded while waiting for results") - - result_url = "/api/investigate/v2/orgs/{}/processes/summary_jobs/{}/results".format( - self._cb.credentials.org_key, - self._query_token, - ) - result = self._cb.get_object(result_url) - - self._total_results = result.get('num_available', 0) - self._count_valid = True - - return self._total_results - def _search(self, start=0, rows=0): """Execute the query, with one expected result.""" if not self._query_token: diff --git a/src/tests/unit/fixtures/platform/mock_process.py b/src/tests/unit/fixtures/platform/mock_process.py index ad0b3171c..7523e46d1 100644 --- a/src/tests/unit/fixtures/platform/mock_process.py +++ b/src/tests/unit/fixtures/platform/mock_process.py @@ -100,6 +100,22 @@ "completed": 45 } +GET_PROCESS_SEARCH_JOB_RESULTS_RESP_ZERO = { + "results": [], + "num_found": 616, + "num_available": 1, + "contacted": 0, + "completed": 0 +} + +GET_PROCESS_SEARCH_JOB_RESULTS_RESP_STILL_QUERYING = { + "results": [], + "num_found": 616, + "num_available": 1, + "contacted": 10, + "completed": 0 +} + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_1 = { "results": [ { @@ -172,6 +188,146 @@ "completed": 45 } +GET_PROCESS_SEARCH_JOB_RESULTS_RESP_NO_PARENT_GUID = { + "results": [ + { + "backend_timestamp": "2020-09-11T19:35:02.972Z", + "childproc_count": 0, + "crossproc_count": 787, + "device_external_ip": "192.168.0.1", + "device_group_id": 0, + "device_id": 1234567, + "device_internal_ip": "192.168.0.2", + "device_name": "Windows10Device", + "device_os": "WINDOWS", + "device_policy_id": 12345, + "device_timestamp": "2020-09-11T19:32:12.821Z", + "enriched": True, + "enriched_event_type": [ + "INJECT_CODE", + "SYSTEM_API_CALL" + ], + "event_type": [ + "crossproc" + ], + "filemod_count": 0, + "ingress_time": 1599852859660, + "legacy": True, + "modload_count": 1, + "netconn_count": 0, + "org_id": "test", + "parent_hash": [ + "9090e0e44e14709fb09b23b98572e0e61c810189e2de8f7156021bc81c3b1bb6", + "bccc12eb2ef644e662a63a023fb83f9b" + ], + "parent_name": "c:\\windows\\system32\\services.exe", + "parent_pid": 644, + "process_cmdline": [ + "\"C:\\Program Files\\VMware\\VMware Tools\\vmtoolsd.exe\"" + ], + "process_effective_reputation": "TRUSTED_WHITE_LIST", + "process_guid": "test-003513bc-00000001-00000000-1d640200c9a61d7", + "process_hash": [ + "f2c7d894abe8ac0b4c2a597caa6b3efe7ad2bdb4226845798d954c5ab9c9bf15", + "12384336325dc8eadfb1e8ff876921c4" + ], + "process_name": "c:\\program files\\vmware\\vmware tools\\vmtoolsd.exe", + "process_pid": [ + 3909 + ], + "process_reputation": "TRUSTED_WHITE_LIST", + "process_username": [ + "Username" + ], + "regmod_count": 1, + "scriptload_count": 0, + "ttp": [ + "ENUMERATE_PROCESSES", + "INJECT_CODE", + "MITRE_T1003_CREDENTIAL_DUMP", + "MITRE_T1005_DATA_FROM_LOCAL_SYS", + "MITRE_T1055_PROCESS_INJECT", + "MITRE_T1057_PROCESS_DISCOVERY", + "RAM_SCRAPING", + "READ_SECURITY_DATA" + ] + } + ], + "num_found": 6168, + "num_available": 1, + "contacted": 45, + "completed": 45 +} + +GET_PROCESS_SEARCH_JOB_RESULTS_RESP_NO_PID = { + "results": [ + { + "backend_timestamp": "2020-09-11T19:35:02.972Z", + "childproc_count": 0, + "crossproc_count": 787, + "device_external_ip": "192.168.0.1", + "device_group_id": 0, + "device_id": 1234567, + "device_internal_ip": "192.168.0.2", + "device_name": "Windows10Device", + "device_os": "WINDOWS", + "device_policy_id": 12345, + "device_timestamp": "2020-09-11T19:32:12.821Z", + "enriched": True, + "enriched_event_type": [ + "INJECT_CODE", + "SYSTEM_API_CALL" + ], + "event_type": [ + "crossproc" + ], + "filemod_count": 0, + "ingress_time": 1599852859660, + "legacy": True, + "modload_count": 1, + "netconn_count": 0, + "org_id": "test", + "parent_guid": "test-0034d5f2-00000284-00000000-1d687097e9cf7b5", + "parent_hash": [ + "9090e0e44e14709fb09b23b98572e0e61c810189e2de8f7156021bc81c3b1bb6", + "bccc12eb2ef644e662a63a023fb83f9b" + ], + "parent_name": "c:\\windows\\system32\\services.exe", + "parent_pid": 644, + "process_cmdline": [ + "\"C:\\Program Files\\VMware\\VMware Tools\\vmtoolsd.exe\"" + ], + "process_effective_reputation": "TRUSTED_WHITE_LIST", + "process_guid": "test-003513bc-00000001-00000000-1d640200c9a61d7", + "process_hash": [ + "f2c7d894abe8ac0b4c2a597caa6b3efe7ad2bdb4226845798d954c5ab9c9bf15", + "12384336325dc8eadfb1e8ff876921c4" + ], + "process_name": "c:\\program files\\vmware\\vmware tools\\vmtoolsd.exe", + "process_reputation": "TRUSTED_WHITE_LIST", + "process_username": [ + "Username" + ], + "regmod_count": 1, + "scriptload_count": 0, + "ttp": [ + "ENUMERATE_PROCESSES", + "INJECT_CODE", + "MITRE_T1003_CREDENTIAL_DUMP", + "MITRE_T1005_DATA_FROM_LOCAL_SYS", + "MITRE_T1055_PROCESS_INJECT", + "MITRE_T1057_PROCESS_DISCOVERY", + "RAM_SCRAPING", + "READ_SECURITY_DATA" + ] + } + ], + "num_found": 6168, + "num_available": 1, + "contacted": 45, + "completed": 45 +} + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_2 = { "results": [ { @@ -553,31 +709,309 @@ "9520a99e77d6196d0d09833146424113", "dd191a5b23df92e12a8852291f9fb5ed594b76a28a5a464418442584afd1e048" ], - "parent_name": "c:\\windows\\system32\\svchost.exe", - "parent_pid": 2924, + "parent_name": "c:\\windows\\system32\\svchost.exe", + "parent_pid": 2924, + "process_cmdline": [ + "\"C:\\Program Files\\Windows Defender\\mpcmdrun.exe\" -wdenable" + ], + "process_effective_reputation": "TRUSTED_WHITE_LIST", + "process_guid": "WNEXFKQ7-00050603-00001d78-00000000-1d6c86e4f3c4a8f", + "process_hash": [ + "cc4f6cbde75f08afdcefb95087149a5d", + "885557be148de55f6a127ea26ac457b9415e3e3baf30266d82b9d19b89e78ee4" + ], + "process_name": "c:\\program files\\windows defender\\mpcmdrun.exe", + "process_pid": [ + 7544 + ], + "process_reputation": "TRUSTED_WHITE_LIST", + "process_start_time": "2020-12-02T05:45:15.531Z", + "process_terminated": True, + "process_username": [ + "NT AUTHORITY\\LOCAL SERVICE" + ], + "regmod_count": 0, + "scriptload_count": 0 + } + ], + "parent": { + "_process_filename": "systemd", + "backend_timestamp": "2020-08-28T19:12:07.989Z", + "childproc_count": 0, + "crossproc_count": 0, + "device_external_ip": "34.56.78.90", + "device_group_id": 0, + "device_id": 176678, + "device_name": "devr-dev", + "device_os": "LINUX", + "device_policy": "sm-restrictive", + "device_policy_id": 11200, + "device_timestamp": "2020-08-28T19:10:02.123Z", + "filemod_count": 0, + "has_children": True, + "hits": False, + "ingress_time": 1598641901273, + "modload_count": 0, + "netconn_count": 0, + "org_id": "ABCD1234", + "process_effective_reputation": "NOT_LISTED", + "process_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "process_hash": [ + "e4b9902024ac32b3ca37f6b4c9b841e8", + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85" + ], + "process_name": "/usr/lib/systemd/systemd", + "process_pid": [ + 1 + ], + "process_reputation": "NOT_LISTED", + "process_start_time": "2020-05-04T21:34:03.968Z", + "regmod_count": 0, + "scriptload_count": 0 + }, + "process": { + "_process_filename": "bash", + "backend_timestamp": "2020-08-28T19:16:11.959Z", + "childproc_count": 333580, + "crossproc_count": 0, + "device_external_ip": "34.56.78.90", + "device_group_id": 0, + "device_id": 176678, + "device_name": "devr-dev", + "device_os": "LINUX", + "device_policy": "sm-restrictive", + "device_policy_id": 11200, + "device_timestamp": "2020-08-28T19:14:41.231Z", + "filemod_count": 0, + "ingress_time": 1598642141411, + "modload_count": 0, + "netconn_count": 0, + "org_id": "ABCD1234", + "parent_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "parent_hash": [ + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85", + "e4b9902024ac32b3ca37f6b4c9b841e8" + ], + "parent_name": "/usr/lib/systemd/systemd", + "parent_pid": 1, + "process_cmdline": [ + "/bin/bash /usr/sbin/ksmtuned" + ], + "process_effective_reputation": "NOT_LISTED", + "process_guid": "ABCD1234-0002b226-00001615-00000000-1d6225bbba75e5e", + "process_hash": [ + "c7084336325dc8eadfb1e8ff876921c4", + "5920199e4fbfa47c1717b863814722148a353e54f8c10912cf1f991a1c86309d" + ], + "process_name": "/usr/bin/bash", + "process_pid": [ + 5653, + 16139 + ], + "process_reputation": "NOT_LISTED", + "process_start_time": "2020-05-04T21:34:03.968Z", + "process_username": [ + "root" + ], + "regmod_count": 0, + "scriptload_count": 0 + }, + "siblings": [ + { + "_process_filename": "nm-dispatcher", + "backend_timestamp": "2020-08-19T20:55:33.446Z", + "childproc_count": 1, + "crossproc_count": 0, + "device_external_ip": "34.56.78.90", + "device_group_id": 0, + "device_id": 176678, + "device_name": "devr-dev", + "device_os": "LINUX", + "device_policy": "sm-restrictive", + "device_policy_id": 11200, + "device_timestamp": "2020-08-19T20:54:44.980Z", + "filemod_count": 0, + "has_children": True, + "hits": False, + "ingress_time": 1597870506825, + "modload_count": 0, + "netconn_count": 0, + "org_id": "ABCD1234", + "parent_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "parent_hash": [ + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85", + "e4b9902024ac32b3ca37f6b4c9b841e8" + ], + "parent_name": "/usr/lib/systemd/systemd", + "parent_pid": 1, + "process_cmdline": [ + "/usr/libexec/nm-dispatcher" + ], + "process_effective_reputation": "NOT_LISTED", + "process_guid": "ABCD1234-0002b226-00005742-00000000-1d6766af7bedb39", + "process_hash": [ + "04b2450579a663c964f3960cd0cf93a8", + "2206d95e0a435aadad6c84b5bce370d076137efecf6adbbf6feddbe0515fb17e" + ], + "process_name": "/usr/libexec/nm-dispatcher", + "process_pid": [ + 22338 + ], + "process_reputation": "NOT_LISTED", + "process_start_time": "2020-08-19T20:54:44.909Z", + "process_username": [ + "root" + ], + "regmod_count": 0, + "scriptload_count": 0 + } + ] + } +} + +GET_PROCESS_SUMMARY_RESP_NO_PID = { + "completed": 30, + "contacted": 30, + "exception": "", + "summary": { + "children": [], + "parent": { + "_process_filename": "systemd", + "backend_timestamp": "2020-08-28T19:12:07.989Z", + "childproc_count": 0, + "crossproc_count": 0, + "device_external_ip": "34.56.78.90", + "device_group_id": 0, + "device_id": 176678, + "device_name": "devr-dev", + "device_os": "LINUX", + "device_policy": "sm-restrictive", + "device_policy_id": 11200, + "device_timestamp": "2020-08-28T19:10:02.123Z", + "filemod_count": 0, + "has_children": True, + "hits": False, + "ingress_time": 1598641901273, + "modload_count": 0, + "netconn_count": 0, + "org_id": "ABCD1234", + "process_effective_reputation": "NOT_LISTED", + "process_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "process_hash": [ + "e4b9902024ac32b3ca37f6b4c9b841e8", + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85" + ], + "process_name": "/usr/lib/systemd/systemd", + "process_pid": [ + 1 + ], + "process_reputation": "NOT_LISTED", + "process_start_time": "2020-05-04T21:34:03.968Z", + "regmod_count": 0, + "scriptload_count": 0 + }, + "process": { + "_process_filename": "bash", + "backend_timestamp": "2020-08-28T19:16:11.959Z", + "childproc_count": 333580, + "crossproc_count": 0, + "device_external_ip": "34.56.78.90", + "device_group_id": 0, + "device_id": 176678, + "device_name": "devr-dev", + "device_os": "LINUX", + "device_policy": "sm-restrictive", + "device_policy_id": 11200, + "device_timestamp": "2020-08-28T19:14:41.231Z", + "filemod_count": 0, + "ingress_time": 1598642141411, + "modload_count": 0, + "netconn_count": 0, + "org_id": "ABCD1234", + "parent_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "parent_hash": [ + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85", + "e4b9902024ac32b3ca37f6b4c9b841e8" + ], + "parent_name": "/usr/lib/systemd/systemd", + "parent_pid": 1, + "process_cmdline": [ + "/bin/bash /usr/sbin/ksmtuned" + ], + "process_effective_reputation": "NOT_LISTED", + "process_guid": "ABCD1234-0002b226-00001615-00000000-1d6225bbba75e5e", + "process_hash": [ + "c7084336325dc8eadfb1e8ff876921c4", + "5920199e4fbfa47c1717b863814722148a353e54f8c10912cf1f991a1c86309d" + ], + "process_name": "/usr/bin/bash", + "process_reputation": "NOT_LISTED", + "process_start_time": "2020-05-04T21:34:03.968Z", + "process_username": [ + "root" + ], + "regmod_count": 0, + "scriptload_count": 0 + }, + "siblings": [ + { + "_process_filename": "nm-dispatcher", + "backend_timestamp": "2020-08-19T20:55:33.446Z", + "childproc_count": 1, + "crossproc_count": 0, + "device_external_ip": "34.56.78.90", + "device_group_id": 0, + "device_id": 176678, + "device_name": "devr-dev", + "device_os": "LINUX", + "device_policy": "sm-restrictive", + "device_policy_id": 11200, + "device_timestamp": "2020-08-19T20:54:44.980Z", + "filemod_count": 0, + "has_children": True, + "hits": False, + "ingress_time": 1597870506825, + "modload_count": 0, + "netconn_count": 0, + "org_id": "ABCD1234", + "parent_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "parent_hash": [ + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85", + "e4b9902024ac32b3ca37f6b4c9b841e8" + ], + "parent_name": "/usr/lib/systemd/systemd", + "parent_pid": 1, "process_cmdline": [ - "\"C:\\Program Files\\Windows Defender\\mpcmdrun.exe\" -wdenable" + "/usr/libexec/nm-dispatcher" ], - "process_effective_reputation": "TRUSTED_WHITE_LIST", - "process_guid": "WNEXFKQ7-00050603-00001d78-00000000-1d6c86e4f3c4a8f", + "process_effective_reputation": "NOT_LISTED", + "process_guid": "ABCD1234-0002b226-00005742-00000000-1d6766af7bedb39", "process_hash": [ - "cc4f6cbde75f08afdcefb95087149a5d", - "885557be148de55f6a127ea26ac457b9415e3e3baf30266d82b9d19b89e78ee4" + "04b2450579a663c964f3960cd0cf93a8", + "2206d95e0a435aadad6c84b5bce370d076137efecf6adbbf6feddbe0515fb17e" ], - "process_name": "c:\\program files\\windows defender\\mpcmdrun.exe", + "process_name": "/usr/libexec/nm-dispatcher", "process_pid": [ - 7544 + 22338 ], - "process_reputation": "TRUSTED_WHITE_LIST", - "process_start_time": "2020-12-02T05:45:15.531Z", - "process_terminated": True, + "process_reputation": "NOT_LISTED", + "process_start_time": "2020-08-19T20:54:44.909Z", "process_username": [ - "NT AUTHORITY\\LOCAL SERVICE" + "root" ], "regmod_count": 0, "scriptload_count": 0 } - ], + ] + } +} + +GET_PROCESS_SUMMARY_RESP_NO_HASH = { + "completed": 30, + "contacted": 30, + "exception": "", + "summary": { + "children": [], "parent": { "_process_filename": "systemd", "backend_timestamp": "2020-08-28T19:12:07.989Z", @@ -643,10 +1077,6 @@ ], "process_effective_reputation": "NOT_LISTED", "process_guid": "ABCD1234-0002b226-00001615-00000000-1d6225bbba75e5e", - "process_hash": [ - "c7084336325dc8eadfb1e8ff876921c4", - "5920199e4fbfa47c1717b863814722148a353e54f8c10912cf1f991a1c86309d" - ], "process_name": "/usr/bin/bash", "process_pid": [ 5653, @@ -713,6 +1143,20 @@ } } +GET_PROCESS_SUMMARY_RESP_ZERO_CONTACTED = { + "completed": 0, + "contacted": 0, + "exception": "", + "summary": {} +} + +GET_PROCESS_SUMMARY_RESP_STILL_QUERYING = { + "completed": 5, + "contacted": 10, + "exception": "", + "summary": {} +} + GET_PROCESS_SUMMARY_RESP_1 = { "exception": "", "summary": { @@ -1284,6 +1728,214 @@ "completed": 34 } +GET_PROCESS_SUMMARY_RESP_NO_CHILDREN = { + "exception": "", + "summary": { + "process": { + "_process_filename": "svchost.exe", + "backend_timestamp": "2020-12-03T20:34:38.889Z", + "childproc_count": 3, + "crossproc_count": 40, + "device_external_ip": "24.243.76.124", + "device_group_id": 0, + "device_id": 329219, + "device_internal_ip": "172.16.115.191", + "device_name": "desktop-8qonquj", + "device_os": "WINDOWS", + "device_policy": "default", + "device_policy_id": 2198, + "device_timestamp": "2020-12-03T20:32:20.912Z", + "filemod_count": 0, + "has_children": True, + "hits": False, + "ingress_time": 1607027652665, + "modload_count": 101, + "netconn_count": 0, + "org_id": "WNEXFKQ7", + "parent_guid": "WNEXFKQ7-00050603-00000270-00000000-1d6c86e280fbff8", + "parent_hash": [ + "1b6ffe1f5480675fc618b42247ef49a1c60ca99d2d53271b3472557e3bea2e8a", + "2bd115a27b60b74bbeb31013519ac199" + ], + "parent_name": "c:\\windows\\system32\\services.exe", + "parent_pid": 624, + "process_cmdline": [ + "C:\\Windows\\System32\\svchost.exe -k LocalServiceNetworkRestricted -p -s wscsvc" + ], + "process_effective_reputation": "TRUSTED_WHITE_LIST", + "process_guid": "WNEXFKQ7-00050603-00000b6c-00000000-1d6c86e29731218", + "process_hash": [ + "45684336325dc8eadfb1e8ff876921c4", + "dd191a5b23df92e12a8852291f9fb5ed594b76a28a5a464418442584afd1e048" + ], + "process_name": "c:\\windows\\system32\\svchost.exe", + "process_pid": [ + 788 + ], + "process_reputation": "TRUSTED_WHITE_LIST", + "process_start_time": "2020-12-02T05:44:12.137Z", + "process_username": [ + "NT AUTHORITY\\LOCAL SERVICE" + ], + "regmod_count": 5, + "scriptload_count": 0 + }, + "siblings": [ + { + "_process_filename": "spoolsv.exe", + "backend_timestamp": "2020-12-03T20:34:38.889Z", + "childproc_count": 2, + "crossproc_count": 35, + "device_external_ip": "24.243.76.124", + "device_group_id": 0, + "device_id": 329219, + "device_internal_ip": "172.16.115.191", + "device_name": "desktop-8qonquj", + "device_os": "WINDOWS", + "device_policy": "default", + "device_policy_id": 2198, + "device_timestamp": "2020-12-03T20:32:18.693Z", + "filemod_count": 405, + "has_children": True, + "hits": False, + "ingress_time": 1607027652665, + "modload_count": 382, + "netconn_count": 0, + "org_id": "WNEXFKQ7", + "parent_guid": "WNEXFKQ7-00050603-00000270-00000000-1d6c86e280fbff8", + "parent_hash": [ + "1b6ffe1f5480675fc618b42247ef49a1c60ca99d2d53271b3472557e3bea2e8a", + "2bd115a27b60b74bbeb31013519ac199" + ], + "parent_name": "c:\\windows\\system32\\services.exe", + "parent_pid": 624, + "process_cmdline": [ + "C:\\Windows\\System32\\spoolsv.exe" + ], + "process_effective_reputation": "LOCAL_WHITE", + "process_guid": "WNEXFKQ7-00050603-00000944-00000000-1d6c86e29169d10", + "process_hash": [ + "94170797d822cd195f8f92da9def082f", + "f45ca80e151494a7394dcd1958ee94c0b83fe3f7b9e281fa1e626e71ff6c2604" + ], + "process_name": "c:\\windows\\system32\\spoolsv.exe", + "process_pid": [ + 2372 + ], + "process_reputation": "COMMON_WHITE_LIST", + "process_start_time": "2020-12-02T05:44:11.531Z", + "process_username": [ + "NT AUTHORITY\\SYSTEM" + ], + "regmod_count": 445, + "scriptload_count": 0 + }, + { + "_process_filename": "wmiapsrv.exe", + "backend_timestamp": "2020-12-02T06:00:54.384Z", + "childproc_count": 0, + "crossproc_count": 3, + "device_external_ip": "24.243.76.124", + "device_group": "schumaker-test", + "device_group_id": 1706, + "device_id": 329219, + "device_internal_ip": "172.16.115.191", + "device_name": "desktop-8qonquj", + "device_os": "WINDOWS", + "device_policy": "default", + "device_policy_id": 2198, + "device_timestamp": "2020-12-02T05:46:50.369Z", + "filemod_count": 0, + "has_children": False, + "ingress_time": 1606888837162, + "modload_count": 21, + "netconn_count": 0, + "org_id": "WNEXFKQ7", + "parent_guid": "WNEXFKQ7-00050603-00000270-00000000-1d6c86e280fbff8", + "parent_hash": [ + "1b6ffe1f5480675fc618b42247ef49a1c60ca99d2d53271b3472557e3bea2e8a", + "2bd115a27b60b74bbeb31013519ac199" + ], + "parent_name": "c:\\windows\\system32\\services.exe", + "parent_pid": 624, + "process_cmdline": [ + "C:\\Windows\\system32\\wbem\\WmiApSrv.exe" + ], + "process_effective_reputation": "LOCAL_WHITE", + "process_guid": "WNEXFKQ7-00050603-000020f8-00000000-1d6c86e87b1e2be", + "process_hash": [ + "55e21dfb7ec2394903e5ca62fdca21e6", + "55c2021f06d28696843672ff90e242c33c4cf6d30cdf0b2d9dcf07d8282cfc19" + ], + "process_name": "c:\\windows\\system32\\wbem\\wmiapsrv.exe", + "process_pid": [ + 8440 + ], + "process_reputation": "ADAPTIVE_WHITE_LIST", + "process_start_time": "2020-12-02T05:46:50.254Z", + "process_terminated": True, + "process_username": [ + "NT AUTHORITY\\SYSTEM" + ], + "regmod_count": 1, + "scriptload_count": 0 + } + ], + "parent": { + "_process_filename": "services.exe", + "backend_timestamp": "2020-12-03T20:34:38.889Z", + "childproc_count": 243, + "crossproc_count": 39, + "device_external_ip": "24.243.76.124", + "device_group_id": 0, + "device_id": 329219, + "device_internal_ip": "172.16.115.191", + "device_name": "desktop-8qonquj", + "device_os": "WINDOWS", + "device_policy": "default", + "device_policy_id": 2198, + "device_timestamp": "2020-12-03T20:32:13.397Z", + "filemod_count": 0, + "has_children": True, + "hits": False, + "ingress_time": 1607027652665, + "modload_count": 53, + "netconn_count": 0, + "org_id": "WNEXFKQ7", + "parent_guid": "WNEXFKQ7-00050603-000001fc-00000000-1d6c86e2801246d", + "parent_hash": [ + "d5e122606054fa0b03db3ee8cf9ea7701e523875e2bdb87581ad7232ffc9308e", + "e83650f70459a027aa596e1a73c961a1" + ], + "parent_name": "c:\\windows\\system32\\wininit.exe", + "parent_pid": 508, + "process_cmdline": [ + "C:\\Windows\\system32\\services.exe" + ], + "process_effective_reputation": "TRUSTED_WHITE_LIST", + "process_guid": "WNEXFKQ7-00050603-00000270-00000000-1d6c86e280fbff8", + "process_hash": [ + "2bd115a27b60b74bbeb31013519ac199", + "1b6ffe1f5480675fc618b42247ef49a1c60ca99d2d53271b3472557e3bea2e8a" + ], + "process_name": "c:\\windows\\system32\\services.exe", + "process_pid": [ + 624 + ], + "process_reputation": "TRUSTED_WHITE_LIST", + "process_start_time": "2020-12-02T05:44:09.808Z", + "process_username": [ + "NT AUTHORITY\\SYSTEM" + ], + "regmod_count": 254, + "scriptload_count": 0 + }, + "children": None + }, + "contacted": 34, + "completed": 34 +} + GET_TREE_RESP = { "exception": "", "summary": { diff --git a/src/tests/unit/platform/test_platform_process.py b/src/tests/unit/platform/test_platform_process.py index c9cb8ee94..0b02249ed 100644 --- a/src/tests/unit/platform/test_platform_process.py +++ b/src/tests/unit/platform/test_platform_process.py @@ -10,6 +10,11 @@ from tests.unit.fixtures.platform.mock_process import (GET_PROCESS_SUMMARY_RESP, GET_PROCESS_SUMMARY_RESP_1, GET_PROCESS_SUMMARY_RESP_2, + GET_PROCESS_SUMMARY_RESP_NO_CHILDREN, + GET_PROCESS_SUMMARY_RESP_STILL_QUERYING, + GET_PROCESS_SUMMARY_RESP_ZERO_CONTACTED, + GET_PROCESS_SUMMARY_RESP_NO_HASH, + GET_PROCESS_SUMMARY_RESP_NO_PID, GET_TREE_RESP, GET_PROCESS_VALIDATION_RESP, POST_PROCESS_SEARCH_JOB_RESP, @@ -22,6 +27,10 @@ GET_PROCESS_SEARCH_JOB_RESULTS_RESP_1, GET_PROCESS_SEARCH_JOB_RESULTS_RESP_2, GET_PROCESS_SEARCH_JOB_RESULTS_RESP_3, + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_ZERO, + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_STILL_QUERYING, + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_NO_PID, + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_NO_PARENT_GUID, GET_PROCESS_SEARCH_PARENT_JOB_RESULTS_RESP, GET_PROCESS_SEARCH_PARENT_JOB_RESULTS_RESP_1, GET_FACET_SEARCH_RESULTS_RESP, @@ -86,10 +95,119 @@ def test_process_select(cbcsdk_mock): def test_summary_select(cbcsdk_mock): """Test querying for a Proc Summary.""" + # mock the POST of a summary search (using same Job ID) + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/summary_jobs", + POST_PROCESS_SEARCH_JOB_RESP) + # mock the GET to check summary search status + cbcsdk_mock.mock_request("GET", ("/api/investigate/v2/orgs/test/processes/" + "summary_jobs/2c292717-80ed-4f0d-845f-779e09470920"), + GET_PROCESS_SUMMARY_RESP) + # mock the GET to get summary search results + cbcsdk_mock.mock_request("GET", ("/api/investigate/v2/orgs/test/processes/" + "summary_jobs/2c292717-80ed-4f0d-845f-779e09470920/results"), + GET_PROCESS_SUMMARY_RESP) + api = cbcsdk_mock.api + guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' + summary = api.select(Process.Summary).where(f"process_guid:{guid}") + assert summary._perform_query() is not None + assert isinstance(summary, SummaryQuery) + summary._query_token = None + summary._still_querying() + + +def test_summary_select_failures(cbcsdk_mock): + """Test querying for a Proc Summary.""" + # mock the POST of a summary search (using same Job ID) + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/summary_jobs", + POST_PROCESS_SEARCH_JOB_RESP) + # mock the GET to check summary search status + cbcsdk_mock.mock_request("GET", ("/api/investigate/v2/orgs/test/processes/" + "summary_jobs/2c292717-80ed-4f0d-845f-779e09470920"), + GET_PROCESS_SUMMARY_RESP) + # mock the GET to get summary search results + cbcsdk_mock.mock_request("GET", ("/api/investigate/v2/orgs/test/processes/" + "summary_jobs/2c292717-80ed-4f0d-845f-779e09470920/results"), + GET_PROCESS_SUMMARY_RESP) + api = cbcsdk_mock.api + guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' + summary = api.select(Process.Summary).where(f"process_guid:{guid}") + assert isinstance(summary, SummaryQuery) + summary._query_token = 'something' + with pytest.raises(ApiError) as ex: + summary._submit() + assert 'Query already submitted:' in ex.value.message + summary._query_token = None + with pytest.raises(ApiError) as ex: + summary._run_async_query('someother') + assert ex.value.message == 'Async query not properly started' + + +def test_summary_still_querying_zero(cbcsdk_mock): + """Testing edge cases for _still_querying""" + # mock the POST of a summary search (using same Job ID) + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/summary_jobs", + POST_PROCESS_SEARCH_JOB_RESP) + # mock the GET to check summary search status + cbcsdk_mock.mock_request("GET", ("/api/investigate/v2/orgs/test/processes/" + "summary_jobs/2c292717-80ed-4f0d-845f-779e09470920"), + GET_PROCESS_SUMMARY_RESP_ZERO_CONTACTED) + api = cbcsdk_mock.api + guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' + summary = api.select(Process.Summary).where(f"process_guid:{guid}") + assert summary._still_querying() is True + + +def test_summary_still_querying(cbcsdk_mock): + """Testing edge cases for _still_querying""" + # mock the POST of a summary search (using same Job ID) + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/summary_jobs", + POST_PROCESS_SEARCH_JOB_RESP) + # mock the GET to check summary search status + cbcsdk_mock.mock_request("GET", ("/api/investigate/v2/orgs/test/processes/" + "summary_jobs/2c292717-80ed-4f0d-845f-779e09470920"), + GET_PROCESS_SUMMARY_RESP_STILL_QUERYING) api = cbcsdk_mock.api guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' summary = api.select(Process.Summary).where(f"process_guid:{guid}") + assert summary._still_querying() is True + summary._search() + summary._timed_out = True + summary._search() + + +def test_summary_select_set_time_range(cbcsdk_mock): + """Test set_time_range for a Process Summary.""" + api = cbcsdk_mock.api + guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' + summary = api.select(Process.Summary).where(f"process_guid:{guid}").where(f"parent_guid:{guid}") assert isinstance(summary, SummaryQuery) + summary = summary.set_time_range(start="2020-01-21T18:34:04Z") + summary = summary.set_time_range(end="2020-02-21T18:34:04Z") + summary = summary.set_time_range(window="-1w") + summary.timeout(1000) + query_params = summary._get_query_parameters() + expected = {'time_range': {'start': '2020-01-21T18:34:04Z', 'end': '2020-02-21T18:34:04Z', 'window': '-1w'}, + 'process_guid': 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00', + 'parent_guid': 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00'} + + assert query_params == expected + + +def test_summary_select_set_time_range_failures(cbcsdk_mock): + """Test set_time_range failures for a Process Summary.""" + api = cbcsdk_mock.api + guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' + summary = api.select(Process.Summary).where(f"process_guid:{guid}") + + with pytest.raises(ApiError) as ex: + summary.set_time_range(start=50) + assert 'Start time must be a string in ISO 8601 format.' in ex.value.message + with pytest.raises(ApiError) as ex: + summary.set_time_range(end=60) + assert 'End time must be a string in ISO 8601 format.' in ex.value.message + with pytest.raises(ApiError) as ex: + summary.set_time_range(window=20) + assert 'Window must be a string.' in ex.value.message def test_process_events(cbcsdk_mock): @@ -207,6 +325,7 @@ def test_process_with_criteria_exclusions(cbcsdk_mock): # use the update methods process = api.select(Process).where("event_type:modload").add_criteria("device_id", [1234]).add_exclusions( "crossproc_effective_reputation", ["REP_WHITE"]) + process.timeout(1000) # mock the search validation cbcsdk_mock.mock_request("GET", "/api/investigate/v1/orgs/test/processes/search_validation", GET_PROCESS_VALIDATION_RESP) @@ -558,7 +677,9 @@ def test_process_sort_by(cbcsdk_mock): (GET_PROCESS_SUMMARY_RESP_1, "test-00340b06-00000314-00000000-1d686b9e4d74f52", GET_PROCESS_SEARCH_PARENT_JOB_RESULTS_RESP_1, False), (GET_PROCESS_SUMMARY_RESP_2, "test-003513bc-0000035c-00000000-1d640200c9a6205", - GET_PROCESS_SEARCH_JOB_RESULTS_RESP_1, True) + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_1, True), + (GET_PROCESS_SUMMARY_RESP_2, "WNEXFKQ7-00050603-00000270-00000000-1d6c86e280fbff8", + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_NO_PARENT_GUID, True) ]) def test_process_parents(cbcsdk_mock, get_summary_response, guid, process_search_results, has_parent_process): """Testing Process.parents property/method.""" @@ -613,7 +734,8 @@ def test_process_parents(cbcsdk_mock, get_summary_response, guid, process_search @pytest.mark.parametrize('get_summary_response, guid, expected_num_children', [ (GET_PROCESS_SUMMARY_RESP, "test-0002b226-000015bd-00000000-1d6225bbba74c00", 2), (GET_PROCESS_SUMMARY_RESP_1, "test-00340b06-00000314-00000000-1d686b9e4d74f52", 3), - (GET_PROCESS_SUMMARY_RESP_2, "test-003513bc-0000035c-00000000-1d640200c9a6205", 2)]) + (GET_PROCESS_SUMMARY_RESP_2, "test-003513bc-0000035c-00000000-1d640200c9a6205", 2), + (GET_PROCESS_SUMMARY_RESP_NO_CHILDREN, "test-003513bc-0000035c-00000000-1d640200c9a6205", 0)]) def test_process_children(cbcsdk_mock, get_summary_response, guid, expected_num_children): """Testing Process.children property.""" # mock the search validation @@ -661,7 +783,9 @@ def test_process_children(cbcsdk_mock, get_summary_response, guid, expected_num_ "12384336325dc8eadfb1e8ff876921c4"), (GET_PROCESS_SEARCH_JOB_RESULTS_RESP_3, GET_PROCESS_SUMMARY_RESP_2, "test-003513bc-0000035c-00000000-1d640200c9a6205", - "45684336325dc8eadfb1e8ff876921c4")]) + "45684336325dc8eadfb1e8ff876921c4"), + (GET_PROCESS_SEARCH_JOB_RESULTS_RESP_3, GET_PROCESS_SUMMARY_RESP_NO_HASH, + "test-003513bc-0000035c-00000000-1d640200c9a6205", None)]) def test_process_md5(cbcsdk_mock, get_process_search_response, get_summary_response, guid, md5): """Testing Process.process_md5 property.""" # mock the search validation @@ -694,8 +818,10 @@ def test_process_md5(cbcsdk_mock, get_process_search_response, get_summary_respo if "process_hash" in process.summary._info["process"]: md5_hash = next((hash for hash in process.summary._info["process"]["process_hash"] if len(hash) == 32), None) assert process.process_md5 == md5_hash - else: + elif "process_hash" in process._info: assert process.process_md5 == md5 + else: + assert process.process_md5 is None def test_process_md5_not_found(cbcsdk_mock): @@ -729,6 +855,8 @@ def test_process_md5_not_found(cbcsdk_mock): process = api.select(Process, "someNonexistantGuid") with pytest.raises(ApiError): process.summary + with pytest.raises(ApiError): + process.tree @pytest.mark.parametrize('get_process_response, get_summary_response, guid, sha256', [ @@ -740,7 +868,9 @@ def test_process_md5_not_found(cbcsdk_mock): "d5e122606054fa0b03db3ee8cf9ea7701e523875e2bdb87581ad7232ffc9308e"), (GET_PROCESS_SEARCH_JOB_RESULTS_RESP_3, GET_PROCESS_SUMMARY_RESP_2, "test-003513bc-0000035c-00000000-1d640200c9a6205", - "63d423ea882264dbb157a965c200306212fc5e1c6ddb8cbbb0f1d3b51ecd82e6")]) + "63d423ea882264dbb157a965c200306212fc5e1c6ddb8cbbb0f1d3b51ecd82e6"), + (GET_PROCESS_SEARCH_JOB_RESULTS_RESP_3, GET_PROCESS_SUMMARY_RESP_NO_HASH, + "test-003513bc-0000035c-00000000-1d640200c9a6205", None)]) def test_process_sha256(cbcsdk_mock, get_process_response, get_summary_response, guid, sha256): """Testing Process.process_sha256 property.""" # mock the search validation @@ -773,8 +903,10 @@ def test_process_sha256(cbcsdk_mock, get_process_response, get_summary_response, if "process_hash" in process.summary._info["process"]: sha256_hash = next((hash for hash in process.summary._info["process"]["process_hash"] if len(hash) == 64), None) assert process.process_sha256 == sha256_hash - else: + elif "process_hash" in process._info: assert process.process_sha256 == sha256 + else: + assert process.process_sha256 is None @pytest.mark.parametrize('get_process_response, get_summary_response, guid, pids', [ @@ -783,7 +915,11 @@ def test_process_sha256(cbcsdk_mock, get_process_response, get_summary_response, (GET_PROCESS_SEARCH_JOB_RESULTS_RESP_1, GET_PROCESS_SUMMARY_RESP_1, "test-00340b06-00000314-00000000-1d686b9e4d74f52", [3909]), (GET_PROCESS_SEARCH_JOB_RESULTS_RESP_2, GET_PROCESS_SUMMARY_RESP_2, - "test-003513bc-0000035c-00000000-1d640200c9a6205", [788])]) + "test-003513bc-0000035c-00000000-1d640200c9a6205", [788]), + (GET_PROCESS_SEARCH_JOB_RESULTS_RESP_NO_PID, GET_PROCESS_SUMMARY_RESP_2, + "test-003513bc-0000035c-00000000-1d640200c9a6205", [788]), + (GET_PROCESS_SEARCH_JOB_RESULTS_RESP_NO_PID, GET_PROCESS_SUMMARY_RESP_NO_PID, + "test-003513bc-0000035c-00000000-1d640200c9a6205", None)]) def test_process_pids(cbcsdk_mock, get_process_response, get_summary_response, guid, pids): """Testing Process.process_pids property.""" # mock the search validation @@ -820,10 +956,64 @@ def test_process_pids(cbcsdk_mock, get_process_response, get_summary_response, g def test_process_select_where(cbcsdk_mock): """Testing Process querying with where().""" + # mock the search validation + cbcsdk_mock.mock_request("GET", "/api/investigate/v1/orgs/test/processes/search_validation", + GET_PROCESS_VALIDATION_RESP) + # mock the POST of a search + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/search_jobs", + POST_PROCESS_SEARCH_JOB_RESP) + # mock the GET to check search status + cbcsdk_mock.mock_request("GET", ("/api/investigate/v1/orgs/test/processes/" + "search_jobs/2c292717-80ed-4f0d-845f-779e09470920"), + GET_PROCESS_SEARCH_JOB_RESP) + # mock the GET to get search results + cbcsdk_mock.mock_request("GET", ("/api/investigate/v2/orgs/test/processes/search_jobs/" + "2c292717-80ed-4f0d-845f-779e09470920/results"), + GET_PROCESS_SEARCH_JOB_RESULTS_RESP) api = cbcsdk_mock.api guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' process = api.select(Process).where(f"process_guid:{guid}") assert isinstance(process, AsyncProcessQuery) + process._count_valid = True + assert process._count() == 0 + + +def test_process_still_querying(cbcsdk_mock): + """Testing Process""" + # mock the POST of a search + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/search_jobs", + POST_PROCESS_SEARCH_JOB_RESP) + # mock the search validation + cbcsdk_mock.mock_request("GET", "/api/investigate/v1/orgs/test/processes/search_validation", + GET_PROCESS_VALIDATION_RESP) + # mock the GET to check search status + cbcsdk_mock.mock_request("GET", ("/api/investigate/v1/orgs/test/processes/" + "search_jobs/2c292717-80ed-4f0d-845f-779e09470920"), + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_ZERO) + api = cbcsdk_mock.api + guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' + process = api.select(Process).where(f"process_guid:{guid}") + assert isinstance(process, AsyncProcessQuery) + assert process._still_querying() is True + + +def test_process_still_querying_zero(cbcsdk_mock): + """Testing Process""" + # mock the POST of a search + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/search_jobs", + POST_PROCESS_SEARCH_JOB_RESP) + # mock the search validation + cbcsdk_mock.mock_request("GET", "/api/investigate/v1/orgs/test/processes/search_validation", + GET_PROCESS_VALIDATION_RESP) + # mock the GET to check search status + cbcsdk_mock.mock_request("GET", ("/api/investigate/v1/orgs/test/processes/" + "search_jobs/2c292717-80ed-4f0d-845f-779e09470920"), + GET_PROCESS_SEARCH_JOB_RESULTS_RESP_STILL_QUERYING) + api = cbcsdk_mock.api + guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' + process = api.select(Process).where(f"process_guid:{guid}") + assert isinstance(process, AsyncProcessQuery) + assert process._still_querying() is True def test_process_facet_select(cbcsdk_mock): @@ -958,3 +1148,6 @@ def test_tree_select(cbcsdk_mock): assert results is not None assert results.children is not None assert results.device_os is not None + + procTree = api.select(Process.Tree, "WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00") + assert procTree is not None From 9ae170de781cfa0c796a116813ff48f6179e7fac Mon Sep 17 00:00:00 2001 From: Emanuela Mitreva Date: Wed, 10 Mar 2021 17:18:35 +0200 Subject: [PATCH 02/20] CBAPI-2022: Include __str__ methods for tree and summary --- src/cbc_sdk/platform/processes.py | 85 +++++++++++++++++++ .../unit/platform/test_platform_process.py | 2 + 2 files changed, 87 insertions(+) diff --git a/src/cbc_sdk/platform/processes.py b/src/cbc_sdk/platform/processes.py index d3ea5444f..cbb5f97db 100644 --- a/src/cbc_sdk/platform/processes.py +++ b/src/cbc_sdk/platform/processes.py @@ -59,6 +59,15 @@ class Summary(UnrefreshableModel): summary_format = "summary" default_sort = "last_update desc" primary_key = "process_guid" + SHOW_ATTR = {'process': {'type': 'single', 'fields': ['device_id', 'device_name', 'process_name', + 'parent_guid', 'parent_hash', 'parent_name', + 'parent_pid', 'process_hash', 'process_pid']}, + 'siblings': {'type': 'list', 'fields': ['process_name', 'process_guid', 'process_hash', + 'process_pid']}, + 'parent': {'type': 'single', 'fields': ['process_name', 'process_guid', 'process_hash', + 'process_pid']}, + 'children': {'type': 'list', 'fields': ['process_name', 'process_guid', 'process_hash', + 'process_pid']}} def __init__(self, cb, model_unique_id=None, initial_data=None, force_init=False, full_doc=True): """ @@ -77,6 +86,45 @@ def __init__(self, cb, model_unique_id=None, initial_data=None, force_init=False initial_data=initial_data, force_init=False, full_doc=True) + def __str__(self): + """ + Returns a string representation of the object. + + Returns: + str: A string representation of the object. + """ + lines = [] + for top_level in self._info: + if self._info[top_level] and top_level in self.SHOW_ATTR: + if self.SHOW_ATTR[top_level]['type'] == 'single': + lines.append(top_level) + else: + lines.append(f"{top_level} - {len(self._info[top_level])}") + + if self.SHOW_ATTR[top_level]['type'] == 'single': + for attr in self._info[top_level]: + if attr in self.SHOW_ATTR[top_level]['fields']: + try: + val = str(self._info[top_level][attr]) + except UnicodeDecodeError: + val = repr(self._info[top_level][attr]) + if len(val) > 50: + val = val[:47] + u"..." + lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", attr, val)) + else: + for item in self._info[top_level]: + for attr in item: + if attr in self.SHOW_ATTR[top_level]['fields']: + try: + val = str(item[attr]) + except UnicodeDecodeError: + val = repr(item[attr]) + if len(val) > 50: + val = val[:47] + u"..." + lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", attr, val)) + lines.append('') + return "\n".join(lines) + @classmethod def _query_implementation(self, cb, **kwargs): return SummaryQuery(self, cb, **kwargs) @@ -95,6 +143,10 @@ class Tree(UnrefreshableModel): summary_format = 'tree' default_sort = "last_update desc" primary_key = 'process_guid' + SHOW_ATTR = {'top': ['device_id', 'device_name', 'process_name', + 'parent_guid', 'parent_hash', 'parent_name', + 'parent_pid', 'process_hash', 'process_pid'], + 'children': ['process_name', 'process_guid', 'process_hash', 'process_pid']} def __init__(self, cb, model_unique_id=None, initial_data=None, force_init=False, full_doc=True): """ @@ -114,6 +166,39 @@ def __init__(self, cb, model_unique_id=None, initial_data=None, force_init=False force_init=force_init, full_doc=full_doc ) + def __str__(self): + """ + Returns a string representation of the object. + + Returns: + str: A string representation of the object. + """ + lines = [] + lines.append('process') + for attr in self._info: + if attr in self.SHOW_ATTR['top']: + try: + val = str(self._info[attr]) + except UnicodeDecodeError: + val = repr(self._info[attr]) + if len(val) > 50: + val = val[:47] + u"..." + lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", attr, val)) + + lines.append(f"children - {len(self._info['children'])}") + for child in self._info['children']: + for attr in child: + if attr in self.SHOW_ATTR['children']: + try: + val = str(child[attr]) + except UnicodeDecodeError: + val = repr(child[attr]) + if len(val) > 50: + val = val[:47] + u"..." + lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", attr, val)) + lines.append('') + return "\n".join(lines) + @classmethod def _query_implementation(self, cb, **kwargs): return SummaryQuery(self, cb, **kwargs) diff --git a/src/tests/unit/platform/test_platform_process.py b/src/tests/unit/platform/test_platform_process.py index 0b02249ed..0b00fb95d 100644 --- a/src/tests/unit/platform/test_platform_process.py +++ b/src/tests/unit/platform/test_platform_process.py @@ -87,6 +87,7 @@ def test_process_select(cbcsdk_mock): api = cbcsdk_mock.api guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' process = api.select(Process, guid) + process.summary.__str__() assert process.summary is not None assert process.siblings is not None summary = api.select(Process.Summary, guid) @@ -1138,6 +1139,7 @@ def test_tree_select(cbcsdk_mock): guid = "WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00" process = api.select(Process, guid) tree = process.tree + tree.__str__() children = tree.children assert len(children) == len(tree.children) assert len(children) > 0 From 00d3494c644f80de91b8824bf94f9e81b6b7d2d1 Mon Sep 17 00:00:00 2001 From: Emanuela Mitreva Date: Thu, 11 Mar 2021 15:13:54 +0200 Subject: [PATCH 03/20] CBAPI-2022: Fixing a few issues based on Alex's input. --- src/cbc_sdk/platform/processes.py | 3 + .../unit/fixtures/platform/mock_process.py | 283 ++++++++++++++++++ .../unit/platform/test_platform_process.py | 117 +++++++- 3 files changed, 395 insertions(+), 8 deletions(-) diff --git a/src/cbc_sdk/platform/processes.py b/src/cbc_sdk/platform/processes.py index cbb5f97db..fdf0d2956 100644 --- a/src/cbc_sdk/platform/processes.py +++ b/src/cbc_sdk/platform/processes.py @@ -778,6 +778,9 @@ def _get_query_parameters(self): args["parent_guid"] = parent_guid return args + def _count(self): + raise ApiError('The result is not iterable') + def _submit(self): if self._query_token: raise ApiError("Query already submitted: token {0}".format(self._query_token)) diff --git a/src/tests/unit/fixtures/platform/mock_process.py b/src/tests/unit/fixtures/platform/mock_process.py index 7523e46d1..5201c52ed 100644 --- a/src/tests/unit/fixtures/platform/mock_process.py +++ b/src/tests/unit/fixtures/platform/mock_process.py @@ -1728,6 +1728,289 @@ "completed": 34 } +GET_PROCESS_TREE_STR = { + "exception": "", + "tree": { + "children": [ + { + "_process_filename": "msiexec.exe", + "backend_timestamp": "2020-10-15T05:44:47.387Z", + "device_external_ip": "144.121.3.50", + "device_group": "schumaker-test", + "device_group_id": 1706, + "device_id": 199106, + "device_internal_ip": "10.210.161.66", + "device_name": "w10prov1703x86", + "device_os": "WINDOWS", + "device_policy": "default", + "device_policy_id": 2198, + "device_timestamp": "2020-10-15T05:43:45.336Z", + "enriched": True, + "enriched_event_type": "SYSTEM_API_CALL", + "event_type": "crossproc", + "has_children": False, + "ingress_time": 1602740641018, + "legacy": True, + "org_id": "WNEXFKQ7", + "parent_guid": "WNEXFKQ7-000309c2-000002c4-00000000-1d6a1c1f161a86a", + "parent_hash": [ + "bd3036f60f1438c82900a29221e3a4912a89bfe904d01aad70c781ef514df0b3" + ], + "parent_name": "c:\\windows\\system32\\services.exe", + "parent_pid": 708, + "process_cmdline":[ + "C:\\WINDOWS\\system32\\msiexec.exe /V" + ], + "process_effective_reputation": "TRUSTED_WHITE_LIST", + "process_guid": "WNEXFKQ7-000309c2-00000454-00000000-1d6a2b6252ba18e", + "process_hash":[ + "f9a3eee1c3a4067702bc9a59bc894285", + "8e2aa014d7729cbfee95671717646ee480561f22e2147dae87a75c18d7369d99" + ], + "process_name": "c:\\windows\\system32\\msiexec.exe", + "process_pid":[ + 1108 + ], + "process_reputation": "TRUSTED_WHITE_LIST", + "process_start_time": "2020-10-15T05:43:44.537Z", + "process_username": [ + "NT AUTHORITY\\SYSTEM" + ], + "ttp":[ + "ENUMERATE_PROCESSES", + "MITRE_T1057_PROCESS_DISCOVERY" + ] + } + ], + "device_id": 176678, + "device_name": "devr-dev", + "device_os": "LINUX", + "device_policy": "sm-restrictive", + "device_policy_id": 11200, + "device_timestamp": "2020-08-28T19:10:02.123Z", + "filemod_count": 0, + "has_children": True, + "hits": False, + "ingress_time": 1598641901273, + "modload_count": 0, + "netconn_count": 0, + "org_id": "ABCD1234", + "process_effective_reputation": "NOT_LISTED", + "process_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "process_hash": [ + "e4b9902024ac32b3ca37f6b4c9b841e8", + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85" + ], + "process_name": "/usr/lib/systemd/systemd", + "process_pid": [1], + "process_reputation": "NOT_LISTED", + "process_start_time": "2020-05-04T21:34:03.968Z", + "regmod_count": 0, + "scriptload_count": 0 + } +} + +GET_PROCESS_SUMMARY_STR = { + "exception": "", + "summary": { + "process": { + "_process_filename": "svchost.exe", + "backend_timestamp": "2020-10-22T16:27:52.931Z", + "device_external_ip": "144.121.3.50", + "device_group_id": 0, + "device_id": 199106, + "device_internal_ip": "10.210.161.66", + "device_name": "w10prov1703x86", + "device_os": "WINDOWS", + "device_policy": "lyon_test", + "device_policy_id": 30241, + "device_timestamp": "2020-10-22T16:15:05.925Z", + "enriched": True, + "enriched_event_type": "NETWORK", + "event_type": "netconn", + "has_children": True, + "hits": True, + "ingress_time": 1603384040142, + "legacy": True, + "org_id": "WNEXFKQ7", + "parent_guid": "WNEXFKQ7-000309c2-000002c4-00000000-1d6a1c1f161a86a", + "parent_hash": [ + "bd3036f60f1438c82900a29221e3a4912a89bfe904d01aad70c781ef514df0b3" + ], + "parent_name": "c:\\windows\\system32\\services.exe", + "parent_pid": 708, + "process_cmdline": [ + "C:\\WINDOWS\\system32\\svchost.exe -k netsvcs -p" + ], + "process_effective_reputation": "TRUSTED_WHITE_LIST", + "process_guid": "WNEXFKQ7-000309c2-00000478-00000000-1d6a1c1f2b02805", + "process_hash": [ + "a7296c1245ee76768d581c6330dade06", + "5be0de7f915ba819d4ba048db7a2a87f6f3253fdd4865dc418181a0d6a031caa" + ], + "process_name": "c:\\windows\\system32\\svchost.exe", + "process_pid": [ + 1144 + ], + "process_reputation": "TRUSTED_WHITE_LIST", + "process_start_time": "2020-10-14T00:35:42.639Z", + "process_username": [ + "NT AUTHORITY\\SYSTEM" + ], + "sensor_action": [ + "DENY", + "BLOCK" + ], + "ttp": [ + "POLICY_DENY" + ] + }, + "siblings": [ + { + "_process_filename": "cb.exe", + "backend_timestamp": "2020-10-22T16:14:38.964Z", + "device_external_ip": "144.121.3.50", + "device_group_id": 0, + "device_id": 199106, + "device_name": "w10prov1703x86", + "device_os": "WINDOWS", + "device_policy": "lyon_test", + "device_policy_id": 30241, + "device_timestamp": "2020-10-22T16:11:30.514Z", + "enriched": True, + "enriched_event_type": "NETWORK", + "event_type": "netconn", + "has_children": False, + "hits": False, + "ingress_time": 1603383254356, + "legacy": True, + "org_id": "WNEXFKQ7", + "parent_guid": "WNEXFKQ7-000309c2-000002c4-00000000-1d6a1c1f161a86a", + "parent_hash": [ + "bd3036f60f1438c82900a29221e3a4912a89bfe904d01aad70c781ef514df0b3" + ], + "parent_name": "c:\\windows\\system32\\services.exe", + "parent_pid": 708, + "process_cmdline": [ + "C:\\WINDOWS\\CarbonBlack\\cb.exe" + ], + "process_effective_reputation": "TRUSTED_WHITE_LIST", + "process_guid": "WNEXFKQ7-000309c2-00000980-00000000-1d6a1c1f41ae014", + "process_hash": [ + "b5a2c3084251ad5ce53e02f071fa7dc9", + "ae600593a0a6915cf5ecbf96b4cb1d0e1d165339bde136c351bf606127c5dcec" + ], + "process_name": "c:\\windows\\carbonblack\\cb.exe", + "process_pid": [ + 2432 + ], + "process_reputation": "TRUSTED_WHITE_LIST", + "process_start_time": "2020-10-14T00:35:45.017Z", + "process_username": [ + "NT AUTHORITY\\SYSTEM" + ], + "sensor_action": [ + "DENY", + "BLOCK" + ], + "ttp": [ + "POLICY_DENY" + ] + } + ], + "parent": { + "_process_filename": "systemd", + "backend_timestamp": "2020-08-28T19:12:07.989Z", + "childproc_count": 0, + "crossproc_count": 0, + "device_external_ip": "34.56.78.90", + "device_group_id": 0, + "device_id": 176678, + "device_name": "devr-dev", + "device_os": "LINUX", + "device_policy": "sm-restrictive", + "device_policy_id": 11200, + "device_timestamp": "2020-08-28T19:10:02.123Z", + "filemod_count": 0, + "has_children": True, + "hits": False, + "ingress_time": 1598641901273, + "modload_count": 0, + "netconn_count": 0, + "org_id": "ABCD1234", + "process_effective_reputation": "NOT_LISTED", + "process_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "process_hash": [ + "e4b9902024ac32b3ca37f6b4c9b841e8", + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85" + ], + "process_name": "/usr/lib/systemd/systemd", + "process_pid": [ + 1 + ], + "process_reputation": "NOT_LISTED", + "process_start_time": "2020-05-04T21:34:03.968Z", + "regmod_count": 0, + "scriptload_count": 0 + }, + "children": [ + { + "_process_filename": "wermgr.exe", + "backend_timestamp": "2020-10-22T16:28:23.556Z", + "device_external_ip": "144.121.3.50", + "device_group_id": 0, + "device_id": 199106, + "device_internal_ip": "10.210.161.66", + "device_name": "w10prov1703x86", + "device_os": "WINDOWS", + "device_policy": "lyon_test", + "device_policy_id": 30241, + "device_timestamp": "2020-10-22T16:15:06.065Z", + "enriched": True, + "enriched_event_type": "NETWORK", + "event_type": "netconn", + "has_children": False, + "hits": True, + "ingress_time": 1603384060202, + "legacy": True, + "org_id": "WNEXFKQ7", + "parent_guid": "WNEXFKQ7-000309c2-00000478-00000000-1d6a1c1f2b02805", + "parent_hash": [ + "5be0de7f915ba819d4ba048db7a2a87f6f3253fdd4865dc418181a0d6a031caa" + ], + "parent_name": "c:\\windows\\system32\\svchost.exe", + "parent_pid": 1144, + "process_cmdline":[ + "C:\\WINDOWS\\system32\\wermgr.exe -upload" + ], + "process_effective_reputation": "TRUSTED_WHITE_LIST", + "process_guid": "WNEXFKQ7-000309c2-000004f8-00000000-1d6a88e80c541a3", + "process_hash":[ + "2ae75e810f4dd1fb36607f66e7e1d80b", + "db703055ec0641e7e96e22a62bf075547b480c51ea9e163d94e33452894b885c" + ], + "process_name": "c:\\windows\\system32\\wermgr.exe", + "process_pid":[ + 1272 + ], + "process_reputation": "TRUSTED_WHITE_LIST", + "process_start_time": "2020-10-22T16:15:05.324Z", + "process_username":[ + "NT AUTHORITY\\SYSTEM" + ], + "sensor_action":[ + "DENY", + "BLOCK" + ], + "ttp":[ + "POLICY_DENY" + ] + } + ], + "process_guid": "b31019a5-d69b-4aba-b36d-0b29fe2e7f61" + } +} + GET_PROCESS_SUMMARY_RESP_NO_CHILDREN = { "exception": "", "summary": { diff --git a/src/tests/unit/platform/test_platform_process.py b/src/tests/unit/platform/test_platform_process.py index 0b00fb95d..2ada03ea9 100644 --- a/src/tests/unit/platform/test_platform_process.py +++ b/src/tests/unit/platform/test_platform_process.py @@ -15,7 +15,6 @@ GET_PROCESS_SUMMARY_RESP_ZERO_CONTACTED, GET_PROCESS_SUMMARY_RESP_NO_HASH, GET_PROCESS_SUMMARY_RESP_NO_PID, - GET_TREE_RESP, GET_PROCESS_VALIDATION_RESP, POST_PROCESS_SEARCH_JOB_RESP, POST_TREE_SEARCH_JOB_RESP, @@ -35,7 +34,9 @@ GET_PROCESS_SEARCH_PARENT_JOB_RESULTS_RESP_1, GET_FACET_SEARCH_RESULTS_RESP, EXPECTED_PROCESS_FACETS, - EXPECTED_PROCESS_RANGES_FACETS) + EXPECTED_PROCESS_RANGES_FACETS, + GET_PROCESS_TREE_STR, + GET_PROCESS_SUMMARY_STR) log = logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s', level=logging.DEBUG, filename='log.txt') @@ -83,11 +84,75 @@ def test_process_select(cbcsdk_mock): # mock the GET to get summary search results cbcsdk_mock.mock_request("GET", ("/api/investigate/v2/orgs/test/processes/" "summary_jobs/2c292717-80ed-4f0d-845f-779e09470920/results"), - GET_PROCESS_SUMMARY_RESP) + GET_PROCESS_SUMMARY_STR) api = cbcsdk_mock.api guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' process = api.select(Process, guid) - process.summary.__str__() + actual = process.summary.__str__() + + process_info = { + "device_id": 199106, + "device_name": "w10prov1703x86", + "parent_guid": "WNEXFKQ7-000309c2-000002c4-00000000-1d6a1c1f161a86a", + "parent_hash": [ + "bd3036f60f1438c82900a29221e3a4912a89bfe904d01aad70c781ef514df0b3" + ], + "parent_name": "c:\\windows\\system32\\services.exe", + "parent_pid": 708, + "process_hash": [ + "a7296c1245ee76768d581c6330dade06", + "5be0de7f915ba819d4ba048db7a2a87f6f3253fdd4865dc418181a0d6a031caa" + ], + "process_name": "c:\\windows\\system32\\svchost.exe", + "process_pid": [1144] + } + sibling_info = { + "process_guid": "WNEXFKQ7-000309c2-00000980-00000000-1d6a1c1f41ae014", + "process_hash": [ + "b5a2c3084251ad5ce53e02f071fa7dc9", + "ae600593a0a6915cf5ecbf96b4cb1d0e1d165339bde136c351bf606127c5dcec" + ], + "process_name": "c:\\windows\\carbonblack\\cb.exe", + "process_pid": [2432] + } + parent_info = { + "process_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "process_hash": [ + "e4b9902024ac32b3ca37f6b4c9b841e8", + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85" + ], + "process_name": "/usr/lib/systemd/systemd", + "process_pid": [1] + } + child_info = { + "process_guid": "WNEXFKQ7-000309c2-000004f8-00000000-1d6a88e80c541a3", + "process_hash": [ + "2ae75e810f4dd1fb36607f66e7e1d80b", + "db703055ec0641e7e96e22a62bf075547b480c51ea9e163d94e33452894b885c" + ], + "process_name": "c:\\windows\\system32\\wermgr.exe", + "process_pid": [1272] + } + info = { + 'process': process_info, + 'siblings - 1': sibling_info, + 'parent': parent_info, + 'children - 1': child_info + } + lines = [] + for top in info: + lines.append(top) + for key in info[top]: + val = str(info[top][key]) + if len(val) > 50: + val = val[:47] + u"..." + lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", key, val)) + if top != 'process' and top != 'parent': + lines.append("") + + expected = "\n".join(lines) + assert actual == expected + assert process.summary is not None assert process.siblings is not None summary = api.select(Process.Summary, guid) @@ -133,6 +198,9 @@ def test_summary_select_failures(cbcsdk_mock): guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' summary = api.select(Process.Summary).where(f"process_guid:{guid}") assert isinstance(summary, SummaryQuery) + with pytest.raises(ApiError) as ex: + summary._count() + assert 'The result is not iterable' in ex.value.message summary._query_token = 'something' with pytest.raises(ApiError) as ex: summary._submit() @@ -172,8 +240,6 @@ def test_summary_still_querying(cbcsdk_mock): summary = api.select(Process.Summary).where(f"process_guid:{guid}") assert summary._still_querying() is True summary._search() - summary._timed_out = True - summary._search() def test_summary_select_set_time_range(cbcsdk_mock): @@ -1133,13 +1199,48 @@ def test_tree_select(cbcsdk_mock): # mock the GET to get search results cbcsdk_mock.mock_request("GET", ("/api/investigate/v2/orgs/test/processes/summary_jobs/" "ee158f11-4dfb-4ae2-8f1a-7707b712226d/results"), - GET_TREE_RESP) + GET_PROCESS_TREE_STR) api = cbcsdk_mock.api guid = "WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00" process = api.select(Process, guid) tree = process.tree - tree.__str__() + process_info = { + "device_id": 176678, + "device_name": "devr-dev", + "process_hash": [ + "e4b9902024ac32b3ca37f6b4c9b841e8", + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85" + ], + "process_name": "/usr/lib/systemd/systemd", + "process_pid": [1], + } + child_info = { + "process_guid": "WNEXFKQ7-000309c2-00000454-00000000-1d6a2b6252ba18e", + "process_hash": [ + "f9a3eee1c3a4067702bc9a59bc894285", + "8e2aa014d7729cbfee95671717646ee480561f22e2147dae87a75c18d7369d99" + ], + "process_name": "c:\\windows\\system32\\msiexec.exe", + "process_pid": [1108] + } + actual = tree.__str__() + info = { + 'process': process_info, + 'children - 1': child_info + } + lines = [] + for top in info: + lines.append(top) + for key in info[top]: + val = str(info[top][key]) + if len(val) > 50: + val = val[:47] + u"..." + lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", key, val)) + if top != 'process': + lines.append("") + expected = "\n".join(lines) + assert actual == expected children = tree.children assert len(children) == len(tree.children) assert len(children) > 0 From 23e25a2a9b99d33a1526b8eb8e9318016fe2f673 Mon Sep 17 00:00:00 2001 From: Emanuela Mitreva Date: Thu, 11 Mar 2021 15:33:44 +0200 Subject: [PATCH 04/20] CBAPI-2022: Removing truncation of field values, changing the len of the siblings and children --- src/cbc_sdk/platform/processes.py | 16 ++++----------- .../unit/platform/test_platform_process.py | 20 ++++++++----------- 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/cbc_sdk/platform/processes.py b/src/cbc_sdk/platform/processes.py index fdf0d2956..1e9e91772 100644 --- a/src/cbc_sdk/platform/processes.py +++ b/src/cbc_sdk/platform/processes.py @@ -97,9 +97,9 @@ def __str__(self): for top_level in self._info: if self._info[top_level] and top_level in self.SHOW_ATTR: if self.SHOW_ATTR[top_level]['type'] == 'single': - lines.append(top_level) + lines.append('{}:'.format(top_level)) else: - lines.append(f"{top_level} - {len(self._info[top_level])}") + lines.append(f"{top_level} ({len(self._info[top_level])}):") if self.SHOW_ATTR[top_level]['type'] == 'single': for attr in self._info[top_level]: @@ -108,8 +108,6 @@ def __str__(self): val = str(self._info[top_level][attr]) except UnicodeDecodeError: val = repr(self._info[top_level][attr]) - if len(val) > 50: - val = val[:47] + u"..." lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", attr, val)) else: for item in self._info[top_level]: @@ -119,8 +117,6 @@ def __str__(self): val = str(item[attr]) except UnicodeDecodeError: val = repr(item[attr]) - if len(val) > 50: - val = val[:47] + u"..." lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", attr, val)) lines.append('') return "\n".join(lines) @@ -174,18 +170,16 @@ def __str__(self): str: A string representation of the object. """ lines = [] - lines.append('process') + lines.append('process:') for attr in self._info: if attr in self.SHOW_ATTR['top']: try: val = str(self._info[attr]) except UnicodeDecodeError: val = repr(self._info[attr]) - if len(val) > 50: - val = val[:47] + u"..." lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", attr, val)) - lines.append(f"children - {len(self._info['children'])}") + lines.append(f"children ({len(self._info['children'])}):") for child in self._info['children']: for attr in child: if attr in self.SHOW_ATTR['children']: @@ -193,8 +187,6 @@ def __str__(self): val = str(child[attr]) except UnicodeDecodeError: val = repr(child[attr]) - if len(val) > 50: - val = val[:47] + u"..." lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", attr, val)) lines.append('') return "\n".join(lines) diff --git a/src/tests/unit/platform/test_platform_process.py b/src/tests/unit/platform/test_platform_process.py index 2ada03ea9..1602eef1d 100644 --- a/src/tests/unit/platform/test_platform_process.py +++ b/src/tests/unit/platform/test_platform_process.py @@ -134,20 +134,18 @@ def test_process_select(cbcsdk_mock): "process_pid": [1272] } info = { - 'process': process_info, - 'siblings - 1': sibling_info, - 'parent': parent_info, - 'children - 1': child_info + 'process:': process_info, + 'siblings (1):': sibling_info, + 'parent:': parent_info, + 'children (1):': child_info } lines = [] for top in info: lines.append(top) for key in info[top]: val = str(info[top][key]) - if len(val) > 50: - val = val[:47] + u"..." lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", key, val)) - if top != 'process' and top != 'parent': + if top != 'process:' and top != 'parent:': lines.append("") expected = "\n".join(lines) @@ -1226,18 +1224,16 @@ def test_tree_select(cbcsdk_mock): } actual = tree.__str__() info = { - 'process': process_info, - 'children - 1': child_info + 'process:': process_info, + 'children (1):': child_info } lines = [] for top in info: lines.append(top) for key in info[top]: val = str(info[top][key]) - if len(val) > 50: - val = val[:47] + u"..." lines.append(u"{0:s} {1:>20s}: {2:s}".format(" ", key, val)) - if top != 'process': + if top != 'process:': lines.append("") expected = "\n".join(lines) assert actual == expected From d478ce8ff0a816359a5839659abe9a325cb4de10 Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Tue, 9 Mar 2021 14:20:12 -0700 Subject: [PATCH 05/20] came up with a replacement strategy for Enriched EventQuery base class It doesn't change the unit tests except for some minor massaging to handle changes in internal variable names. --- src/cbc_sdk/endpoint_standard/base.py | 96 +------------------ .../test_endpoint_standard_enriched_events.py | 4 +- 2 files changed, 6 insertions(+), 94 deletions(-) diff --git a/src/cbc_sdk/endpoint_standard/base.py b/src/cbc_sdk/endpoint_standard/base.py index 781b7f6d0..56561901e 100644 --- a/src/cbc_sdk/endpoint_standard/base.py +++ b/src/cbc_sdk/endpoint_standard/base.py @@ -15,6 +15,7 @@ from cbc_sdk.base import (MutableBaseModel, UnrefreshableModel, CreatableModelMixin, NewBaseModel, FacetQuery, PaginatedQuery, QueryBuilder, QueryBuilderSupportMixin, IterableQueryMixin, AsyncQueryMixin) +from cbc_sdk.base import Query as BaseEventQuery from cbc_sdk.utils import convert_query_params from cbc_sdk.errors import ApiError from cbc_sdk.platform.reputation import ReputationOverride @@ -608,7 +609,7 @@ def _search(self, start=0, rows=0): break -class EnrichedEventQuery(Query, AsyncQueryMixin): +class EnrichedEventQuery(BaseEventQuery): """Represents the query logic for an Enriched Event query. This class specializes `Query` to handle the particulars of enriched events querying. @@ -623,16 +624,10 @@ def __init__(self, doc_class, cb): cb (CBCloudAPI): A reference to the CBCloudAPI object. """ super(EnrichedEventQuery, self).__init__(doc_class, cb) - self._sort_by = None - self._group_by = None - self._rows = 500 - self._default_args = {} - self._default_args["rows"] = self._rows + self._default_args["rows"] = self._batch_size self._query_token = None self._timeout = 0 self._timed_out = False - self._sort = [] - self._time_range = {} self._aggregation = False self._aggregation_field = None @@ -659,15 +654,6 @@ def aggregation(self, field): self._aggregation_field = field return self - def _get_query_parameters(self): - """Need to override base class implementation as it sets custom (invalid) fields""" - args = self._default_args.copy() - args['query'] = self._query_builder._collapse() - if self._time_range: - args["time_range"] = self._time_range - - return args - def set_rows(self, rows): """ Sets the 'rows' query body parameter to the 'start search' API call, determining how many rows to request. @@ -679,70 +665,7 @@ def set_rows(self, rows): raise ApiError(f"Rows must be an integer. {rows} is a {type(rows)}.") if rows > 10000: raise ApiError("Maximum allowed value for rows is 10000") - - self._rows = rows - self._default_args["rows"] = self._rows - return self - - def set_time_range(self, start=None, end=None, window=None): - """ - Sets the 'time_range' query body parameter, determining a time window based on 'device_timestamp'. - - Args: - start (str in ISO 8601 timestamp): When to start the result search. - end (str in ISO 8601 timestamp): When to end the result search. - window (str): Time window to execute the result search, ending on the current time. - Should be in the form "-2w", where y=year, w=week, d=day, h=hour, m=minute, s=second. - - Note: - - `window` will take precedence over `start` and `end` if provided. - - Examples: - query = api.select(EnrichedEvent).set_time_range(start="2020-10-20T20:34:07Z") - second_query = api.select(EnrichedEvent).set_time_range(start="2020-10-20T20:34:07Z", - end="2020-10-30T20:34:07Z") - third_query = api.select(EnrichedEvent).set_time_range(window='-3d') - """ - if start: - if not isinstance(start, str): - raise ApiError(f"Start time must be a string in ISO 8601 format. {start} is a {type(start)}.") - self._time_range["start"] = start - if end: - if not isinstance(end, str): - raise ApiError(f"End time must be a string in ISO 8601 format. {end} is a {type(end)}.") - self._time_range["end"] = end - if window: - if not isinstance(window, str): - raise ApiError(f"Window must be a string. {window} is a {type(window)}.") - self._time_range["window"] = window - - return self - - def sort_by(self, key, direction="ASC"): - """Sets the sorting behavior on a query's results. - - Arguments: - key (str): The key in the schema to sort by. - direction (str): The sort order, either "ASC" or "DESC". - - Returns: - Query (EnrichedEventQuery: The query with sorting parameters. - - Example: - >>> cb.select(EnrichedEvent).where(process_name="cmd.exe").sort_by("device_timestamp") - """ - found = False - - for sort_item in self._sort: - if sort_item['field'] == key: - sort_item['order'] = direction - found = True - - if not found: - self._sort.append({'field': key, 'order': direction}) - - self._default_args['sort'] = self._sort - + super(EnrichedEventQuery, self).set_rows(rows) return self def timeout(self, msecs): @@ -894,14 +817,3 @@ def _search(self, start=0, rows=0): still_fetching = False log.debug("current: {}, total_results: {}".format(current, self._total_results)) - - def _run_async_query(self, context): - """Executed in the background to run an asynchronous query. - - Args: - context (object): The context (query token) returned by _init_async_query. - - Returns: - Any: Result of the async query, which is then returned by the future. - """ - return list(self._search()) diff --git a/src/tests/unit/endpoint_standard/test_endpoint_standard_enriched_events.py b/src/tests/unit/endpoint_standard/test_endpoint_standard_enriched_events.py index 276e94439..21a76aed9 100644 --- a/src/tests/unit/endpoint_standard/test_endpoint_standard_enriched_events.py +++ b/src/tests/unit/endpoint_standard/test_endpoint_standard_enriched_events.py @@ -244,14 +244,14 @@ def test_enriched_event_query_sort(cbcsdk_mock): api = cbcsdk_mock.api events = api.select(EnrichedEvent).where(process_pid=1000).or_(process_pid=1000).sort_by("process_pid", direction="DESC") - assert events._sort == [{"field": "process_pid", "order": "DESC"}] + assert events._sort_by == [{"field": "process_pid", "order": "DESC"}] def test_enriched_event_rows(cbcsdk_mock): """Testing EnrichedEvent results sort.""" api = cbcsdk_mock.api events = api.select(EnrichedEvent).where(process_pid=1000).set_rows(1500) - assert events._rows == 1500 + assert events._batch_size == 1500 def test_enriched_event_time_range(cbcsdk_mock): From 09483950ac0ee2268f51efb96452aeacfb072af0 Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Thu, 11 Mar 2021 16:19:21 -0700 Subject: [PATCH 06/20] added example script for process events --- examples/endpoint_standard/process_events.py | 79 ++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 examples/endpoint_standard/process_events.py diff --git a/examples/endpoint_standard/process_events.py b/examples/endpoint_standard/process_events.py new file mode 100755 index 000000000..65219007e --- /dev/null +++ b/examples/endpoint_standard/process_events.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# ******************************************************* +# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# SPDX-License-Identifier: MIT +# ******************************************************* +# * +# * DISCLAIMER. THIS PROGRAM IS PROVIDED TO YOU "AS IS" WITHOUT +# * WARRANTIES OR CONDITIONS OF ANY KIND, WHETHER ORAL OR WRITTEN, +# * EXPRESS OR IMPLIED. THE AUTHOR SPECIFICALLY DISCLAIMS ANY IMPLIED +# * WARRANTIES OR CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, +# * NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. + +"""Example script retrieving process events.""" + +import sys +from cbc_sdk.helpers import build_cli_parser, get_cb_cloud_object +from cbc_sdk.endpoint_standard import EnrichedEvent + + +def parse_key_value_pairs(kvlist): + """Parse the key=value strings into a dict of lists of values""" + output = {} + if kvlist: + for kvpair in kvlist: + (key, value) = kvpair.split('=') + if not (key and value): + raise RuntimeError(f"invalid exclusion specified: {kvpair}") + if key in output: + output[key].append(value) + else: + output[key] = [value] + return output + + +def main(): + """Main function of the process events script.""" + parser = build_cli_parser() + parser.add_argument("--query", "-q", type=str, help="Query string for the search", default=None) + parser.add_argument("--include", "-i", action='append', type=str, + help="Specifies included event field values, as key=value") + parser.add_argument("--exclude", "-x", action='append', type=str, + help="Specifies excluded event field values, as key=value") + parser.add_argument("--fields", "-f", action='append', type=str, help="Specifies names of fields to include") + parser.add_argument("--numrows", "-n", type=int, help="Maximum number of rows to be returned", default=None) + parser.add_argument("--group", "-g", type=str, help="Field to group by, either device_id or process_sha256", + default=None) + parser.add_argument("--timeout", "-T", type=int, help="Timeout for the search in milliseconds", default=None) + + args = parser.parse_args() + cb = get_cb_cloud_object(args) + + query = cb.select(EnrichedEvent) + if args.query: + query.where(args.query) + inclusions = parse_key_value_pairs(args.include) + for (key, value) in inclusions: + query.update_criteria(key, value) + exclusions = parse_key_value_pairs(args.exclude) + for (key, value) in exclusions: + query.add_exclusion(key, value) + if args.fields: + query.set_fields(args.fields) + if args.numrows: + query.set_rows(args.numrows) + if args.group: + query.aggregation(args.group) + if args.timeout: + query.timeout(args.timeout) + + separator = False + for event in query: + if separator: + print("------------------------------------------------------------------------\n") + separator = True + print(f"{event}\n") + + +if __name__ == "__main__": + sys.exit(main()) From 11f11eb77b0be69ce62ccced3e1d0f18087b1380 Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Thu, 11 Mar 2021 16:32:50 -0700 Subject: [PATCH 07/20] removed an extraneous import spotted by flake8 --- src/cbc_sdk/endpoint_standard/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cbc_sdk/endpoint_standard/base.py b/src/cbc_sdk/endpoint_standard/base.py index 56561901e..0c4d8904f 100644 --- a/src/cbc_sdk/endpoint_standard/base.py +++ b/src/cbc_sdk/endpoint_standard/base.py @@ -14,7 +14,7 @@ """Model and Query Classes for Endpoint Standard""" from cbc_sdk.base import (MutableBaseModel, UnrefreshableModel, CreatableModelMixin, NewBaseModel, FacetQuery, - PaginatedQuery, QueryBuilder, QueryBuilderSupportMixin, IterableQueryMixin, AsyncQueryMixin) + PaginatedQuery, QueryBuilder, QueryBuilderSupportMixin, IterableQueryMixin) from cbc_sdk.base import Query as BaseEventQuery from cbc_sdk.utils import convert_query_params from cbc_sdk.errors import ApiError From 50c1d8a9518723d726604749b39cb640faae040e Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Fri, 12 Mar 2021 11:16:29 -0700 Subject: [PATCH 08/20] rename script at Alex's suggestion --- .../{process_events.py => enriched_events_query.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/endpoint_standard/{process_events.py => enriched_events_query.py} (100%) diff --git a/examples/endpoint_standard/process_events.py b/examples/endpoint_standard/enriched_events_query.py similarity index 100% rename from examples/endpoint_standard/process_events.py rename to examples/endpoint_standard/enriched_events_query.py From e9c6606ec92d4071d2bd00d8b4b072da0b0174af Mon Sep 17 00:00:00 2001 From: Hristo Karagitliev Date: Mon, 15 Mar 2021 17:54:22 +0200 Subject: [PATCH 09/20] update changelog and fix workload in sidebar --- docs/cbc_sdk.workload.rst | 2 +- docs/changelog.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/cbc_sdk.workload.rst b/docs/cbc_sdk.workload.rst index 0413b95ca..51a5ae66a 100644 --- a/docs/cbc_sdk.workload.rst +++ b/docs/cbc_sdk.workload.rst @@ -1,4 +1,4 @@ -cbc\_sdk.workload package +Workload ========================= Submodules diff --git a/docs/changelog.rst b/docs/changelog.rst index 847514849..e4f65e2c1 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -12,6 +12,7 @@ New Features * Appliance Service * Sensor Lifecycle Management * VM Workloads Search + * Vulnerability Assessment * Add tutorial for Reputation Override From 7d14afd2c7eeba8628f3dfe23282c92a43a0ac26 Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Mon, 15 Mar 2021 13:06:20 -0600 Subject: [PATCH 10/20] modified changelog --- docs/changelog.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 847514849..adebce89a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,7 +9,6 @@ New Features * VMware Carbon Black Cloud Workload support for managing workloads: * Appliance Installation - * Appliance Service * Sensor Lifecycle Management * VM Workloads Search From c907708953f3962f04da818390468ad4a33c3c23 Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Mon, 15 Mar 2021 13:26:17 -0600 Subject: [PATCH 11/20] modified changelog --- docs/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index adebce89a..fd81192f4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -8,7 +8,7 @@ New Features * VMware Carbon Black Cloud Workload support for managing workloads: - * Appliance Installation + * Vulnerability Assessment * Sensor Lifecycle Management * VM Workloads Search From 81f652a3a007df907ef194484ceed30d2f61b277 Mon Sep 17 00:00:00 2001 From: Emanuela Mitreva Date: Tue, 16 Mar 2021 08:53:11 +0200 Subject: [PATCH 12/20] Remove unused line and unused class --- src/cbc_sdk/platform/processes.py | 4 ++-- src/tests/unit/platform/test_platform_process.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cbc_sdk/platform/processes.py b/src/cbc_sdk/platform/processes.py index 1e9e91772..19c868bea 100644 --- a/src/cbc_sdk/platform/processes.py +++ b/src/cbc_sdk/platform/processes.py @@ -15,7 +15,7 @@ from cbc_sdk.base import (UnrefreshableModel, BaseQuery, Query, FacetQuery, QueryBuilderSupportMixin, QueryBuilder, - AsyncQueryMixin, IterableQueryMixin) + AsyncQueryMixin) from cbc_sdk.platform import Event from cbc_sdk.platform.reputation import ReputationOverride from cbc_sdk.errors import ApiError, TimeoutError @@ -684,7 +684,7 @@ def _run_async_query(self, context): return list(self._search()) -class SummaryQuery(BaseQuery, AsyncQueryMixin, QueryBuilderSupportMixin, IterableQueryMixin): +class SummaryQuery(BaseQuery, AsyncQueryMixin, QueryBuilderSupportMixin): """Represents the logic for a Process Summary or Process Tree query.""" def __init__(self, doc_class, cb): """ diff --git a/src/tests/unit/platform/test_platform_process.py b/src/tests/unit/platform/test_platform_process.py index 1602eef1d..357c6a3a1 100644 --- a/src/tests/unit/platform/test_platform_process.py +++ b/src/tests/unit/platform/test_platform_process.py @@ -237,7 +237,6 @@ def test_summary_still_querying(cbcsdk_mock): guid = 'WNEXFKQ7-0002b226-000015bd-00000000-1d6225bbba74c00' summary = api.select(Process.Summary).where(f"process_guid:{guid}") assert summary._still_querying() is True - summary._search() def test_summary_select_set_time_range(cbcsdk_mock): From 91bc95ced8ea471673c27f79f8683ad7f37add91 Mon Sep 17 00:00:00 2001 From: Hristo Karagitliev Date: Tue, 16 Mar 2021 10:24:06 +0200 Subject: [PATCH 13/20] update changelog with develop --- docs/changelog.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index e4f65e2c1..b18058a8b 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -8,6 +8,10 @@ New Features * VMware Carbon Black Cloud Workload support for managing workloads: + * Vulnerability Assessment + * Sensor Lifecycle Management + * VM Workloads Search + * Appliance Installation * Appliance Service * Sensor Lifecycle Management From 464752d33994a00107ae1f8e063121d41f419cd0 Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Tue, 16 Mar 2021 16:04:51 -0600 Subject: [PATCH 14/20] CBAPI-2021: added process detail support to platform Process object --- src/cbc_sdk/platform/processes.py | 68 +++++++++++++++ .../unit/fixtures/platform/mock_process.py | 86 +++++++++++++++++++ .../unit/platform/test_platform_process.py | 61 ++++++++++++- 3 files changed, 214 insertions(+), 1 deletion(-) diff --git a/src/cbc_sdk/platform/processes.py b/src/cbc_sdk/platform/processes.py index 19c868bea..3d9348938 100644 --- a/src/cbc_sdk/platform/processes.py +++ b/src/cbc_sdk/platform/processes.py @@ -357,6 +357,74 @@ def facets(self): """ return self._cb.select(ProcessFacet).where(process_guid=self.process_guid) + def get_details(self, timeout=0, async_mode=False): + """Requests detailed results. + + Args: + timeout (int): Event details request timeout in milliseconds. + async_mode (bool): True to request details in an asynchronous manner. + + Note: + - When using asynchronous mode, this method returns a python future. + You can call result() on the future object to wait for completion and get the results. + """ + self._details_timeout = timeout + if not self.process_guid: + raise ApiError("Trying to get process details on an invalid process_guid") + if async_mode: + return self._cb._async_submit(lambda arg, kwarg: self._get_detailed_results()._info) + else: + return self._get_detailed_results()._info + + def _get_detailed_results(self): + """Actual search details implementation""" + args = {"process_guids": [self.process_guid]} + url = "/api/investigate/v2/orgs/{}/processes/detail_jobs".format(self._cb.credentials.org_key) + query_start = self._cb.post_object(url, body=args) + job_id = query_start.json().get("job_id") + timed_out = False + submit_time = time.time() * 1000 + + while True: + status_url = "/api/investigate/v2/orgs/{}/processes/detail_jobs/{}".format( + self._cb.credentials.org_key, + job_id, + ) + result = self._cb.get_object(status_url) + searchers_contacted = result.get("contacted", 0) + searchers_completed = result.get("completed", 0) + log.debug("contacted = {}, completed = {}".format(searchers_contacted, searchers_completed)) + if searchers_contacted == 0: + time.sleep(.5) + continue + if searchers_completed < searchers_contacted: + if self._details_timeout != 0 and (time.time() * 1000) - submit_time > self._details_timeout: + timed_out = True + break + else: + break + + time.sleep(.5) + + if timed_out: + raise TimeoutError(message="user-specified timeout exceeded while waiting for results") + + log.debug("Pulling detailed results, timed_out={}".format(timed_out)) + + still_fetching = True + result_url = "/api/investigate/v2/orgs/{}/processes/detail_jobs/{}/results".format( + self._cb.credentials.org_key, + job_id + ) + query_parameters = {} + while still_fetching: + result = self._cb.get_object(result_url, query_parameters=query_parameters) + total_results = result.get('num_available', 0) + if total_results != 0: + results = result.get('results', []) + self._info = results[0] + return self + def ban_process_sha256(self, description=""): """Bans the application by adding the process_sha256 to the BLACK_LIST diff --git a/src/tests/unit/fixtures/platform/mock_process.py b/src/tests/unit/fixtures/platform/mock_process.py index 5201c52ed..113ff837f 100644 --- a/src/tests/unit/fixtures/platform/mock_process.py +++ b/src/tests/unit/fixtures/platform/mock_process.py @@ -2360,6 +2360,92 @@ "completed": 33 } +POST_PROCESS_DETAILS_JOB_RESP = { + 'job_id': 'ccc47a52-9a61-4c77-8652-8a03dc187b98' +} + +GET_PROCESS_DETAILS_JOB_STATUS_RESP = { + 'contacted': 16, + 'completed': 16 +} + +GET_PROCESS_DETAILS_JOB_STATUS_IN_PROGRESS_RESP = { + 'contacted': 16, + 'completed': 8 +} + +GET_PROCESS_DETAILS_JOB_RESULTS_RESP = { + 'contacted': 16, + 'completed': 16, + 'num_available': 1, + 'num_found': 1, + 'results': [ + { + "backend_timestamp": "2020-08-28T19:14:40.394Z", + "childproc_count": 333576, + "crossproc_count": 0, + "device_external_ip": "34.56.78.90", + "device_group_id": 0, + "device_id": 176678, + "device_location": "UNKNOWN", + "device_name": "devr-dev", + "device_os": "LINUX", + "device_os_version": "CentOS 7.6-1810", + "device_policy": "sm-restrictive", + "device_policy_id": 11200, + "device_target_priority": "MEDIUM", + "device_timestamp": "2020-08-28T19:12:41.178Z", + "document_guid": "6Gqoe-abQXu-k9LagGOoQg", + "filemod_count": 0, + "ingress_time": 1598642021337, + "modload_count": 0, + "netconn_count": 0, + "org_id": "test", + "parent_effective_reputation": "NOT_LISTED", + "parent_guid": "ABCD1234-0002b226-00000001-00000000-1d6225bbba75e43", + "parent_hash": [ + "81b37dcb0321108e564d528df827580153ab64005be3bcafd5162e9e7e707e85", + "e4b9902024ac32b3ca37f6b4c9b841e8" + ], + "parent_name": "/usr/lib/systemd/systemd", + "parent_pid": 1, + "parent_publisher_state": [ + "FILE_SIGNATURE_STATE_NOT_SIGNED" + ], + "parent_reputation": "NOT_LISTED", + "process_cmdline": [ + "/usr/bin/gitea" + ], + "process_cmdline_length": [ + 14 + ], + "process_effective_reputation": "NOT_LISTED", + "process_guid": "80dab519-3b5f-4502-afad-da87cd58a4c3", + "process_hash": [ + "285044ad8f8b9322d0cc5e929e2cc18c", + "5975d972eea6b1c53ef9a69452797439ed5bf63fae72e1780761ea1c2cb6976a" + ], + "process_name": "/usr/bin/bash", + "process_pid": [ + 10111, + 10222, + 10333 + ], + "process_publisher_state": [ + "FILE_SIGNATURE_STATE_NOT_SIGNED" + ], + "process_reputation": "NOT_LISTED", + "process_sha256": "5975d972eea6b1c53ef9a69452797439ed5bf63fae72e1780761ea1c2cb6976a", + "process_start_time": "2020-05-04T21:34:03.968Z", + "process_username": [ + "root" + ], + "regmod_count": 0, + "scriptload_count": 0 + } + ] +} + GET_FACET_SEARCH_RESULTS_RESP = { "ranges": [ { diff --git a/src/tests/unit/platform/test_platform_process.py b/src/tests/unit/platform/test_platform_process.py index 357c6a3a1..0de5148c1 100644 --- a/src/tests/unit/platform/test_platform_process.py +++ b/src/tests/unit/platform/test_platform_process.py @@ -5,7 +5,7 @@ from cbc_sdk.platform import Process, ProcessFacet, Event, AsyncProcessQuery, SummaryQuery from cbc_sdk.base import FacetQuery, Query from cbc_sdk.rest_api import CBCloudAPI -from cbc_sdk.errors import ApiError +from cbc_sdk.errors import ApiError, TimeoutError from tests.unit.fixtures.CBCSDKMock import CBCSDKMock from tests.unit.fixtures.platform.mock_process import (GET_PROCESS_SUMMARY_RESP, GET_PROCESS_SUMMARY_RESP_1, @@ -32,6 +32,10 @@ GET_PROCESS_SEARCH_JOB_RESULTS_RESP_NO_PARENT_GUID, GET_PROCESS_SEARCH_PARENT_JOB_RESULTS_RESP, GET_PROCESS_SEARCH_PARENT_JOB_RESULTS_RESP_1, + POST_PROCESS_DETAILS_JOB_RESP, + GET_PROCESS_DETAILS_JOB_STATUS_RESP, + GET_PROCESS_DETAILS_JOB_STATUS_IN_PROGRESS_RESP, + GET_PROCESS_DETAILS_JOB_RESULTS_RESP, GET_FACET_SEARCH_RESULTS_RESP, EXPECTED_PROCESS_FACETS, EXPECTED_PROCESS_RANGES_FACETS, @@ -1080,6 +1084,61 @@ def test_process_still_querying_zero(cbcsdk_mock): assert process._still_querying() is True +def test_process_get_details(cbcsdk_mock): + """Test get_details on a process.""" + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/detail_jobs", + POST_PROCESS_DETAILS_JOB_RESP) + cbcsdk_mock.mock_request("GET", + "/api/investigate/v2/orgs/test/processes/detail_jobs/ccc47a52-9a61-4c77-8652-8a03dc187b98", # noqa: E501 + GET_PROCESS_DETAILS_JOB_STATUS_RESP) + cbcsdk_mock.mock_request("GET", + "/api/investigate/v2/orgs/test/processes/detail_jobs/ccc47a52-9a61-4c77-8652-8a03dc187b98/results", # noqa: E501 + GET_PROCESS_DETAILS_JOB_RESULTS_RESP) + + api = cbcsdk_mock.api + process = Process(api, '80dab519-3b5f-4502-afad-da87cd58a4c3', + {'process_guid': '80dab519-3b5f-4502-afad-da87cd58a4c3'}) + results = process.get_details() + assert results['process_guid'] == '80dab519-3b5f-4502-afad-da87cd58a4c3' + assert results['process_cmdline'][0] == '/usr/bin/gitea' + assert 10222 in results['process_pid'] + + +def test_process_get_details_async(cbcsdk_mock): + """Test get_details on a process in async mode.""" + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/detail_jobs", + POST_PROCESS_DETAILS_JOB_RESP) + cbcsdk_mock.mock_request("GET", + "/api/investigate/v2/orgs/test/processes/detail_jobs/ccc47a52-9a61-4c77-8652-8a03dc187b98", # noqa: E501 + GET_PROCESS_DETAILS_JOB_STATUS_RESP) + cbcsdk_mock.mock_request("GET", + "/api/investigate/v2/orgs/test/processes/detail_jobs/ccc47a52-9a61-4c77-8652-8a03dc187b98/results", # noqa: E501 + GET_PROCESS_DETAILS_JOB_RESULTS_RESP) + + api = cbcsdk_mock.api + process = Process(api, '80dab519-3b5f-4502-afad-da87cd58a4c3', + {'process_guid': '80dab519-3b5f-4502-afad-da87cd58a4c3'}) + future = process.get_details(0, True) + results = future.result() + assert results['process_guid'] == '80dab519-3b5f-4502-afad-da87cd58a4c3' + assert results['process_cmdline'][0] == '/usr/bin/gitea' + assert 10222 in results['process_pid'] + + +def test_process_get_details_timeout(cbcsdk_mock): + """Test the timeout of a get_details request.""" + cbcsdk_mock.mock_request("POST", "/api/investigate/v2/orgs/test/processes/detail_jobs", + POST_PROCESS_DETAILS_JOB_RESP) + cbcsdk_mock.mock_request("GET", + "/api/investigate/v2/orgs/test/processes/detail_jobs/ccc47a52-9a61-4c77-8652-8a03dc187b98", # noqa: E501 + GET_PROCESS_DETAILS_JOB_STATUS_IN_PROGRESS_RESP) + api = cbcsdk_mock.api + process = Process(api, '80dab519-3b5f-4502-afad-da87cd58a4c3', + {'process_guid': '80dab519-3b5f-4502-afad-da87cd58a4c3'}) + with pytest.raises(TimeoutError): + process.get_details(1000) + + def test_process_facet_select(cbcsdk_mock): """Testing ProcessFacet select(), ranges_, terms_.""" api = cbcsdk_mock.api From 77594b76718063f24c8605f78bb5fc95e16322b9 Mon Sep 17 00:00:00 2001 From: Amy Bowersox Date: Wed, 17 Mar 2021 14:56:07 -0600 Subject: [PATCH 15/20] CBAPI-2021: added process details call to UAT script --- src/tests/uat/process_search_calls.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/tests/uat/process_search_calls.py b/src/tests/uat/process_search_calls.py index 93359602d..8ca84b32b 100755 --- a/src/tests/uat/process_search_calls.py +++ b/src/tests/uat/process_search_calls.py @@ -26,6 +26,11 @@ * Start a Facet Search on Processes (v2) * Retrieve Results for a Process Facets Search (v2) +Process Details: +* Request Details of Processes (v2) +* Get the Status of a Process Detail Search (v2) +* Retrieve Results for a Process Detail Search (v2) + Process Events: * Get Validation for Event Search (v1) * Get Events Associated with a Given Process (v2) @@ -184,6 +189,27 @@ def get_process_basic_window_enriched(cb, print_detail, window): return matching_processes[6].process_guid +def get_process_details_for_single_process(cb, guid): + """ + Start API calls for getting process details and print the response. + + Args: + cb (CBCloudAPI): API object + guid (str): GUID of process to have details retrieved + """ + print("API Calls:") + print("Request Details of Processes (v2)") + print("Get the Status of a Process Detail Search (v2)") + print("Retrieve Results for a Process Detail Search (v2)") + print(f"process_guid: {guid}\n") + + process_query = cb.select(Process).where(process_guid=guid) + pprint(process_query[0].get_details()) + + print("\nCompare results manually with Postman") + print("----------------------------------------------------------") + + def get_process_events_for_single_process(cb, print_detail, guid): """ Text @@ -392,6 +418,7 @@ def main(): cb = get_cb_cloud_object(args) if do_process: process_guid = get_process_basic_window_enriched(cb, print_detail, window) + get_process_details_for_single_process(cb, process_guid) get_process_events_for_single_process(cb, print_detail, process_guid) run_process_invalid_search(cb, print_detail) run_process_event_invalid_search(cb, print_detail) From 0b3a023b1687a475ff7968daf9f33f0853097b7e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Mar 2021 00:32:49 +0000 Subject: [PATCH 16/20] Bump pyyaml in /examples/enterprise_edr/threat_intelligence Bumps [pyyaml](https://github.com/yaml/pyyaml) from 5.1.2 to 5.4. - [Release notes](https://github.com/yaml/pyyaml/releases) - [Changelog](https://github.com/yaml/pyyaml/blob/master/CHANGES) - [Commits](https://github.com/yaml/pyyaml/compare/5.1.2...5.4) Signed-off-by: dependabot[bot] --- examples/enterprise_edr/threat_intelligence/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/enterprise_edr/threat_intelligence/requirements.txt b/examples/enterprise_edr/threat_intelligence/requirements.txt index a5b90e6e7..d636e1fd9 100644 --- a/examples/enterprise_edr/threat_intelligence/requirements.txt +++ b/examples/enterprise_edr/threat_intelligence/requirements.txt @@ -5,6 +5,6 @@ stix==1.2.0.7 lxml==4.6.2 urllib3>=1.24.2 python_dateutil==2.8.1 -PyYAML==5.1.2 +PyYAML==5.4 schema carbon-black-cloud-sdk From e714d44344468af2ca7834ca63ac9a13be2c78bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 Mar 2021 15:53:49 +0000 Subject: [PATCH 17/20] Bump lxml in /examples/enterprise_edr/threat_intelligence Bumps [lxml](https://github.com/lxml/lxml) from 4.6.2 to 4.6.3. - [Release notes](https://github.com/lxml/lxml/releases) - [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt) - [Commits](https://github.com/lxml/lxml/compare/lxml-4.6.2...lxml-4.6.3) Signed-off-by: dependabot[bot] --- examples/enterprise_edr/threat_intelligence/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/enterprise_edr/threat_intelligence/requirements.txt b/examples/enterprise_edr/threat_intelligence/requirements.txt index d636e1fd9..35ed4fe12 100644 --- a/examples/enterprise_edr/threat_intelligence/requirements.txt +++ b/examples/enterprise_edr/threat_intelligence/requirements.txt @@ -2,7 +2,7 @@ cybox==2.1.0.18 dataclasses>=0.6 cabby==0.1.20 stix==1.2.0.7 -lxml==4.6.2 +lxml==4.6.3 urllib3>=1.24.2 python_dateutil==2.8.1 PyYAML==5.4 From 69c7f0f0595afb99fed699d845da044a28a0b3d1 Mon Sep 17 00:00:00 2001 From: Alex Van Brunt Date: Thu, 25 Mar 2021 16:55:00 -0600 Subject: [PATCH 18/20] Fix spawnworkers, error log, and removing errored jobs --- src/cbc_sdk/live_response_api.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/cbc_sdk/live_response_api.py b/src/cbc_sdk/live_response_api.py index 2885cd77d..975054391 100644 --- a/src/cbc_sdk/live_response_api.py +++ b/src/cbc_sdk/live_response_api.py @@ -937,6 +937,8 @@ def run(self): if item.status == "error": log.error("Error encountered by JobWorker[{0}]: {1}".format(item.device_id, item.exception)) + # Don't reattempt error'd jobs + del self._unscheduled_jobs[item.device_id] elif item.status == "exiting": log.debug("JobWorker[{0}] has exited, waiting...".format(item.device_id)) self._job_workers[item.device_id].join() @@ -1015,17 +1017,18 @@ def _spawn_new_workers(self): if len(self._job_workers) >= self._max_workers: return - schedule_max = self._max_workers - len(self._job_workers) + from datetime import datetime, timedelta + now = datetime.utcnow() + delta = timedelta(minutes=60) from cbc_sdk.endpoint_standard import Device devices = [s for s in self._cb.select(Device) if s.deviceId in self._unscheduled_jobs - and s.deviceId not in self._job_workers and s.status == "Online"] # noqa: W503 - devices_to_schedule = sorted(devices, key=lambda x: ( - int(x.num_storefiles_bytes) + int(x.num_eventlog_bytes), x.next_checkin_time - ))[:schedule_max] + and s.deviceId not in self._job_workers and now - s.lastContact < delta] # noqa: W503 - log.debug("Spawning new workers to handle these devices: {0}".format(devices_to_schedule)) - for device in devices_to_schedule: + log.debug("Spawning new workers to handle these devices: {0}".format(devices)) + for device in devices: + if len(self._job_workers) >= self._max_workers: + break log.debug("Spawning new JobWorker for device id {0}".format(device.deviceId)) self._job_workers[device.deviceId] = JobWorker(self._cb, device.deviceId, self.schedule_queue) self._job_workers[device.deviceId].start() @@ -1296,7 +1299,7 @@ def poll_status(cb, url, desired_status="complete", timeout=None, delay=None): while status != desired_status and time.time() - start_time < timeout: res = cb.get_object(url) - log.error(f"url: {url} -> status: {res['status']}") + log.debug(f"url: {url} -> status: {res['status']}") if res["status"] == desired_status: log.debug(json.dumps(res)) return res From a45af26fde9ea10b8421497ae052d65d8215ac89 Mon Sep 17 00:00:00 2001 From: Alex Van Brunt Date: Tue, 30 Mar 2021 12:53:18 -0600 Subject: [PATCH 19/20] Add set_max_rows for device query --- src/cbc_sdk/platform/devices.py | 21 +++++++++++++++++++ .../unit/platform/test_platform_devices.py | 14 +++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/cbc_sdk/platform/devices.py b/src/cbc_sdk/platform/devices.py index 8bb543ba0..18c009c63 100644 --- a/src/cbc_sdk/platform/devices.py +++ b/src/cbc_sdk/platform/devices.py @@ -267,6 +267,7 @@ def __init__(self, doc_class, cb): self._time_filter = {} self._exclusions = {} self._sortcriteria = {} + self.max_rows = -1 def _update_exclusions(self, key, newlist): """ @@ -485,6 +486,24 @@ def set_deployment_type(self, deployment_type): self._update_criteria("deployment_type", deployment_type) return self + def set_max_rows(self, max_rows): + """ + Sets the max number of devices to fetch in a singular query + + Args: + max_rows (integer): Max number of devices + + Returns: + DeviceSearchQuery: This instance. + + Raises: + ApiError: If rows is negative or greater than 10000 + """ + if max_rows < 0 or max_rows > 10000: + raise ApiError("Max rows must be between 0 and 10000") + self.max_rows = max_rows + return self + def _build_request(self, from_row, max_rows): """ Creates the request body for an API call. @@ -505,6 +524,8 @@ def _build_request(self, from_row, max_rows): request["start"] = from_row if max_rows >= 0: request["rows"] = max_rows + elif self.max_rows >= 0: + request["rows"] = self.max_rows if self._sortcriteria != {}: request["sort"] = [self._sortcriteria] return request diff --git a/src/tests/unit/platform/test_platform_devices.py b/src/tests/unit/platform/test_platform_devices.py index b1f89d277..0daa00a22 100644 --- a/src/tests/unit/platform/test_platform_devices.py +++ b/src/tests/unit/platform/test_platform_devices.py @@ -4,6 +4,7 @@ import logging from cbc_sdk.platform import Device, DeviceSearchQuery from cbc_sdk.rest_api import CBCloudAPI +from cbc_sdk.errors import ApiError from tests.unit.fixtures.CBCSDKMock import CBCSDKMock from tests.unit.fixtures.platform.mock_devices import (GET_DEVICE_RESP, POST_DEVICE_SEARCH_RESP) @@ -77,3 +78,16 @@ def test_device_id_property(cbcsdk_mock): cbcsdk_mock.mock_request("GET", "/appservices/v6/orgs/test/devices/98765", GET_DEVICE_RESP) a = Device(cbcsdk_mock.api, 98765) a.deviceId + + +def test_device_max_rows(cbcsdk_mock): + """Testing Device Querying with .set_max_rows""" + api = cbcsdk_mock.api + query = api.select(Device).set_max_rows(10) + assert query.max_rows == 10 + + with pytest.raises(ApiError): + query.set_max_rows(-1) + + with pytest.raises(ApiError): + query.set_max_rows(10001) From 39a01083411cc58fd91807b8b4d8e01af9f774d8 Mon Sep 17 00:00:00 2001 From: Alex Van Brunt Date: Wed, 31 Mar 2021 14:30:11 -0600 Subject: [PATCH 20/20] Release v1.2.1 --- LICENSE | 2 +- README.md | 4 ++-- VERSION | 2 +- bin/cbc-sdk-help.py | 2 +- bin/set-windows-registry.py | 2 +- docs/changelog.rst | 17 +++++++++++++++++ docs/conf.py | 4 ++-- examples/audit_remediation/manage_run.py | 2 +- .../endpoint_standard/enriched_events_query.py | 2 +- examples/endpoint_standard/live_response_cli.py | 2 +- examples/endpoint_standard/policy_operations.py | 2 +- examples/enterprise_edr/feed_operations.py | 2 +- examples/platform/device_actions.py | 2 +- examples/platform/device_processes.py | 2 +- examples/platform/list_devices.py | 2 +- src/cbc_sdk/__init__.py | 2 +- src/cbc_sdk/audit_remediation/base.py | 2 +- src/cbc_sdk/base.py | 2 +- src/cbc_sdk/cache/lru.py | 2 +- src/cbc_sdk/connection.py | 2 +- src/cbc_sdk/credential_providers/default.py | 2 +- .../environ_credential_provider.py | 2 +- .../file_credential_provider.py | 2 +- .../registry_credential_provider.py | 2 +- src/cbc_sdk/credentials.py | 2 +- src/cbc_sdk/endpoint_standard/base.py | 2 +- .../endpoint_standard/usb_device_control.py | 2 +- .../enterprise_edr/threat_intelligence.py | 2 +- src/cbc_sdk/enterprise_edr/ubs.py | 2 +- src/cbc_sdk/errors.py | 2 +- src/cbc_sdk/helpers.py | 2 +- src/cbc_sdk/live_response_api.py | 2 +- src/cbc_sdk/platform/alerts.py | 2 +- src/cbc_sdk/platform/base.py | 2 +- src/cbc_sdk/platform/devices.py | 2 +- src/cbc_sdk/platform/events.py | 2 +- src/cbc_sdk/platform/processes.py | 2 +- src/cbc_sdk/platform/reputation.py | 2 +- src/cbc_sdk/rest_api.py | 2 +- src/cbc_sdk/utils.py | 2 +- src/cbc_sdk/winerror.py | 2 +- src/cbc_sdk/workload/sensor_lifecycle.py | 2 +- src/tests/uat/device_control_uat.py | 2 +- src/tests/uat/platform_devices_uat.py | 2 +- src/tests/uat/process_search_calls.py | 2 +- src/tests/unit/conftest.py | 2 +- .../unit/credential_providers/test_default.py | 2 +- .../unit/credential_providers/test_environ.py | 2 +- .../unit/credential_providers/test_file.py | 2 +- .../unit/credential_providers/test_registry.py | 2 +- .../unit/endpoint_standard/test_usb_device.py | 2 +- .../test_usb_device_approval.py | 2 +- .../endpoint_standard/test_usb_device_block.py | 2 +- src/tests/unit/fixtures/CBCSDKMock.py | 2 +- src/tests/unit/fixtures/mock_credentials.py | 2 +- src/tests/unit/platform/test_alertsv6_api.py | 2 +- src/tests/unit/platform/test_devicev6_api.py | 2 +- src/tests/unit/platform/test_platform_models.py | 2 +- src/tests/unit/test_base_api.py | 2 +- src/tests/unit/test_connection.py | 2 +- src/tests/unit/test_credentials.py | 2 +- src/tests/unit/test_live_response_api.py | 2 +- src/tests/unit/test_utils.py | 2 +- .../unit/workload/test_sensor_lifecycle.py | 2 +- 64 files changed, 82 insertions(+), 65 deletions(-) diff --git a/LICENSE b/LICENSE index 3c6b906ff..4b5f6ad22 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Carbon Black +Copyright (c) 2020-2021 Carbon Black Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 2508cb13e..1f5c5ebb7 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # VMware Carbon Black Cloud Python SDK -**Latest Version:** 1.2.0 +**Latest Version:** 1.2.1
-**Release Date:** 9 March 2021 +**Release Date:** 31 March 2021 [![Coverage Status](https://coveralls.io/repos/github/carbonblack/carbon-black-cloud-sdk-python/badge.svg?t=Id6Baf)](https://coveralls.io/github/carbonblack/carbon-black-cloud-sdk-python) [![Codeship Status for carbonblack/carbon-black-cloud-sdk-python](https://app.codeship.com/projects/9e55a370-a772-0138-aae4-129773225755/status?branch=develop)](https://app.codeship.com/projects/402767) diff --git a/VERSION b/VERSION index 26aaba0e8..6085e9465 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.0 +1.2.1 diff --git a/bin/cbc-sdk-help.py b/bin/cbc-sdk-help.py index 423656e49..b69045aa0 100644 --- a/bin/cbc-sdk-help.py +++ b/bin/cbc-sdk-help.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/bin/set-windows-registry.py b/bin/set-windows-registry.py index a11a5b037..81f68b1cc 100755 --- a/bin/set-windows-registry.py +++ b/bin/set-windows-registry.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/docs/changelog.rst b/docs/changelog.rst index fd81192f4..42bff7953 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,23 @@ Changelog ================================ +CBC SDK 1.2.1 - Released March 31, 2021 +-------------------------------------- + +New Features + +* Add `__str__` functions for Process.Tree and Process.Summary +* Add `get_details` for Process +* Add `set_max_rows` to DeviceQuery + +Bug Fixes + +* Modify base class for EnrichedEventQuery to Query from cbc_sdk.base to support entire feature set for searching +* Document fixes for changelog and Workload +* Fix `_spawn_new_workers` to correctly find active devices for Carbon Black Cloud + + + CBC SDK 1.2.0 - Released March 9, 2021 -------------------------------------- diff --git a/docs/conf.py b/docs/conf.py index 5d891ee89..29266256d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,11 +19,11 @@ # -- Project information ----------------------------------------------------- project = 'Carbon Black Cloud Python SDK' -copyright = '2020, Developer Relations' +copyright = '2020-2021, Developer Relations' author = 'Developer Relations' # The full version, including alpha/beta/rc tags -release = '1.2.0' +release = '1.2.1' # -- General configuration --------------------------------------------------- diff --git a/examples/audit_remediation/manage_run.py b/examples/audit_remediation/manage_run.py index 7da273818..d074ab8df 100755 --- a/examples/audit_remediation/manage_run.py +++ b/examples/audit_remediation/manage_run.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/examples/endpoint_standard/enriched_events_query.py b/examples/endpoint_standard/enriched_events_query.py index 65219007e..2f469c02d 100755 --- a/examples/endpoint_standard/enriched_events_query.py +++ b/examples/endpoint_standard/enriched_events_query.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/examples/endpoint_standard/live_response_cli.py b/examples/endpoint_standard/live_response_cli.py index 0ce87a85c..7f77c76cc 100755 --- a/examples/endpoint_standard/live_response_cli.py +++ b/examples/endpoint_standard/live_response_cli.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/examples/endpoint_standard/policy_operations.py b/examples/endpoint_standard/policy_operations.py index 19678bc35..7d1f4552b 100755 --- a/examples/endpoint_standard/policy_operations.py +++ b/examples/endpoint_standard/policy_operations.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/examples/enterprise_edr/feed_operations.py b/examples/enterprise_edr/feed_operations.py index d9bb5925d..899ff4001 100755 --- a/examples/enterprise_edr/feed_operations.py +++ b/examples/enterprise_edr/feed_operations.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/examples/platform/device_actions.py b/examples/platform/device_actions.py index 2b7f2ddca..eb31f35ed 100755 --- a/examples/platform/device_actions.py +++ b/examples/platform/device_actions.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/examples/platform/device_processes.py b/examples/platform/device_processes.py index 2aef8e1b4..51b9b2251 100755 --- a/examples/platform/device_processes.py +++ b/examples/platform/device_processes.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/examples/platform/list_devices.py b/examples/platform/list_devices.py index 4e8d6e473..2e26b9396 100755 --- a/examples/platform/list_devices.py +++ b/examples/platform/list_devices.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/__init__.py b/src/cbc_sdk/__init__.py index 4da31b397..a4324adab 100644 --- a/src/cbc_sdk/__init__.py +++ b/src/cbc_sdk/__init__.py @@ -4,7 +4,7 @@ __author__ = 'Carbon Black Developer Network' __license__ = 'MIT' __copyright__ = 'Copyright 2020-2021 VMware Carbon Black' -__version__ = '1.2.0' +__version__ = '1.2.1' from .rest_api import CBCloudAPI from .cache import lru diff --git a/src/cbc_sdk/audit_remediation/base.py b/src/cbc_sdk/audit_remediation/base.py index 53f0dcf26..f12da4bcc 100644 --- a/src/cbc_sdk/audit_remediation/base.py +++ b/src/cbc_sdk/audit_remediation/base.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/base.py b/src/cbc_sdk/base.py index 41c3d8126..9d6659baf 100644 --- a/src/cbc_sdk/base.py +++ b/src/cbc_sdk/base.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/cache/lru.py b/src/cbc_sdk/cache/lru.py index 2e895e14c..d79ab0d90 100644 --- a/src/cbc_sdk/cache/lru.py +++ b/src/cbc_sdk/cache/lru.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/connection.py b/src/cbc_sdk/connection.py index 7fbd44619..3c9620379 100644 --- a/src/cbc_sdk/connection.py +++ b/src/cbc_sdk/connection.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/credential_providers/default.py b/src/cbc_sdk/credential_providers/default.py index be4adff52..7241fbfbe 100755 --- a/src/cbc_sdk/credential_providers/default.py +++ b/src/cbc_sdk/credential_providers/default.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/credential_providers/environ_credential_provider.py b/src/cbc_sdk/credential_providers/environ_credential_provider.py index dd6b79435..162fea1fb 100755 --- a/src/cbc_sdk/credential_providers/environ_credential_provider.py +++ b/src/cbc_sdk/credential_providers/environ_credential_provider.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/credential_providers/file_credential_provider.py b/src/cbc_sdk/credential_providers/file_credential_provider.py index c4a0f05d9..5b447db0d 100755 --- a/src/cbc_sdk/credential_providers/file_credential_provider.py +++ b/src/cbc_sdk/credential_providers/file_credential_provider.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/credential_providers/registry_credential_provider.py b/src/cbc_sdk/credential_providers/registry_credential_provider.py index 1992d302e..c488a94a1 100755 --- a/src/cbc_sdk/credential_providers/registry_credential_provider.py +++ b/src/cbc_sdk/credential_providers/registry_credential_provider.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/credentials.py b/src/cbc_sdk/credentials.py index a14fe9426..c6dfb6208 100644 --- a/src/cbc_sdk/credentials.py +++ b/src/cbc_sdk/credentials.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/endpoint_standard/base.py b/src/cbc_sdk/endpoint_standard/base.py index 0c4d8904f..06887231c 100644 --- a/src/cbc_sdk/endpoint_standard/base.py +++ b/src/cbc_sdk/endpoint_standard/base.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/endpoint_standard/usb_device_control.py b/src/cbc_sdk/endpoint_standard/usb_device_control.py index fcd71c705..ac60aea86 100755 --- a/src/cbc_sdk/endpoint_standard/usb_device_control.py +++ b/src/cbc_sdk/endpoint_standard/usb_device_control.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/enterprise_edr/threat_intelligence.py b/src/cbc_sdk/enterprise_edr/threat_intelligence.py index d368a64a1..fae655f7b 100644 --- a/src/cbc_sdk/enterprise_edr/threat_intelligence.py +++ b/src/cbc_sdk/enterprise_edr/threat_intelligence.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/enterprise_edr/ubs.py b/src/cbc_sdk/enterprise_edr/ubs.py index 16072d8c6..ce9c451d1 100644 --- a/src/cbc_sdk/enterprise_edr/ubs.py +++ b/src/cbc_sdk/enterprise_edr/ubs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/errors.py b/src/cbc_sdk/errors.py index 8bbe0cf19..1b8217b90 100644 --- a/src/cbc_sdk/errors.py +++ b/src/cbc_sdk/errors.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/helpers.py b/src/cbc_sdk/helpers.py index 733083e04..9b7697476 100644 --- a/src/cbc_sdk/helpers.py +++ b/src/cbc_sdk/helpers.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/live_response_api.py b/src/cbc_sdk/live_response_api.py index 975054391..fcfddd513 100644 --- a/src/cbc_sdk/live_response_api.py +++ b/src/cbc_sdk/live_response_api.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/platform/alerts.py b/src/cbc_sdk/platform/alerts.py index 7a6a22be0..700b278ba 100644 --- a/src/cbc_sdk/platform/alerts.py +++ b/src/cbc_sdk/platform/alerts.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/platform/base.py b/src/cbc_sdk/platform/base.py index c14ea4e73..4863d47c3 100644 --- a/src/cbc_sdk/platform/base.py +++ b/src/cbc_sdk/platform/base.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/platform/devices.py b/src/cbc_sdk/platform/devices.py index 18c009c63..ff38caed8 100644 --- a/src/cbc_sdk/platform/devices.py +++ b/src/cbc_sdk/platform/devices.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/platform/events.py b/src/cbc_sdk/platform/events.py index f3f2a7013..08420b8f9 100644 --- a/src/cbc_sdk/platform/events.py +++ b/src/cbc_sdk/platform/events.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/platform/processes.py b/src/cbc_sdk/platform/processes.py index 3d9348938..41a447ffb 100644 --- a/src/cbc_sdk/platform/processes.py +++ b/src/cbc_sdk/platform/processes.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/platform/reputation.py b/src/cbc_sdk/platform/reputation.py index 873761117..f318953cc 100644 --- a/src/cbc_sdk/platform/reputation.py +++ b/src/cbc_sdk/platform/reputation.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/rest_api.py b/src/cbc_sdk/rest_api.py index 444c356e5..c529d4f10 100644 --- a/src/cbc_sdk/rest_api.py +++ b/src/cbc_sdk/rest_api.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/utils.py b/src/cbc_sdk/utils.py index 7a2bba0b4..b3a2e04b8 100755 --- a/src/cbc_sdk/utils.py +++ b/src/cbc_sdk/utils.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/winerror.py b/src/cbc_sdk/winerror.py index 56e118d7c..c92de7ea4 100644 --- a/src/cbc_sdk/winerror.py +++ b/src/cbc_sdk/winerror.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/cbc_sdk/workload/sensor_lifecycle.py b/src/cbc_sdk/workload/sensor_lifecycle.py index 94e48c8ba..b849cfd46 100755 --- a/src/cbc_sdk/workload/sensor_lifecycle.py +++ b/src/cbc_sdk/workload/sensor_lifecycle.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/uat/device_control_uat.py b/src/tests/uat/device_control_uat.py index 10854613f..a5ef10e8b 100644 --- a/src/tests/uat/device_control_uat.py +++ b/src/tests/uat/device_control_uat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/uat/platform_devices_uat.py b/src/tests/uat/platform_devices_uat.py index e86fdbee2..9fec2a54d 100755 --- a/src/tests/uat/platform_devices_uat.py +++ b/src/tests/uat/platform_devices_uat.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/uat/process_search_calls.py b/src/tests/uat/process_search_calls.py index 8ca84b32b..c51256d32 100755 --- a/src/tests/uat/process_search_calls.py +++ b/src/tests/uat/process_search_calls.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/conftest.py b/src/tests/unit/conftest.py index e2553896a..acba3ae98 100755 --- a/src/tests/unit/conftest.py +++ b/src/tests/unit/conftest.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/credential_providers/test_default.py b/src/tests/unit/credential_providers/test_default.py index 67aa4c266..e2cd23b33 100755 --- a/src/tests/unit/credential_providers/test_default.py +++ b/src/tests/unit/credential_providers/test_default.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/credential_providers/test_environ.py b/src/tests/unit/credential_providers/test_environ.py index aa3a6313d..f91ba0ff2 100755 --- a/src/tests/unit/credential_providers/test_environ.py +++ b/src/tests/unit/credential_providers/test_environ.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/credential_providers/test_file.py b/src/tests/unit/credential_providers/test_file.py index eb1fecb5b..db85b38c1 100755 --- a/src/tests/unit/credential_providers/test_file.py +++ b/src/tests/unit/credential_providers/test_file.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/credential_providers/test_registry.py b/src/tests/unit/credential_providers/test_registry.py index 828c887a3..b05c684a2 100755 --- a/src/tests/unit/credential_providers/test_registry.py +++ b/src/tests/unit/credential_providers/test_registry.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/endpoint_standard/test_usb_device.py b/src/tests/unit/endpoint_standard/test_usb_device.py index a88084380..0e3d61ff1 100755 --- a/src/tests/unit/endpoint_standard/test_usb_device.py +++ b/src/tests/unit/endpoint_standard/test_usb_device.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/endpoint_standard/test_usb_device_approval.py b/src/tests/unit/endpoint_standard/test_usb_device_approval.py index 8d77ad579..ffe880d41 100755 --- a/src/tests/unit/endpoint_standard/test_usb_device_approval.py +++ b/src/tests/unit/endpoint_standard/test_usb_device_approval.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/endpoint_standard/test_usb_device_block.py b/src/tests/unit/endpoint_standard/test_usb_device_block.py index b2555a9f6..ce5c11279 100755 --- a/src/tests/unit/endpoint_standard/test_usb_device_block.py +++ b/src/tests/unit/endpoint_standard/test_usb_device_block.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/fixtures/CBCSDKMock.py b/src/tests/unit/fixtures/CBCSDKMock.py index 662f47bbf..bd84f69fb 100644 --- a/src/tests/unit/fixtures/CBCSDKMock.py +++ b/src/tests/unit/fixtures/CBCSDKMock.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/fixtures/mock_credentials.py b/src/tests/unit/fixtures/mock_credentials.py index e933eeeb1..04554985c 100755 --- a/src/tests/unit/fixtures/mock_credentials.py +++ b/src/tests/unit/fixtures/mock_credentials.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/platform/test_alertsv6_api.py b/src/tests/unit/platform/test_alertsv6_api.py index 7b3360582..2035a1148 100755 --- a/src/tests/unit/platform/test_alertsv6_api.py +++ b/src/tests/unit/platform/test_alertsv6_api.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/platform/test_devicev6_api.py b/src/tests/unit/platform/test_devicev6_api.py index 3e6190c67..3b8a06619 100755 --- a/src/tests/unit/platform/test_devicev6_api.py +++ b/src/tests/unit/platform/test_devicev6_api.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/platform/test_platform_models.py b/src/tests/unit/platform/test_platform_models.py index ea3973473..789a06f25 100755 --- a/src/tests/unit/platform/test_platform_models.py +++ b/src/tests/unit/platform/test_platform_models.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/test_base_api.py b/src/tests/unit/test_base_api.py index 7448c4c01..0591417c1 100755 --- a/src/tests/unit/test_base_api.py +++ b/src/tests/unit/test_base_api.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/test_connection.py b/src/tests/unit/test_connection.py index fc1390952..2c90cd277 100755 --- a/src/tests/unit/test_connection.py +++ b/src/tests/unit/test_connection.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/test_credentials.py b/src/tests/unit/test_credentials.py index 3c33fa618..2944e1c2c 100755 --- a/src/tests/unit/test_credentials.py +++ b/src/tests/unit/test_credentials.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/test_live_response_api.py b/src/tests/unit/test_live_response_api.py index 98ba326f9..7ab514a21 100755 --- a/src/tests/unit/test_live_response_api.py +++ b/src/tests/unit/test_live_response_api.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/test_utils.py b/src/tests/unit/test_utils.py index 05a46f247..322c5a6c2 100755 --- a/src/tests/unit/test_utils.py +++ b/src/tests/unit/test_utils.py @@ -1,5 +1,5 @@ # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # * diff --git a/src/tests/unit/workload/test_sensor_lifecycle.py b/src/tests/unit/workload/test_sensor_lifecycle.py index 8e4713340..e88336d14 100755 --- a/src/tests/unit/workload/test_sensor_lifecycle.py +++ b/src/tests/unit/workload/test_sensor_lifecycle.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # ******************************************************* -# Copyright (c) VMware, Inc. 2020. All Rights Reserved. +# Copyright (c) VMware, Inc. 2020-2021. All Rights Reserved. # SPDX-License-Identifier: MIT # ******************************************************* # *