def install(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) command_client = APIClient(db.get_configure()).get_command_api_client() enterprise_id = db.get_enterprise_id() device_client = APIClient(db.get_configure()).get_device_api_client() if self.app.pargs.device: device_name = self.app.pargs.device kwargs = {'name': device_name} try: search_response = device_client.get_all_devices(enterprise_id, limit=1, offset=0, **kwargs) if not search_response.results or len(search_response.results) == 0: self.app.log.debug(f'[device-command-install] Device does not exist with name {device_name}') self.app.render(f'Device does not exist with name {device_name}\n') return response = search_response.results[0] device_id = response.id except ApiException as e: self.app.log.error(f"[device-command-install] Failed to list devices: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n") return else: device = db.get_device() if not device or not device.get('id'): self.app.log.debug('[device-command-install] There is no active device.') self.app.render('There is no active device.\n') return device_id = device.get('id') version_id = self.app.pargs.version command_request = CommandRequest(command_args={"app_version": version_id}, command=DeviceCommandEnum.INSTALL.name) try: response = command_client.run_command(enterprise_id, device_id, command_request) except ApiException as e: self.app.log.error(f"[device-command-install] Failed to fire the install command: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n") return if not self.app.pargs.json: renderable = self._command_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._command_basic_response(response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)
def set_active(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) device_client = APIClient(db.get_configure()).get_device_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.name: device_name = self.app.pargs.name kwargs = {'name': device_name} try: search_response = device_client.get_all_devices(enterprise_id, limit=1, offset=0, **kwargs) if not search_response.results or len(search_response.results) == 0: self.app.log.debug(f'[device-active] Device does not exist with name {device_name}') self.app.render(f'Device does not exist with name {device_name}\n') return response = search_response.results[0] db.set_device({'id': response.id, 'name': response.device_name}) except ApiException as e: self.app.log.error(f"[device-active] Failed to list devices: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n") return else: device = db.get_device() if device is None or device.get('name') is None: self.app.log.debug('[device-active] There is no active device.') self.app.render('There is no active device.\n') return device_id = device.get('id') try: response = device_client.get_device_by_id(enterprise_id, device_id) except ApiException as e: self.app.log.error(f"[device-active] Failed to show active device: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n") return if not self.app.pargs.json: renderable = self._device_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._device_basic_response(response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)
def connect(self): """Setup and connect securely via Remote ADB to device""" validate_creds_exists(self.app) db = DBWrapper(self.app.creds) enterprise_id = db.get_enterprise_id() # Remove older certs cleanup_certs(self.app) # Create new certs create_self_signed_cert(local_cert=self.app.local_cert, local_key=self.app.local_key) try: # Get device device_id = None if self.app.pargs.device_name: device_id = self._fetch_device_by_name( self.app.pargs.device_name) self.app.log.debug( f"Device Name: {self.app.pargs.device_name}. Device ID: {device_id}" ) elif db.get_device(): device_id = db.get_device().get('id') else: self.app.log.error("[remoteadb-connect] Device not specified!") return self.app.render( "\nInitiating Remote ADB Session. This may take a few seconds...\n" ) # Call SCAPI for establish remote adb connection with device remoteadb_id = initiate_remoteadb_connection( environment=db.get_configure().get("environment"), enterprise_id=enterprise_id, device_id=device_id, api_key=db.get_configure().get("api_key"), client_cert_path=self.app.local_cert, log=self.app.log) # Poll and fetch the TCP relay's endpoint relay_ip, relay_port = fetch_relay_endpoint( environment=db.get_configure().get("environment"), enterprise_id=enterprise_id, device_id=device_id, remoteadb_id=remoteadb_id, api_key=db.get_configure().get("api_key"), log=self.app.log) # Poll and fetch the Device's Certificate String device_cert = fetch_device_certificate( environment=db.get_configure().get("environment"), enterprise_id=enterprise_id, device_id=device_id, remoteadb_id=remoteadb_id, api_key=db.get_configure().get("api_key"), log=self.app.log) # Save Device certificate to disk save_device_certificate(self.app.device_cert, device_cert) # Setup an SSL connection to TCP relay secure_sock = self.setup_ssl_connection( host=relay_ip, port=relay_port, client_cert=self.app.local_cert, client_key=self.app.local_key, device_cert=self.app.device_cert) relay = Relay(relay_conn=secure_sock, relay_addr=secure_sock.getsockname(), log=self.app.log) listener_ip, listener_port = relay.get_listener_address() title = "Secure ADB Client" table = [ { title: f"Please connect ADB client to the following endpoint: {listener_ip} : {listener_port}" }, { title: f"If adb-tools is installed, please run the command below:\n adb connect {listener_ip}:{listener_port}" }, { title: "Press Ctrl+C to quit! " }, ] self.app.render(table, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") self.app.log.debug("[remoteadb-connect] Starting Client Mediator") relay.accept_connection() relay.start_relay() except (SecureADBWorkflowError, RemoteADBError) as timeout_exc: self.app.log.error(f"[remoteadb-connect] {str(timeout_exc)}") self.app.render( f"[ERROR] Issue in reaching Esper API Service for connection negotiation!" ) except CaughtSignal as sig: self.app.log.debug( f"Recieved Signal: {signal.Signals(sig.signum).name}") if sig.signum == signal.SIGINT: self.app.render("Quitting application...") except Exception as exc: self.app.log.error( f"Failed to establish Secure ADB connection to device: {self.app.pargs.device_name}" ) self.app.log.debug(f"Exception Encountered -> {exc}") finally: if "relay" in locals(): relay = locals().get("relay") relay.stop_relay() metrics = relay.gather_metrics() relay.cleanup_connections() if metrics.get('started') and metrics.get('stopped'): self.app.render( f"\nSession Duration: {metrics.get('stopped') - metrics.get('started')}" ) if metrics.get('bytes'): self.app.render( f"\nTotal Data streamed: {metrics.get('bytes')/1024.0} KB\n" )
def latest(self): """Command to list status""" validate_creds_exists(self.app) db = DBWrapper(self.app.creds) device_client = APIClient(db.get_configure()).get_device_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.device: device_name = self.app.pargs.device kwargs = {'name': device_name} try: search_response = device_client.get_all_devices(enterprise_id, limit=1, offset=0, **kwargs) if not search_response.results or len( search_response.results) == 0: self.app.log.debug( f'[status-latest] Device does not exist with name {device_name}' ) self.app.render( f'Device does not exist with name {device_name}') return response = search_response.results[0] device_id = response.id except ApiException as e: self.app.log.error( f"[status-latest] Failed to list devices: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return else: device = db.get_device() if not device or not device.get('id'): self.app.log.debug( '[status-latest] There is no active device.') self.app.render('There is no active device.') return device_id = device.get('id') try: response = device_client.get_device_event(enterprise_id, device_id, latest_event=1) except ApiException as e: self.app.log.error( f"[status-latest] Failed to get latest device status: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return battery_level = None battery_temp = None data_download = None data_upload = None memory_storage = None memory_ram = None link_speed = None signal_strength = None if response.results and len(response.results) > 0: data = literal_eval(response.results[0].data) if data.get("powerManagementEvent") and data.get( "powerManagementEvent").get("batteryStatus"): if data.get("powerManagementEvent").get("batteryStatus").get( "batteryLevel"): battery_level = data.get("powerManagementEvent").get( "batteryStatus").get("batteryLevel") if data.get("powerManagementEvent").get("batteryStatus").get( "batteryTemperature"): battery_temp = data.get("powerManagementEvent").get( "batteryStatus").get("batteryTemperature") if data.get("dataUsageStats"): if data.get("dataUsageStats").get("totalDataDownload"): data_download = data.get("dataUsageStats").get( "totalDataDownload") if data.get("dataUsageStats").get("totalDataUpload"): data_upload = data.get("dataUsageStats").get( "totalDataUpload") if data.get("memoryEvents") and len(data.get("memoryEvents")) > 1 and \ data.get("memoryEvents")[1].get("countInMb"): memory_storage = data.get("memoryEvents")[1].get("countInMb") if data.get("memoryEvents") and len(data.get("memoryEvents")) > 0 and \ data.get("memoryEvents")[0].get("countInMb"): memory_ram = data.get("memoryEvents")[0].get("countInMb") if data.get("networkEvent") and data.get("networkEvent").get( "wifiNetworkInfo"): if data.get("networkEvent").get("wifiNetworkInfo").get( "linkSpeed"): link_speed = data.get("networkEvent").get( "wifiNetworkInfo").get("linkSpeed") if data.get("networkEvent").get("wifiNetworkInfo").get( "signalStrength"): signal_strength = data.get("networkEvent").get( "wifiNetworkInfo").get("signalStrength") if not self.app.pargs.json: title = "TITLE" details = "DETAILS" renderable = [{ title: 'battery_level', details: battery_level }, { title: 'battery_temperature', details: battery_temp }, { title: 'data_download', details: data_download }, { title: 'data_upload', details: data_upload }, { title: 'memory_storage', details: memory_storage }, { title: 'memory_ram', details: memory_ram }, { title: 'link_speed', details: link_speed }, { title: 'signal_strength', details: signal_strength }] self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = { 'battery_level': battery_level, 'battery_temperature': battery_temp, 'data_download': data_download, 'data_upload': data_upload, 'memory_storage': memory_storage, 'memory_ram': memory_ram, 'link_speed': link_speed, 'signal_strength': signal_strength } self.app.render(renderable, format=OutputFormat.JSON.value)
def list(self): """Command to list installs""" validate_creds_exists(self.app) db = DBWrapper(self.app.creds) device_client = APIClient(db.get_configure()).get_device_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.device: device_name = self.app.pargs.device kwargs = {'name': device_name} try: search_response = device_client.get_all_devices(enterprise_id, limit=1, offset=0, **kwargs) if not search_response.results or len( search_response.results) == 0: self.app.log.debug( f'[installs-list] Device does not exist with name {device_name}' ) self.app.render( f'Device does not exist with name {device_name}') return response = search_response.results[0] device_id = response.id except ApiException as e: self.app.log.error( f"[installs-list] Failed to list devices: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return else: device = db.get_device() if not device or not device.get('id'): self.app.log.debug( '[installs-list] There is no active device.') self.app.render('There is no active device.') return device_id = device.get('id') app_name = self.app.pargs.appname package_name = self.app.pargs.package install_state = self.app.pargs.state limit = self.app.pargs.limit offset = self.app.pargs.offset kwargs = {} if app_name: kwargs['application_name'] = app_name if package_name: kwargs['package_name'] = package_name if install_state: kwargs['install_state'] = install_state try: response = device_client.get_app_installs(enterprise_id, device_id, limit=limit, offset=offset, **kwargs) except ApiException as e: self.app.log.error(f"[installs-list] Failed to list installs: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return self.app.render(f"Total Number of Installs: {response.count}") if not self.app.pargs.json: installs = [] label = { 'id': "ID", 'application_name': "APPLICATION", 'package_name': "PACKAGE", 'version_code': "VERSION", 'install_state': "STATE" } for install in response.results: installs.append({ label['id']: install.id, label['application_name']: install.application.application_name, label['package_name']: install.application.package_name, label['version_code']: install.application.version.version_code, label['install_state']: install.install_state }) self.app.render(installs, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: installs = [] for install in response.results: installs.append({ 'id': install.id, 'application_name': install.application.application_name, 'package_name': install.application.package_name, 'version_code': install.application.version.version_code, 'install_state': install.install_state }) self.app.render(installs, format=OutputFormat.JSON.value)
def wipe(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) command_client = APIClient(db.get_configure()).get_command_api_client() enterprise_id = db.get_enterprise_id() device_client = APIClient(db.get_configure()).get_device_api_client() if self.app.pargs.device: device_name = self.app.pargs.device kwargs = {'name': device_name} try: search_response = device_client.get_all_devices(enterprise_id, limit=1, offset=0, **kwargs) if not search_response.results or len( search_response.results) == 0: self.app.log.debug( f'[device-command-wipe] Device does not exist with name {device_name}' ) self.app.render( f'Device does not exist with name {device_name}') return response = search_response.results[0] device_id = response.id except ApiException as e: self.app.log.error( f"[device-command-wipe] Failed to list devices: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return else: device = db.get_device() if not device or not device.get('id'): self.app.log.debug( '[device-command-wipe] There is no active device.') self.app.render('There is no active device.') return device_id = device.get('id') external_storage = self.app.pargs.external_storage frp = self.app.pargs.frp if external_storage is None: self.app.log.info( '[device-command-wipe] External storage value is empty') self.app.render('External storage value is empty') if frp is None: self.app.log.info( '[device-command-wipe] Factory reset production value is empty' ) self.app.render('Factory reset production value is empty') command_request = CommandRequest(command_args={ "wipe_external_storage": external_storage, 'wipe_FRP': frp }, command=DeviceCommandEnum.WIPE.name) try: response = command_client.run_command(enterprise_id, device_id, command_request) except ApiException as e: self.app.log.error( f"[device-command-wipe] Failed to fire the wipe command: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if not self.app.pargs.json: renderable = self._command_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._command_basic_response(response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)