Source code for tenable.sc.scan_instances

'''
Scan Instances
==============

The following methods allow for interaction into the Tenable Security Center
:sc-api:`Scan Result <Scan-Result.htm>` API.  While the Tenable Security Center API refers
to the model these endpoints interact with as *ScanResult*, were actually
interacting with an instance of a scan definition stored within the *Scan* API
endpoints.  These scan instances could be running scans, stopped scans, errored
scans, or completed scans.  These items are typically seen under the
**Scan Results** section of Tenable Security Center.

Methods available on ``sc.scan_instances``:

.. rst-class:: hide-signature
.. autoclass:: ScanResultAPI
    :members:
'''
from .base import SCEndpoint
from tenable.utils import dict_merge
from io import BytesIO

[docs]class ScanResultAPI(SCEndpoint):
[docs] def copy(self, id, *users): ''' Clones the scan instance. :sc-api:`scan-result: copy <Scan-Result.htm#ScanResultRESTReference-/scanResult/{id}/copy>` Args: id (int): The identifier of the scan instance to clone. *users (int): A user id to associate to the scan instance. Returns: :obj:`dict`: The cloned scan instance record. Examples: >>> sc.scan_instances.copy(1) ''' payload = dict() if users: payload['users'] = [{'id': self._check('user:id', u, int)} for u in users] return self._api.post('scanResult/{}/copy'.format( self._check('id', id, int)), json=payload).json()['response']
[docs] def delete(self, id): ''' Removes the scan instance from TenableSC. :sc-api:`scan-result: delete <Scan-Result.htm#scanResult_id_DELETE>` Args: id (int): The identifier of the scan instance to delete. Returns: :obj:`str`: An empty string. Examples: >>> sc.scan_instances.delete(1) ''' return self._api.delete('scanResult/{}'.format( self._check('id', id, int))).json()['response']
[docs] def details(self, id, fields=None): ''' Retrieves the details for the specified scan instance. :sc-api:`scan-result: details <Scan-Result.htm#scanResult_id_GET>` Args: id (int): The identifier for the scan instance to be retrieved. fields (list, optional): List of fields to return. Refer to the API documentation referenced above for a list of available fields. Returns: :obj:`dict`: The scan instance resource record. Examples: Getting the details of a scan instance with just the default parameters: >>> scan = sc.scan_instances.details(1) >>> pprint(scan) Specifying what fields you'd like to be returned: >>> scan = sc.scan_instances.details(1, ... fields=['name', 'status', 'scannedIPs', 'startTime', 'finishTime']) >>> pprint(scan) ''' params = dict() if fields: params['fields'] = ','.join([self._check('field', f, str) for f in self._check('fields', fields, list)]) return self._api.get('scanResult/{}'.format(self._check('id', id, int)), params=params).json()['response']
[docs] def email(self, id, *emails): ''' Emails the scan results of the requested scan to the email addresses defined. :sc-api:`scan-result: email <Scan-Result.htm#ScanResultRESTReference-/scanResult/{id}/email>` Args: id (int): The identifier for the specified scan instance. *emails (str): Valid email address. Returns: :obj:`str`: Empty string response. Examples: >>> sc.scan_instances.email(1, 'email@company.tld') ''' return self._api.post('scanResult/{}/email'.format( self._check('id', id, int)), json={'email': ','.join( [self._check('address', e, str) for e in emails])}).json()['response']
[docs] def export_scan(self, id, fobj=None, export_format=None): ''' Downloads the results of the scan. :sc-api:`scan-result: download <Scan-Result.htm#ScanResultRESTReference-/scanResult/{id}/download>` Args: id (int): The scan instance identifier. export_format (str, optional): The format of the resulting data. Allowable values are ``scap1_2`` and ``v2``. ``v2`` is the default value if none are specified. fobj (FileObject, optional): The file-like object to write the resulting file into. If no file-like object is provided, a BytesIO objects with the downloaded file will be returned. Be aware that the default option of using a BytesIO object means that the file will be stored in memory, and it's generally recommended to pass an actual file-object to write to instead. Returns: :obj:`FileObject`: The file-like object with the resulting zipped report. Examples: >>> with open('example.zip', 'wb') as fobj: ... sc.scan_instances.export_scan(1, fobj) ''' resp = self._api.post('scanResult/{}/download'.format( self._check('id', id, int)), stream=True, json={ 'downloadType': self._check('export_format', export_format, str, choices=['scap1_2', 'v2'], default='v2')}) # if no file-like object was passed, then we will instantiate a BytesIO # object to push the file into. if not fobj: fobj = BytesIO() # Lets stream the file into the file-like object... for chunk in resp.iter_content(chunk_size=1024): if chunk: fobj.write(chunk) fobj.seek(0) resp.close() return fobj
[docs] def import_scan(self, fobj, repo, **kw): ''' Imports a nessus file into Tenable Security Center. :sc-api:`scan-result: import <Scan-Result.htm#ScanResultRESTReference-/scanResult/import>` Args: fobj (FileObject): The file-like object containing the Nessus file to import. repo (int): The repository id for the scan. auto_mitigation (int, optional): How many days to hold on to data before mitigating it? The default value is 0. host_tracking (bool, optional): Should DHCP host tracking be enabled? The default is False. vhosts (bool, optional): Should virtual host logic be enabled for the scan? The default is ``False``. Returns: :obj:`str`: An empty string response. Examples: >>> with open('example.nessus') as fobj: ... sc.scan_instances.import_scan(fobj, 1) ''' kw['repo'] = repo payload = self._api.scans._constructor(**kw) payload['filename'] = self._api.files.upload(fobj) return self._api.post( 'scanResult/import', json=payload).json()['response']
[docs] def reimport_scan(self, id, **kw): ''' Re-imports an existing scan into the cumulative repository. :sc-api:`scan-result: re-import <Scan-Result.htm#ScanResultRESTReference-/scanResult/{id}/import>` Args: id (int): The scan instance identifier. auto_mitigation (int, optional): How many days to hold on to data before mitigating it? The default value is 0. host_tracking (bool, optional): Should DHCP host tracking be enabled? The default is False. vhosts (bool, optional): Should virtual host logic be enabled for the scan? The default is ``False``. Returns: :obj:`str`: An empty string response. Examples: >>> sc.scan_instances.reimport_scan(1) ''' payload = self._api.scans._constructor(**kw) return self._api.post('scanResult/{}/import'.format(self._check( 'id', id, int)), json=payload).json()['response']
[docs] def list(self, fields=None, start_time=None, end_time=None, optimize=True): ''' Retrieves the list of scan instances. :sc-api:`scan-result: list <Scan-Result.htm#ScanResultRESTReference-/scanResult>` Args: fields (list, optional): A list of attributes to return. start_time (int, optional): Epoch time to start search (searches against createdTime and defaults to now-30d) end_time (int, optional): Epoch time to end search (searches against createdTime and defaults to now) optimize (bool, optional): Informs Tenable Security Center to optimize completed scan results. If left unspecified, the default is `True`. Returns: :obj:`dict`: A list of scan instance resources. Examples: * Retrieving all of the manageable scans instances: >>> for scan in sc.scan_instances.list()['manageable']: ... pprint(scan) ''' params = dict( optimizeCompletedScanResults=str(optimize).lower() ) if fields: params['fields'] = ','.join([self._check('field', f, str) for f in fields]) if start_time: params['startTime'] = self._check('start_time', start_time, int) if end_time: params['endTime'] = self._check('end_time', end_time, int) return self._api.get('scanResult', params=params).json()['response']
[docs] def pause(self, id): ''' Pauses a running scan instance. Note that this will not impact agent scan instances. :sc-api:`scan-result: pause <Scan-Result.htm#ScanResultRESTReference-/scanResult/{id}/pause>` Args: id (int): The unique identifier for the scan instance. Returns: :obj:`dict`: The Scan instance state Examples: >>> sc.scan_instances.pause(1) ''' return self._api.post('scanResult/{}/pause'.format(self._check( 'id', id, int))).json()['response']
[docs] def resume(self, id): ''' Resumes a paused scan instance. Note that this will not impact agent scan instances. :sc-api:`scan-result: resume <Scan-Result.htm#ScanResultRESTReference-/scanResult/{id}/resume>` Args: id (int): The unique identifier for the scan instance. Returns: :obj:`dict`: The Scan instance state Examples: >>> sc.scan_instances.resume(1) ''' return self._api.post('scanResult/{}/resume'.format(self._check( 'id', id, int))).json()['response']
[docs] def stop(self, id): ''' Stops a running scan instance. Note that this will not impact agent scan instances. :sc-api:`scan-result: stop <Scan-Result.htm#ScanResultRESTReference-/scanResult/{id}/stop>` Args: id (int): The unique identifier for the scan instance. Returns: :obj:`dict`: The Scan instance state Examples: >>> sc.scan_instances.stop(1) ''' return self._api.post('scanResult/{}/stop'.format(self._check( 'id', id, int))).json()['response']