diff --git a/lerc_client/lercConsole/App.config b/lerc_client/lercConsole/App.config index 40ff78a..8b37fa7 100644 --- a/lerc_client/lercConsole/App.config +++ b/lerc_client/lercConsole/App.config @@ -1,7 +1,7 @@  - + diff --git a/lerc_client/lercConsole/lercConsole.csproj b/lerc_client/lercConsole/lercConsole.csproj index b0dbf62..78682ae 100644 --- a/lerc_client/lercConsole/lercConsole.csproj +++ b/lerc_client/lercConsole/lercConsole.csproj @@ -9,7 +9,7 @@ Properties lercConsole lercConsole - v4.5.2 + v4.8 512 true @@ -22,6 +22,7 @@ DEBUG;TRACE prompt 4 + v4.8 AnyCPU @@ -31,6 +32,7 @@ TRACE prompt 4 + v4.8 diff --git a/lerc_client/lercLib/lercLib.csproj b/lerc_client/lercLib/lercLib.csproj index a7e97df..f0a4cd9 100644 --- a/lerc_client/lercLib/lercLib.csproj +++ b/lerc_client/lercLib/lercLib.csproj @@ -9,7 +9,7 @@ Properties lercLib lercLib - v4.5.2 + v4.8 512 diff --git a/lerc_client/lercService/App.config b/lerc_client/lercService/App.config index f826dde..b08d813 100644 --- a/lerc_client/lercService/App.config +++ b/lerc_client/lercService/App.config @@ -1,7 +1,7 @@  - + diff --git a/lerc_client/lercService/lercService.csproj b/lerc_client/lercService/lercService.csproj index a145736..3dbaee8 100644 --- a/lerc_client/lercService/lercService.csproj +++ b/lerc_client/lercService/lercService.csproj @@ -9,7 +9,7 @@ Properties lercService lerc - v4.5.2 + v4.8 512 true publish\ @@ -92,9 +92,9 @@ - + False - Microsoft .NET Framework 4.5.2 %28x86 and x64%29 + Microsoft .NET Framework 4.8 %28x86 and x64%29 true diff --git a/lerc_client/packages.config b/lerc_client/packages.config index 508c490..1f23437 100644 --- a/lerc_client/packages.config +++ b/lerc_client/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/lerc_control/__init__.py b/lerc_control/__init__.py index 4f025b9..9fc6759 100644 --- a/lerc_control/__init__.py +++ b/lerc_control/__init__.py @@ -102,7 +102,7 @@ def main(): parser_run = subparsers.add_parser('run', help="Run a shell command on the host.") parser_run.add_argument('hostname', help="the host you'd like to work with") parser_run.add_argument('command', help='The shell command for the host to execute`') - parser_run.add_argument('-a', '--async', action='store_true', help='Set asynchronous to true (do NOT wait for output or command to complete)') + parser_run.add_argument('-a', '--asynchronous', action='store_true', help='Set asynchronous to true (do NOT wait for output or command to complete)') parser_run.add_argument('-p', '--print-only', action='store_true', help='Only print results to screen.') parser_run.add_argument('-w', '--write-only', action='store_true', help='Only write results to file.') parser_run.add_argument('-o', '--output-filename', default=None, action='store', help='Specify the name of the file to write any results to.') @@ -324,25 +324,24 @@ def main(): sys.exit(0) logger.info("Attempting to deploy lerc with CarbonBlack..") try: - from cbapi.response import CbResponseAPI - from cbapi.psc.threathunter import CbThreatHunterAPI + from cbc_sdk import CBCloudAPI from cbinterface.cli import load_configured_environments - from cbinterface.psc.device import find_device_by_hostname + from cbinterface.enterprise_edr.device import find_device_by_hostname from lerc_control.deploy_lerc import deploy_lerc, CbSensor_search - except: - logger.error("Failed to import deployment functions. Install and configure cbinterface, if you have Carbon Black.") + except Exception as e: + logger.error(f"{e}Failed to import deployment functions. Install and configure cbinterface, if you have Carbon Black.") sys.exit(1) logging.getLogger('lerc_control.deploy_lerc').setLevel(logging.ERROR) device_or_sensor = None configured_environments = load_configured_environments() - if "psc" in configured_environments or "cbc" in configured_environments: + if "enterprise_edr" in configured_environments or "cbc" in configured_environments: # search here first logger.info(f"searching for device...") - profiles = configured_environments.get("psc", []) + profiles = configured_environments.get("enterprise_edr", []) profiles.extend(configured_environments.get("cbc", [])) for profile in profiles: - cb = CbThreatHunterAPI(profile=profile) + cb = CBCloudAPI(profile=profile) device_or_sensor = find_device_by_hostname(cb, args.hostname) if device_or_sensor: break @@ -509,8 +508,8 @@ def main(): # Else, see if we're running a command directly cmd = None if args.instruction == 'run': - if args.async: - cmd = client.Run(args.command, async=args.async) + if args.asynchronous: + cmd = client.Run(args.command, asynchronous=args.asynchronous) else: cmd = client.Run(args.command) diff --git a/lerc_control/collect.py b/lerc_control/collect.py index 85cf337..83d67aa 100644 --- a/lerc_control/collect.py +++ b/lerc_control/collect.py @@ -6,6 +6,7 @@ import pprint import logging import configparser +import sys from lerc_control.scripted import load_script, execute_script from lerc_control import lerc_api @@ -206,10 +207,10 @@ def full_collection(lerc): logger.info("Starting full Live Response collection on {}.".format(lerc.hostname)) - # for contriving the output filename - local_date_str_cmd = lerc.Run('date /t') # Delete any existing LR artifacts - lerc.Run("DEL /S /F /Q lr && rmdir /S /Q lr") + lerc.Run("DEL /F /Q lr.exe && DEL /S /F /Q lr && rmdir /S /Q lr") + # for contriving the output filename + local_date_str_cmd = lerc.Run('powershell -NoProfile -Command "Get-Date -Format \'yyyyMMdd\'"') # download the package lr_download = lerc.Download(lr_path) logger.info("Issued CID={} for client to download {}.".format(lr_download.id, lr_path)) @@ -226,14 +227,8 @@ def full_collection(lerc): if local_date_str_cmd.status == 'COMPLETE': dateStr = local_date_str_cmd.get_results(return_content=True).decode('utf-8') logger.debug("Got date string of '{}'".format(dateStr)) - try: - # Mon 11/19/2018 -> 20181119 - dateStr = dateStr.split(' ')[1].split('/') - dateStr = dateStr[2]+dateStr[0]+dateStr[1] - # hostname.upper() because streamline.py expects uppercase - output_filename = lerc.hostname.upper() + "." + dateStr + ".7z" - except IndexError: - logger.warning("Unexpected date string obtained. Got '{}'".format(dateStr)) + # hostname.upper() because streamline.py expects uppercase + output_filename = lerc.hostname.upper() + "." + dateStr.strip() + ".7z" break # wait five seconds before asking the server again time.sleep(5) @@ -293,7 +288,7 @@ def full_collection(lerc): upload_command.get_results(file_path=output_filename) # Call steamline on the 7z lr package logger.info("[+] Starting streamline on {}".format(output_filename)) - args = shlex.split(streamline_path + " " + output_filename) + args = shlex.split(f"{sys.executable} {streamline_path} {output_filename}") try: subprocess.Popen(args).wait() logger.info("[+] Streamline complete") diff --git a/lerc_control/deploy_lerc.py b/lerc_control/deploy_lerc.py index ee98a4a..c7c7392 100755 --- a/lerc_control/deploy_lerc.py +++ b/lerc_control/deploy_lerc.py @@ -16,17 +16,17 @@ logger = logging.getLogger("lerc_control."+__name__) try: - from cbapi.psc import Device - from cbapi.psc.threathunter import CbThreatHunterAPI + from cbc_sdk.platform.devices import Device + from cbc_sdk import CBCloudAPI from cbapi.response import CbResponseAPI, Sensor - from cbapi.errors import ConnectionError, UnauthorizedError, ServerError, ClientError + from cbc_sdk.errors import ConnectionError, UnauthorizedError, ServerError, ClientError from cbinterface.cli import load_configured_environments - from cbinterface.config import get_default_cbapi_product, get_default_cbapi_profile + from cbinterface.config import get_default_cb_product, get_default_cb_profile from cbinterface.helpers import input_with_timeout from cbinterface.commands import ExecuteCommand, PutFile, GetFile, DeleteFile - from cbinterface.psc.device import find_device_by_hostname, is_device_online + from cbinterface.enterprise_edr.device import find_device_by_hostname, is_device_online from cbinterface.response.sensor import make_sensor_query, is_sensor_online except ModuleNotFoundError: sys.stderr.write("[ERROR] deploy_lerc only supports deployment with carbon black and cbinterface.") @@ -105,7 +105,7 @@ def deploy_lerc(device_or_sensor: Union[Device, Sensor], install_command: str, l hostname = device = sensor = None if isinstance(device_or_sensor, Device): - from cbinterface.psc.sessions import CustomLiveResponseSessionManager + from cbinterface.enterprise_edr.sessions import CustomLiveResponseSessionManager device = device_or_sensor hostname = device.name[device.name.rfind('\\')+1:] if '\\' in device.name else device.name elif isinstance(device_or_sensor, Sensor): @@ -138,7 +138,7 @@ def deploy_lerc(device_or_sensor: Union[Device, Sensor], install_command: str, l cb = device_or_sensor._cb offline = False - timeout = 1200 # default 20 minutes (same used by Cb) + timeout = 900 # default 15 minutes (same used by Cb) if device and not is_device_online(device): # Decision point: if the device is NOT online, give the analyst and option to wait logger.warning(f"{device.id}:{device.name} is offline.") @@ -170,18 +170,18 @@ def deploy_lerc(device_or_sensor: Union[Device, Sensor], install_command: str, l timeout = timeout * 86400 logger.info(f"waiting for active session on device ...") - session_manager = CustomLiveResponseSessionManager(cb, custom_session_keepalive=True) + session_manager = CustomLiveResponseSessionManager(cb, custom_session_keepalive=False) if not session_manager.wait_for_active_session(device_or_sensor, timeout=timeout): logger.error(f"reached timeout waiting for active session.") return False - download = PutFile(lerc_installer_path, 'lercSetup.msi') + download = PutFile(lerc_installer_path, 'C:\\Windows\\System32\\lercSetup.msi') execute = ExecuteCommand(install_command, wait_for_output=False, wait_timeout=60, wait_for_completion=True) logger.info(f"submitting commands to download and install lerc.") if previously_installed: # delete any old msi package, just in-case - session_manager.submit_command(DeleteFile('lercSetup.msi'), device_or_sensor) + session_manager.submit_command(DeleteFile('C:\\Windows\\System32\\lercSetup.msi'), device_or_sensor) session_manager.submit_command(download, device_or_sensor) session_manager.submit_command(execute, device_or_sensor) session_manager.process_completed_commands() # wait diff --git a/lerc_control/lerc_api/__init__.py b/lerc_control/lerc_api/__init__.py index 380a384..466939f 100644 --- a/lerc_control/lerc_api/__init__.py +++ b/lerc_control/lerc_api/__init__.py @@ -102,10 +102,10 @@ def load_config(profile='default', required_keys=[]): QUERY_FIELD_DESCRIPTIONS.append({'field': key, 'description': QUERY_FIELD_DICT[key]}) def parse_lerc_server_query(query_str): - """This function converts a string from field:value pairs into \*\*args that lerc_session.query can recognize. + """This function converts a string from field:value pairs into args that lerc_session.query can recognize. :param str query_str: A query string to be parsed. - :return: \*\*args ready for lerc_session.Query() + :return: args ready for lerc_session.Query() """ logger = logging.getLogger(__name__+".parse_lerc_server_query") query_parts = query_str.split() @@ -241,13 +241,13 @@ def _issue_command(self, command): return False - def Run(self, shell_command, async=False): + def Run(self, shell_command, asynchronous=False): """Execute a shell command on the host. :param str shell_command: The command to run on the host :param bool async: (optional) ``False``: LERC client will stream any results and wait until for completion. ``True``: Execute the command and return immediately. """ - command = { "operation":"run", "command": shell_command, "async": async } + command = { "operation":"run", "command": shell_command, "async": asynchronous } return self._issue_command(command) def Download(self, server_file_path, client_file_path=None, analyst_file_path=None): @@ -297,7 +297,7 @@ def list_directory(self, dir_path): for line in dir_lines: content = {} if line: - if line[2] == '/': + if line[2] == '/' or line[2] == '-': content['name'] = line[line.rfind(' ')+1:] if 'DIR' in line: content['type'] = 'DIR' @@ -348,7 +348,7 @@ def contain(self): self.Run('del {}'.format(bat_name)) self.Download(safe_contain_bat_path) - containment_command = self.Run(contain_cmd.format(int(self.sleep_cycle)+5), async=True) + containment_command = self.Run(contain_cmd.format(int(self.sleep_cycle)+5), asynchronous=True) # Dummy command to give the containment command enough time to execute before lerc kills it with wmic flag_cmd = self.Run("dir") diff --git a/lerc_control/scripted.py b/lerc_control/scripted.py index 003a06c..a6db3cb 100644 --- a/lerc_control/scripted.py +++ b/lerc_control/scripted.py @@ -182,7 +182,7 @@ def execute_script(lerc, script_path, return_result_commands=False, execute_clea # assuming we never will want to async_run OR write_results_path OR print_results COMMON_CLEANUP_COMMANDS['RUN'].append(run_string) continue - cmd = lerc.Run(run_string, async=async_run) + cmd = lerc.Run(run_string, asynchronous=async_run) command_history[command] = cmd command_history[command].get_the_results = get_results command_history[command].write_results_path = write_results_path diff --git a/lerc_control/scripts/collect_browsing_history.ini b/lerc_control/scripts/collect_browsing_history.ini index 4d7c4dd..f521915 100644 --- a/lerc_control/scripts/collect_browsing_history.ini +++ b/lerc_control/scripts/collect_browsing_history.ini @@ -6,7 +6,7 @@ get_results=no [command_2] operation=run -command=BrowsingHistoryView.exe /sort 2 /HistorySource 1 /VisitTimeFilterType 1 /scomma browserhistory.csv +command=BrowsingHistoryView.exe /sort 2 /HistorySource 1 /VisitTimeFilterType 1 /LoadIE 1 /LoadEdge 1 /LoadOpera 1 /LoadBrave 1 /LoadFirefox 1 /LoadChrome 1 /LoadSafari 1 /StopIECacheTask 1 /scomma browserhistory.csv async_run=no [command_3] @@ -44,4 +44,5 @@ write_results_path={HOSTNAME}_Chrome_Preferences [command_cleanup] operation=run -command=del browserhistory.csv Chrome_* BrowsingHistoryView.exe get_chrome_data.bat Firefox* \ No newline at end of file +command=del browserhistory.csv Chrome_* BrowsingHistoryView.exe get_chrome_data.bat Firefox* + diff --git a/lerc_control/tools/BrowsingHistoryView.exe b/lerc_control/tools/BrowsingHistoryView.exe index c08c275..1345259 100644 Binary files a/lerc_control/tools/BrowsingHistoryView.exe and b/lerc_control/tools/BrowsingHistoryView.exe differ diff --git a/lerc_control/upgrade_clients.py b/lerc_control/upgrade_clients.py index 5d9cde4..0489f78 100755 --- a/lerc_control/upgrade_clients.py +++ b/lerc_control/upgrade_clients.py @@ -35,7 +35,7 @@ def upgrade_host(hostname, upgrade_bat_path, lerc_msi_path): #. Drop lercSetup.msi #. Drop upgrade.bat - #. Execute upgrade.bat async=True with correct params ex. -> upgrade.bat 0 15 2048 "https://your-server-address/" -> company=0 reconnectdelay=15 chunksize=2048 serverurls="https://your-server-address/" + #. Execute upgrade.bat async_run=True with correct params ex. -> upgrade.bat 0 15 2048 "https://your-server-address/" -> company=0 reconnectdelay=15 chunksize=2048 serverurls="https://your-server-address/" #. Issue Quit command to host """ @@ -62,7 +62,7 @@ def upgrade_host(hostname, upgrade_bat_path, lerc_msi_path): host_commands.append(result) run_cmd = config['default']['upgrade_cmd'] - result = host.Run(run_cmd.format(host.id), async=True) + result = host.Run(run_cmd.format(host.id), async_run=True) host_commands.append(result) result = host.Quit() diff --git a/lerc_server/host_status_maintainer.py b/lerc_server/host_status_maintainer.py index 4de9eaa..67be092 100755 --- a/lerc_server/host_status_maintainer.py +++ b/lerc_server/host_status_maintainer.py @@ -7,7 +7,7 @@ import pymysql import pymysql.cursors -from datetime import datetime, timedelta +from datetime import datetime, timedelta, UTC BASE_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -26,8 +26,13 @@ offline_timeout = int(config['host_checker']['offline_timeout']) # Connect to Db -db = pymysql.connect(DB_server, DB_user, DB_userpass, "lerc", - cursorclass=pymysql.cursors.DictCursor) +db = pymysql.connect( + host=DB_server, + user=DB_user, + password=DB_userpass, + database="lerc", + cursorclass=pymysql.cursors.DictCursor +) # configure some logging logging.basicConfig(format='[%(levelname)s] %(asctime)s - %(name)s - %(message)s', @@ -46,21 +51,17 @@ def status_update(): c.execute("SELECT * FROM clients") for client in c.fetchall(): if client['status'] == "BUSY": - away_time = datetime.utcnow() - client['last_activity'] + away_time = datetime.now(UTC) - client['last_activity'].replace(tzinfo=UTC) with db.cursor() as tmp_c: tmp_c.execute("SELECT operation,command_id FROM commands WHERE hostname='{}' AND status='STARTED'".format(client['hostname'])) command = tmp_c.fetchone() if command is None: LOGGER.error("{} is in BUSY state with no STARTED commands in queue. Away time='{}' - Setting UNKNOWN".format(client['hostname'], away_time)) tmp_c.execute("UPDATE clients SET status='UNKNOWN' WHERE hostname='{}'".format(client['hostname'])) - elif away_time > timedelta(seconds=client['sleep_cycle']+2): - c.execute("UPDATE clients SET status='OFFLINE' WHERE hostname='{}'".format(client['hostname'])) - LOGGER.info("Set {} to OFFLINE: Exceeded it's next expected check-in by '{}'".format(client['hostname'], - str(away_time - timedelta(seconds=client['sleep_cycle'])))) else: LOGGER.info("{} is in a BUSY state working on CID={} since '{}'".format(client['hostname'], command['command_id'], client['last_activity'])) elif client['status'] != "UNKNOWN" and client['status'] != "UNINSTALLED" and client['status'] != "OFFLINE": - away_time = datetime.utcnow() - client['last_activity'] + away_time = datetime.now(UTC) - client['last_activity'].replace(tzinfo=UTC) LOGGER.debug("{} hasn't fetched in '{}'".format(client['hostname'], away_time)) if away_time > timedelta(days=offline_timeout): c.execute("UPDATE clients SET status='UNKNOWN' WHERE hostname='{}'".format(client['hostname'])) @@ -76,9 +77,8 @@ def status_update(): return if __name__ == '__main__': - status_update() - time.sleep(30) + time.sleep(25) status_update() db.close() diff --git a/lerc_server/installer/requirements-3.6.txt b/lerc_server/installer/requirements-3.9.txt similarity index 80% rename from lerc_server/installer/requirements-3.6.txt rename to lerc_server/installer/requirements-3.9.txt index a3ee76d..610145c 100644 --- a/lerc_server/installer/requirements-3.6.txt +++ b/lerc_server/installer/requirements-3.9.txt @@ -3,3 +3,4 @@ flask_restful flask_sqlalchemy pymysql pytz +cryptography diff --git a/lerc_server/installer/sql/user.sql b/lerc_server/installer/sql/user.sql index ed916f7..4a92fcd 100644 --- a/lerc_server/installer/sql/user.sql +++ b/lerc_server/installer/sql/user.sql @@ -1,4 +1,6 @@ DROP USER IF EXISTS 'lerc_user'@'localhost'; FLUSH PRIVILEGES; -GRANT ALL PRIVILEGES ON lerc . * TO 'lerc_user'@'localhost' IDENTIFIED BY 'LERC_DB_USER_PASSWORD'; +CREATE USER 'lerc_user'@'localhost' IDENTIFIED BY 'LERC_DB_USER_PASSWORD'; +GRANT ALL PRIVILEGES ON lerc . * TO 'lerc_user'@'localhost'; FLUSH PRIVILEGES; + diff --git a/lerc_server/library/clientInstructions.py b/lerc_server/library/clientInstructions.py index 27b6e38..1c5bd92 100644 --- a/lerc_server/library/clientInstructions.py +++ b/lerc_server/library/clientInstructions.py @@ -3,9 +3,9 @@ def Sleep(seconds): # return dict return { "operation":"sleep", "seconds":seconds } -def Run(command_id, command, async=False): +def Run(command_id, command, async_run=False): # execute a shell command on the host - return { "operation":"run", "id":command_id, "command":command , "async":async} + return { "operation":"run", "id":command_id, "command":command , "async":async_run} def Download(command_id, path): # Send file to endpoint - resume capable diff --git a/lerc_server/server.py b/lerc_server/server.py index f7620f1..e6781d2 100755 --- a/lerc_server/server.py +++ b/lerc_server/server.py @@ -7,7 +7,7 @@ import pytz import configparser from hashlib import md5 -from datetime import datetime +from datetime import datetime, timedelta, UTC from flask_restful import Resource, Api from flask import Flask, request, jsonify, stream_with_context, Response, make_response @@ -119,8 +119,8 @@ def host_check(host, company, version=None): elif client.status == clientStatusTypes.UNINSTALLED: logger.info("Client being re-installed.") client.status = clientStatusTypes.ONLINE - client.install_date = datetime.utcnow() - client.last_activity = datetime.utcnow() + client.install_date = datetime.now(UTC) + client.last_activity = datetime.now(UTC) client.company_id=company client.sleep_cycle=15 db.session.commit() @@ -130,7 +130,7 @@ def host_check(host, company, version=None): logger.info("setting company_id for {}".format(host)) client.company_id = company client.status = clientStatusTypes.ONLINE - client.last_activity = datetime.utcnow() + client.last_activity = datetime.now(UTC) db.session.commit() return client logger.error("Company id mismatch for {}. Two clients with the same hostname in different environments?".format(host)) @@ -139,7 +139,7 @@ def host_check(host, company, version=None): return False else: client.status = clientStatusTypes.ONLINE - client.last_activity = datetime.utcnow() + client.last_activity = datetime.now(UTC) client.version = version db.session.commit() return client @@ -157,7 +157,7 @@ def command_manager(host, remove_cid=None): # XXX Maybe write code that attempts to recover the STARTED but not COMPLETE command logger.error("{} fetched without finishing CID={} - Changing command statue to UNKNOWN.".format(started_command.hostname, started_command.command_id)) started_command.status = cmdStatusTypes.UNKNOWN - started_command.evaluated_time = datetime.utcnow() + started_command.evaluated_time = datetime.now(UTC) db.session.commit() # Any open commands? command = Commands.query.filter(Commands.hostname==host).filter(Commands.status==cmdStatusTypes.PENDING).order_by(Commands.command_id.asc()).first() @@ -267,14 +267,14 @@ def get(self): if command: logger.info("Issuing {} to {}".format(command.operation, command.hostname)) if command.operation == operationTypes.RUN: - return ci.Run(command.command_id, command.command, async=command.async_run) + return ci.Run(command.command_id, command.command, async_run=command.async_run) elif command.operation == operationTypes.UPLOAD: return ci.Upload(command.command_id, command.client_file_path, command.file_position) elif command.operation == operationTypes.DOWNLOAD: return ci.Download(command.command_id, command.client_file_path) elif command.operation == operationTypes.QUIT: command.status = cmdStatusTypes.COMPLETE - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) client = Clients.query.filter_by(hostname=host).first() client.status = clientStatusTypes.UNINSTALLED db.session.commit() @@ -311,7 +311,7 @@ def post(self): # update last_activity and status client = Clients.query.filter_by(hostname=host).one() client.status = clientStatusTypes.BUSY - client.last_activity = datetime.utcnow() + client.last_activity = datetime.now(UTC) db.session.commit() # Note: the client posts run results as they come in or after a certain timeout with no output from running command @@ -328,18 +328,18 @@ def post(self): if command.status == cmdStatusTypes.PENDING: if cmd_status_flag_done: command.status = cmdStatusTypes.COMPLETE - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) logging.info("Command status set to COMPLETE for command {}".format(cid)) elif 'done' not in request.args: logging.warning("DONE flag missing from arguments for command {}".format(cid)) command.status = cmdStatusTypes.COMPLETE - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) else: command.status = cmdStatusTypes.STARTED logging.info("Command status set to STARTED for command {}".format(cid)) if command.status == cmdStatusTypes.STARTED and cmd_status_flag_done: command.status = cmdStatusTypes.COMPLETE - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) logging.info("Command status set to COMPLETE for command {}".format(cid)) #statinfo = os.stat(os.path.join(BASE_DIR, command.server_file_path)) db.session.commit() @@ -372,7 +372,7 @@ def post(self): # update last_activity and status client = Clients.query.filter_by(hostname=host).one() client.status = clientStatusTypes.BUSY - client.last_activity = datetime.utcnow() + client.last_activity = datetime.now(UTC) db.session.commit() stream_error = receive_streamed_data(command) @@ -389,13 +389,13 @@ def post(self): logger.info("Upload command {} completed sucessfully - file: {}".format(command.command_id, command.server_file_path)) command.status = cmdStatusTypes.COMPLETE - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) db.session.commit() else: logger.warn("{} indicates upload command {} complete, however, {}/{} filesize mismatch".format(host, command.command_id, statinfo.st_size, command.filesize)) command.status = cmdStatusTypes.UNKNOWN - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) db.session.commit() return True @@ -418,7 +418,7 @@ def get(self): except FileNotFoundError as e: logger.error("FileNotFoundError: {} on this server".format(str(e))) command.status = cmdStatusTypes.ERROR - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) command.log_file_path = "FileNotFoundError" db.session.commit() return Response() @@ -426,7 +426,7 @@ def get(self): if command.file_position == statinfo.st_size: logger.warning("File at same path and of same size is already on {}. Previously repeated command?".format(host)) command.status = cmdStatusTypes.COMPLETE - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) db.session.commit() logger.info("Download command {} completed successfully".format(command.command_id)) return Response() @@ -446,7 +446,7 @@ def stream_response(): if error_message is None: command.status = cmdStatusTypes.COMPLETE - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) db.session.commit() logger.info("Download command {} completed successfully".format(command.command_id)) else: @@ -458,7 +458,7 @@ def stream_response(): # update last_activity and status client = Clients.query.filter_by(hostname=host).one() client.status = clientStatusTypes.BUSY - client.last_activity = datetime.utcnow() + client.last_activity = datetime.now(UTC) db.session.commit() return Response(stream_with_context(stream_response())) @@ -501,10 +501,10 @@ def post(self): command.status = cmdStatusTypes.PENDING else: command.status = cmdStatusTypes.ERROR - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) # update last_activity client = Clients.query.filter_by(hostname=host).one() - client.last_activity = datetime.utcnow() + client.last_activity = datetime.now(UTC) db.session.commit() error_log = {'time': datetime.now(pytz.utc).strftime('%Y-%m-%d %H:%M:%S%z'), 'command_id': str(command.command_id), @@ -822,7 +822,7 @@ def post(self): command = Commands.query.filter(Commands.command_id==command_id).one() if command: command.status = cmdStatusTypes.CANCELED - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) db.session.commit() return command.to_dict() return {'status_code':'404', @@ -881,7 +881,7 @@ def post(self): logger.error("{} indicates upload command {} complete, however, {}/{} filesize mismatch".format(host, command.command_id, statinfo.st_size, command.filesize)) command.status = cmdStatusTypes.UNKNOWN - command.evaluated_time = datetime.utcnow() + command.evaluated_time = datetime.now(UTC) db.session.commit() return command.to_dict() diff --git a/setup.py b/setup.py index c269122..35af36e 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ from codecs import open from os import path -__version__ = "0.0.24" +__version__ = "0.0.25" description = "Libraries and utilities for controling and working with Live Endpoint Response Clients." here = path.abspath(path.dirname(__file__))