def fetch_args(self): results = {} validate_creds_exists(self.app) db = DBWrapper(self.app.creds) results["environment"] = db.get_configure().get("environment") results["enterprise_id"] = db.get_enterprise_id() results["api_key"] = db.get_configure().get("api_key") if hasattr(self.app.pargs, "pipeline_id"): pipeline_id = self.app.pargs.pipeline_id if not pipeline_id: pipeline_id = prompt.query("Enter the Pipeline ID: ") results["pipeline_id"] = pipeline_id if hasattr(self.app.pargs, "execution_id"): execution_id = self.app.pargs.execution_id if not execution_id: execution_id = prompt.query("Enter the Execution ID: ") results["execution_id"] = execution_id if hasattr(self.app.pargs, "reason"): reason = self.app.pargs.reason if not reason: reason = prompt.query( "Why do you want to stop this Execution? : ") results["reason"] = reason return results
def remove(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) environment = db.get_configure().get("environment") enterprise_id = db.get_enterprise_id() pipeline_id = self.app.pargs.pipeline_id if not pipeline_id: pipeline_id = prompt.query("Enter the Pipeline ID: ") # Calling Pipeline Graphs API url = get_pipeline_url(environment, enterprise_id, pipeline_id=pipeline_id) api_key = db.get_configure().get("api_key") try: self.app.log.debug("Removing Pipeline...") response = delete_api(url, api_key) except APIException: self.app.render("ERROR in connecting to Environment!\n") return if not response.ok: self.app.log.debug(f"Response not OK. Status Code: {response.status_code}") self.app.log.debug(f"Response not OK. Response: {response.json()}") if response.status_code == 404: self.app.log.error("Pipeline not found!") if response.status_code == 500: self.app.log.error(f"Internal Server Error! {response.json()}") return self.app.render(f"Removed Pipeline Successfully! \n")
def lock(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-lock] 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-lock] 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-lock] There is no active device.') self.app.render('There is no active device.') return device_id = device.get('id') command_request = CommandRequest(command=DeviceCommandEnum.LOCK.name) try: response = command_client.run_command(enterprise_id, device_id, command_request) except ApiException as e: self.app.log.error( f"[device-command-lock] Failed to fire the lock 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)
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}\n') 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)}\n") 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.\n') 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\n') 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\n') 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)}\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 delete(self): application_id = self.app.pargs.application_id validate_creds_exists(self.app) db = DBWrapper(self.app.creds) application_client = APIClient( db.get_configure()).get_application_api_client() enterprise_id = db.get_enterprise_id() try: application_client.delete_application(application_id, enterprise_id) self.app.log.debug( f"[application-delete] Application with id : {application_id} deleted successfully" ) self.app.render( f"Application with id {application_id} deleted successfully") # Unset current application if matching application = db.get_application() if application and application.get( 'id') and application_id == application.get('id'): db.unset_application() self.app.log.debug( f'[application-delete] Unset the active application {application_id}' ) except ApiException as e: self.app.log.debug( f"[application-delete] Failed to delete an application: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return
def list(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) group_client = APIClient(db.get_configure()).get_group_api_client() enterprise_id = db.get_enterprise_id() name = self.app.pargs.name limit = self.app.pargs.limit offset = self.app.pargs.offset kwargs = {} if name: kwargs['name'] = name try: response = group_client.get_all_groups(enterprise_id, limit=limit, offset=offset, **kwargs) except ApiException as e: self.app.log.error(f"[group-list] Failed to list groups: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if not self.app.pargs.json: groups = [] label = { 'id': "ID", 'name': "NAME", 'device_count': "DEVICE COUNT" } for group in response.results: groups.append({ label['id']: group.id, label['name']: group.name, label['device_count']: group.device_count if group.device_count else 0 }) self.app.render(f"Number of Groups: {response.count}") self.app.render(groups, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: groups = [] for group in response.results: groups.append({ 'id': group.id, 'name': group.name, 'device_count': group.device_count if group.device_count else 0 }) self.app.render(f"Number of Groups: {response.count}") self.app.render(groups, format=OutputFormat.JSON.value)
def show(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) group_client = APIClient(db.get_configure()).get_group_api_client() enterprise_id = db.get_enterprise_id() group_name = self.app.pargs.group_name kwargs = {'name': group_name} try: search_response = group_client.get_all_groups(enterprise_id, limit=1, offset=0, **kwargs) response = None for group in search_response.results: if group.name == group_name: response = group break if not response: self.app.log.info(f'[group-show] Group does not exist with name {group_name}') self.app.render(f'Group does not exist with name {group_name}') return except ApiException as e: self.app.log.error(f"[group-show] Failed to list groups: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if self.app.pargs.active: db.set_group({'id': response.id, 'name': group_name}) if not self.app.pargs.json: renderable = self._group_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._group_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}') 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)}") 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.') 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)}") 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 show(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) enterprise_client = APIClient( db.get_configure()).get_enterprise_api_client() enterprise_id = db.get_enterprise_id() try: response = enterprise_client.get_enterprise(enterprise_id) except ApiException as e: self.app.log.error( f"[enterprise-show] Failed to show details of an enterprise: {e}" ) self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if not self.app.pargs.json: renderable = self._enterprise_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._enterprise_basic_response( response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)
def create(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) group_client = APIClient(db.get_configure()).get_group_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.name: data = DeviceGroup(name=self.app.pargs.name) else: self.app.log.debug('[group-create] name cannot be empty.') self.app.render('name cannot be empty.') return try: response = group_client.create_group(enterprise_id, data) except ApiException as e: self.app.log.error(f"[group-create] Failed to create a group: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if not self.app.pargs.json: renderable = self._group_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._group_basic_response(response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)
def show(self): version_id = self.app.pargs.version_id validate_creds_exists(self.app) db = DBWrapper(self.app.creds) application_client = APIClient(db.get_configure()).get_application_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.application: application_id = self.app.pargs.application else: application = db.get_application() if not application or not application.get('id'): self.app.log.debug('[version-show] There is no active application.') self.app.render('There is no active application.\n') return application_id = application.get('id') try: response = application_client.get_app_version(version_id, application_id, enterprise_id) except ApiException as e: self.app.log.error(f"[version-show] Failed to show details of an version: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n") return if not self.app.pargs.json: renderable = self._version_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._version_basic_response(response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)
def configure(self): """Configure the credentials and host endpoints of the customer""" # Trigger the Insert operation, if --set is given OR if the Creds DB is empty db = DBWrapper(self.app.creds) credentials = db.get_configure() if self.app.pargs.set or not credentials: environment = input("Environment name: ") api_key = prompt.query("Esper API Key: ") token_client = APIClient({'api_key': api_key, 'environment': environment}).get_token_api_client() try: response = token_client.get_token_info() except ApiException as e: self.app.log.error(f"[configure] Failed to get token info: {e}") if e.status == HTTPStatus.UNAUTHORIZED: self.app.render("You are not authorized, invalid API Key.") else: error_message = json.loads(e.body).get('message') if e.body and json.loads(e.body).get( 'message') else e.reason self.app.render(f"ERROR: {error_message}") return if response: enterprise_id = response.enterprise else: self.app.log.info(f"[configure] API key is not associated with any enterprise.") self.app.render("API key is not associated with any enterprise.") return credentials = { "environment": environment, "api_key": api_key, "enterprise_id": enterprise_id } # set new credentials into the DB self.app.log.debug("Purging and inserting new credentials DB...") db.set_configure(credentials) # Trigger listing operation, if --list is given or Creds DB has content if self.app.pargs.list or credentials: validate_creds_exists(self.app) if not self.app.pargs.json: title = "TITLE" details = "DETAILS" renderable = [ {title: 'environment', details: credentials.get('environment')}, {title: 'api_key', details: credentials.get('api_key')} ] self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = { 'environment': credentials.get('environment'), 'api_key': credentials.get('api_key') } self.app.render(renderable, format=OutputFormat.JSON.value)
def get_groups_list(self, limit=20, offset=0): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) group_client = APIClient(db.get_configure()).get_group_api_client() enterprise_id = db.get_enterprise_id() try: response = group_client.get_all_groups(enterprise_id, limit=limit, offset=offset) except ApiException as e: self.app.log.error(f"[group-list] Failed to list groups: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n") return groups = [] for group in response.results: groups.append({ 'id': group.id, 'name': group.name, 'device_count': group.device_count if group.device_count else 0 }) return response.count, groups
def delete(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) group_client = APIClient(db.get_configure()).get_group_api_client() enterprise_id = db.get_enterprise_id() group_name = self.app.pargs.name kwargs = {'name': group_name} try: search_response = group_client.get_all_groups(enterprise_id, limit=1, offset=0, **kwargs) if not search_response.results or len(search_response.results) == 0: self.app.log.debug(f'[group-delete] Group does not exist with name {group_name}') self.app.render(f'Group does not exist with name {group_name}') return response = search_response.results[0] group_id = response.id except ApiException as e: self.app.log.error(f"[group-update] Failed to list groups: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return try: group_client.delete_group(group_id, enterprise_id) self.app.log.debug(f"[group-update] Group with name {group_name} deleted successfully") self.app.render(f"Group with name {group_name} deleted successfully") # Unset current group if matching group = db.get_group() if group and group.get('id') and group_id == group.get('id'): db.unset_group() self.app.log.debug(f'[group-update] Unset the active group {group_name}') except ApiException as e: self.app.log.error(f"[group-update] Failed to delete group: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return
def update(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) enterprise_client = APIClient( db.get_configure()).get_enterprise_api_client() enterprise_id = db.get_enterprise_id() data = EnterpriseUpdate() if self.app.pargs.name: data.name = self.app.pargs.name if self.app.pargs.display_name: data.display_name = self.app.pargs.display_name details = {} if self.app.pargs.registered_name: details['registered_name'] = self.app.pargs.registered_name if self.app.pargs.address: details['registered_address'] = self.app.pargs.address if self.app.pargs.location: details['location'] = self.app.pargs.location if self.app.pargs.zipcode: details['zipcode'] = self.app.pargs.zipcode if self.app.pargs.email: details['contact_email'] = self.app.pargs.email if self.app.pargs.contact_person: details['contact_person'] = self.app.pargs.contact_person if self.app.pargs.contact_number: details['contact_number'] = self.app.pargs.contact_number if bool(details): data.details = details try: response = enterprise_client.partial_update_enterprise( enterprise_id, data) except ApiException as e: self.app.log.error( f"[enterprise-update] Failed to update details of an enterprise: {e}" ) self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if not self.app.pargs.json: renderable = self._enterprise_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._enterprise_basic_response( response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)
def list(self): """Command to list applications""" validate_creds_exists(self.app) db = DBWrapper(self.app.creds) application_client = APIClient( db.get_configure()).get_application_api_client() enterprise_id = db.get_enterprise_id() name = self.app.pargs.name package = self.app.pargs.package limit = self.app.pargs.limit offset = self.app.pargs.offset kwargs = {} if name: kwargs['application_name'] = name if package: kwargs['package_name'] = package kwargs['is_hidden'] = False try: # Find applications in an enterprise response = application_client.get_all_applications(enterprise_id, limit=limit, offset=offset, **kwargs) except ApiException as e: self.app.log.error( f"[application-list] Failed to list applications: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return self.app.render(f"Total Number of Applications: {response.count}") if not self.app.pargs.json: applications = [] label = {'id': "ID", 'name': "NAME", 'package': "PACKAGE NAME"} for application in response.results: applications.append({ label['id']: application.id, label['name']: application.application_name, label['package']: application.package_name }) self.app.render(applications, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: applications = [] for application in response.results: applications.append({ 'id': application.id, 'name': application.application_name, 'package': application.package_name }) self.app.render(applications, format=OutputFormat.JSON.value)
def validate_creds_exists(app): db = DBWrapper(app.creds) if not db.get_configure(): app.log.error("[validate_creds_exists] Credentials have not been set!") app.log.info( "[validate_creds_exists] Setup credentials by calling `configure` command." ) sys.exit(1)
def download(self): version_id = self.app.pargs.version_id validate_creds_exists(self.app) db = DBWrapper(self.app.creds) application_client = APIClient( db.get_configure()).get_application_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.application: application_id = self.app.pargs.application else: application = db.get_application() if not application or not application.get('id'): self.app.log.debug( '[app-download] There is no active application.') self.app.render('There is no active application.') return application_id = application.get('id') if self.app.pargs.dest: destination = self.app.pargs.dest else: self.app.log.debug( '[app-download] destination file path cannot be empty.') self.app.render('destination file path cannot be empty.') return try: response = application_client.get_app_version( version_id, application_id, enterprise_id) except ApiException as e: self.app.log.error( f"[app-download] Failed to show details of an version: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return url = response.app_file file_size = int(response.size_in_mb * 1024 * 1024) first_byte = 0 pbar = tqdm(total=file_size, initial=first_byte, unit='B', unit_scale=True, desc='Downloading......') req = requests.get(url, stream=True) with (open(destination, 'ab')) as f: for chunk in req.iter_content(chunk_size=1024): if chunk: f.write(chunk) pbar.update(1024) time.sleep(0.001) pbar.close()
def set_active(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) group_client = APIClient(db.get_configure()).get_group_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.name: group_name = self.app.pargs.name kwargs = {'name': group_name} try: search_response = group_client.get_all_groups(enterprise_id, limit=1, offset=0, **kwargs) if not search_response.results or len( search_response.results) == 0: self.app.log.info( f'[group-active] Group does not exist with name {group_name}' ) self.app.render( f'Group does not exist with name {group_name}') return response = search_response.results[0] db.set_group({'id': response.id, 'name': group_name}) except ApiException as e: self.app.log.error( f"[group-active] Failed to list groups: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return else: group = db.get_group() if group is None or group.get('name') is None: self.app.log.debug('[group-active] There is no active group.') self.app.render('There is no active group.') return group_id = group.get('id') try: response = group_client.get_group_by_id( group_id, enterprise_id) except ApiException as e: self.app.log.error( f"[group-active] Failed to show active group: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if not self.app.pargs.json: renderable = self._group_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._group_basic_response(response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)
def update(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) group_client = APIClient(db.get_configure()).get_group_api_client() enterprise_id = db.get_enterprise_id() data = DeviceGroupUpdate() group_name = self.app.pargs.name kwargs = {'name': group_name} try: search_response = group_client.get_all_groups(enterprise_id, limit=1, offset=0, **kwargs) if not search_response.results or len( search_response.results) == 0: self.app.log.debug( f'[group-update] Group does not exist with name {group_name}' ) self.app.render(f'Group does not exist with name {group_name}') return response = search_response.results[0] group_id = response.id except ApiException as e: self.app.log.error(f"[group-update] Failed to list groups: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if self.app.pargs.new_name: data.name = self.app.pargs.new_name else: self.app.log.debug('[group-update] name cannot be empty.') self.app.render('name cannot be empty.') return try: response = group_client.partial_update_group( group_id, enterprise_id, data) except ApiException as e: self.app.log.error( f"[group-update] Failed to update details of a group: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if not self.app.pargs.json: renderable = self._group_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._group_basic_response(response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)
def validate_group_name(self, name) -> DeviceGroup: validate_creds_exists(self.app) db = DBWrapper(self.app.creds) group_client = APIClient(db.get_configure()).get_group_api_client() enterprise_id = db.get_enterprise_id() response = group_client.get_all_groups(enterprise_id, name=name) if response.count > 0: return response.results[0] else: raise ApiException("No such Group-Name found!")
def set_active(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) application_client = APIClient( db.get_configure()).get_application_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.id: application_id = self.app.pargs.id try: response = application_client.get_application( application_id, enterprise_id) db.set_application({'id': application_id}) except ApiException as e: self.app.log.error( f"[application-active] Failed to show active application: {e}" ) self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return else: application = db.get_application() if application is None or application.get('id') is None: self.app.log.debug( '[application-active] There is no active application.') self.app.render('There is no active application.') return application_id = application.get('id') try: response = application_client.get_application( application_id, enterprise_id) db.set_application({'id': application_id}) except ApiException as e: self.app.log.error( f"[application-active] Failed to show active application: {e}" ) self.app.render(f"ERROR: {parse_error_message(self.app, e)}") return if not self.app.pargs.json: renderable = self._application_basic_response(response) self.app.render(renderable, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: renderable = self._application_basic_response( response, OutputFormat.JSON) self.app.render(renderable, format=OutputFormat.JSON.value)
def show(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) device_name = self.app.pargs.device_name device_client = APIClient(db.get_configure()).get_device_api_client() enterprise_id = db.get_enterprise_id() 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-show] 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] except ApiException as e: self.app.log.error(f"[device-show] Failed to list devices: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n") return if self.app.pargs.active: name, _ = self.get_name_and_tags_from_device(response) db.set_device({'id': response.id, 'name': name}) 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 _fetch_device_by_name(self, name: str) -> str: """ Fetch the device entry by its device-name :param name: Device Name :return: uuid str - Device ID as UUID string """ db = DBWrapper(self.app.creds) device_name = name device_client = APIClient(db.get_configure()).get_device_api_client() enterprise_id = db.get_enterprise_id() kwargs = {'name': device_name} 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: raise SecureADBWorkflowError(f'Device does not exist with name {device_name}') return search_response.results[0].id
def delete(self): version_id = self.app.pargs.version_id validate_creds_exists(self.app) db = DBWrapper(self.app.creds) application_client = APIClient(db.get_configure()).get_application_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.application: application_id = self.app.pargs.application else: application = db.get_application() if not application or not application.get('id'): self.app.log.debug('[version-delete] There is no active application.') self.app.render('There is no active application.\n') return application_id = application.get('id') try: application_client.delete_app_version(version_id, application_id, enterprise_id) self.app.log.debug(f"[version-delete] Version with id : {version_id} deleted successfully") self.app.render(f"Version with id {version_id} deleted successfully\n") except ApiException as e: self.app.log.error(f"[version-delete] Failed to delete a version: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n") return # Unset current application if matching try: application_client.get_application(application_id, enterprise_id) except ApiException as e: if e.status == HTTPStatus.NOT_FOUND: application = db.get_application() if application and application.get('id') and application_id == application.get('id'): db.unset_application() self.app.log.debug(f'[version-delete] Unset the active application {application_id}') else: self.app.log.debug(f"[version-delete] Failed to get an application when deleting a version: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n")
def show(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) environment = db.get_configure().get("environment") enterprise_id = db.get_enterprise_id() pipeline_id = self.app.pargs.pipeline_id if not pipeline_id: pipeline_id = prompt.query("Enter the Pipeline ID: ") stage_id = self.app.pargs.stage_id if not stage_id: stage_id = prompt.query("Enter the Stage ID: ") # Calling Pipeline Graphs API url = get_operation_url(environment, enterprise_id, pipeline_id=pipeline_id, stage_id=stage_id) api_key = db.get_configure().get("api_key") try: self.app.log.debug("Listing Operations...") response = list_stages(url, api_key) except APIException: self.app.render("ERROR in connecting to Environment!\n") return if not response.ok: self.app.log.debug( f"Response not OK. Status Code: {response.status_code}") self.app.log.debug(f"Response not OK. Response: {response.json()}") if response.status_code == 400: errors = response.json().get('meta', {}).get('non_field_errors') if errors: self.app.log.error(f"Validation Error: {errors}") if response.json().get("errors"): self.app.log.error( f"Validation Error: {response.json().get('errors')}") if response.status_code == 404: self.app.log.error("Stage URL not found!") if response.status_code == 500: self.app.log.error(f"Internal Server Error! {response.json()}") return # Rendering table with populated values data = response.json().get("results") render_data = [] for stage in data: render_pipeline = { "ID": stage.get("id"), "NAME": stage.get("name"), "DESCRIPTION": stage.get("description"), "ORDERING": stage.get("ordering"), "ACTION": stage.get("action"), "VERSION": stage.get("version") } render_data.append(render_pipeline) self.app.render(f"Listing Operations for the Stage! Details: \n") self.app.render(render_data, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain")
def edit(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) environment = db.get_configure().get("environment") enterprise_id = db.get_enterprise_id() pipeline_id = self.app.pargs.pipeline_id if not pipeline_id: pipeline_id = prompt.query("Enter the Pipeline ID: ") stage_id = self.app.pargs.stage_id if not stage_id: stage_id = prompt.query("Enter the Stage ID: ") operation_id = self.app.pargs.operation_id if not operation_id: operation_id = prompt.query("Enter the Operation ID: ") name = self.app.pargs.name if not name: name = input("Change the name of the Operation: ") desc = self.app.pargs.desc if not desc: desc = input( "Change the description for this Operation [optional]: ") action = self.app.pargs.action if not action: p = Prompt("Action for this Operation: ", options=ActionEnums.choices_values(), numbered=True) action = ActionEnums(p.input).name # Calling Pipeline Graphs API url = get_operation_url(environment, enterprise_id, pipeline_id=pipeline_id, stage_id=stage_id, operation_id=operation_id) api_key = db.get_configure().get("api_key") try: self.app.log.debug("Editing Operation...") response = edit_operation(url, api_key, name, action, desc) except APIException: self.app.render("ERROR in connecting to Environment!\n") return if not response.ok: self.app.log.debug( f"Response not OK. Status Code: {response.status_code}") self.app.log.debug(f"Response not OK. Response: {response.json()}") if response.status_code == 400: errors = response.json().get('meta', {}).get('non_field_errors') if errors: self.app.log.error(f"Validation Error: {errors}") if response.json().get("errors"): self.app.log.error( f"Validation Error: {response.json().get('errors')}") if response.status_code == 404: self.app.log.error("Pipeline URL not found!") if response.status_code == 500: self.app.log.error(f"Internal Server Error! {response.json()}") return # Rendering table with populated values data = render_single_dict(response.json()) self.app.render( f"Edited Operation for this Stage Successfully! Details: \n") self.app.render(data, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain")
def create(self): validate_creds_exists(self.app) db = DBWrapper(self.app.creds) environment = db.get_configure().get("environment") enterprise_id = db.get_enterprise_id() pipeline_id = self.app.pargs.pipeline_id if not pipeline_id: pipeline_id = prompt.query("Enter the Pipeline ID: ") stage_id = self.app.pargs.stage_id if not stage_id: stage_id = prompt.query("Enter the Stage ID: ") name = self.app.pargs.name if not name: name = input("Name of the Operation: ") action = self.app.pargs.action if not action: p = Prompt("Action for this Operation: ", options=ActionEnums.choices_values(), numbered=True) action = ActionEnums(p.input).name group = self.app.pargs.group_name if not group: name = input( "Name of the Group (to which the command must be fired): ") try: group_obj = self.validate_group_name(name) group_url = get_group_command_url(environment, enterprise_id, group_obj.id) except ApiException as e: self.app.log.error( f"[group-list] Failed to find group with name {name}: {e}") return desc = self.app.pargs.desc if not desc: desc = input("Description for this Operation [optional]: ") # Calling Pipeline API url = get_operation_url(environment, enterprise_id, pipeline_id, stage_id) api_key = db.get_configure().get("api_key") try: self.app.log.debug("Creating Operation...") response = create_operation(url, api_key, name, action, desc, group_url) except APIException: self.app.render("ERROR in connecting to Environment!\n") return if not response.ok: self.app.log.debug( f"Response not OK. Status Code: {response.status_code}") self.app.log.debug(f"Response not OK. Response: {response.json()}") if response.status_code == 400: errors = response.json().get('meta', {}).get('non_field_errors') if errors: self.app.log.error(f"Validation Error: {errors}") if response.json().get("errors"): if "The fields pipeline, ordering must make a unique set." in response.json( ).get("message"): self.app.log.error( f"Operation with same `name` already created for this Stage!" ) else: self.app.log.error( f"Validation Error: {response.json().get('errors')}" ) self.app.log.error(f"400 Errors -> {response.json()}") if response.status_code == 404: self.app.log.error("Stage URL not found!") if response.status_code == 500: self.app.log.error(f"Internal Server Error! {response.json()}") return # Rendering table with populated values data = render_single_dict(response.json()) self.app.render(f"Added Operation to Stage Successfully! Details: \n") self.app.render(data, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain")
def list(self): """Command to list application versions""" validate_creds_exists(self.app) db = DBWrapper(self.app.creds) application_client = APIClient(db.get_configure()).get_application_api_client() enterprise_id = db.get_enterprise_id() if self.app.pargs.application: application_id = self.app.pargs.application else: application = db.get_application() if not application or not application.get('id'): self.app.log.debug('[version-list] There is no active application.') self.app.render('There is no active application.\n') return application_id = application.get('id') version_code = self.app.pargs.version_code build_number = self.app.pargs.build_number limit = self.app.pargs.limit offset = self.app.pargs.offset kwargs = {} if version_code: kwargs['version_code'] = version_code if build_number: kwargs['build_number'] = build_number try: # Find application versions in an enterprise response = application_client.get_app_versions(application_id, enterprise_id, limit=limit, offset=offset, **kwargs) except ApiException as e: self.app.log.error(f"[version-list] Failed to list applications: {e}") self.app.render(f"ERROR: {parse_error_message(self.app, e)}\n") return self.app.render(f"Total Number of Versions: {response.count}") if not self.app.pargs.json: versions = [] label = { 'id': "ID", 'version_code': "VERSION CODE", 'build_number': "BUILD NUMBER", 'size_in_mb': "SIZE IN MB", 'release_track': "RELEASE TRACK", 'installed_count': "INSTALLED COUNT", } for version in response.results: versions.append( { label['id']: version.id, label['version_code']: version.version_code, label['build_number']: version.build_number, label['size_in_mb']: version.size_in_mb, label['release_track']: version.release_track, label['installed_count']: version.installed_count if version.installed_count else 0 } ) self.app.render(versions, format=OutputFormat.TABULATED.value, headers="keys", tablefmt="plain") else: versions = [] for version in response.results: versions.append( { 'id': version.id, 'version_code': version.version_code, 'build_number': version.build_number, 'size_in_mb': version.size_in_mb, 'release_track': version.release_track, 'installed_count': version.installed_count if version.installed_count else 0 } ) self.app.render(versions, 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" )