Source code for tenable.sc

'''
.. autoclass:: TenableSC

    .. automethod:: login
    .. automethod:: logout

.. automodule:: tenable.sc.alerts
.. automodule:: tenable.sc.accept_risks
.. automodule:: tenable.sc.analysis
.. automodule:: tenable.sc.asset_lists
.. automodule:: tenable.sc.audit_files
.. automodule:: tenable.sc.credentials
.. automodule:: tenable.sc.current
.. automodule:: tenable.sc.feeds
.. automodule:: tenable.sc.files
.. automodule:: tenable.sc.groups
.. automodule:: tenable.sc.organizations
.. automodule:: tenable.sc.plugins
.. automodule:: tenable.sc.policies
.. automodule:: tenable.sc.queries
.. automodule:: tenable.sc.repositories
.. automodule:: tenable.sc.roles
.. automodule:: tenable.sc.scan_zones
.. automodule:: tenable.sc.scans
.. automodule:: tenable.sc.scan_instances
.. automodule:: tenable.sc.scanners
.. automodule:: tenable.sc.status
.. automodule:: tenable.sc.system
.. automodule:: tenable.sc.users
.. automodule:: tenable.sc.base


Raw HTTP Calls
==============

Even though the ``TenableSC`` object pythonizes the Tenable.sc API for
you, there may still bee the occasional need to make raw HTTP calls to the
Tenable.sc API.  The methods listed below aren't run through any
naturalization by the library aside from the response code checking.  These
methods effectively route directly into the requests session.  The responses
will be Response objects from the ``requests`` library.  In all cases, the path
is appended to the base ``url`` parameter that the ``TenableSC`` object was
instantiated with.

Example:

.. code-block:: python

   resp = sc.get('feed')

.. py:module:: tenable.sc
.. rst-class:: hide-signature
.. py:class:: TenableSC

    .. automethod:: get
    .. automethod:: post
    .. automethod:: put
    .. automethod:: delete
'''
from tenable.base import APISession
from tenable.errors import *
from .accept_risks import AcceptRiskAPI
from .alerts import AlertAPI
from .analysis import AnalysisAPI
from .asset_lists import AssetListAPI
from .audit_files import AuditFileAPI
from .credentials import CredentialAPI
from .current import CurrentSessionAPI
from .files import FileAPI
from .feeds import FeedAPI
from .groups import GroupAPI
from .organizations import OrganizationAPI
from .plugins import PluginAPI
from .policies import ScanPolicyAPI
from .queries import QueryAPI
from .recast_risks import RecastRiskAPI
from .repositories import RepositoryAPI
from .roles import RoleAPI
from .scanners import ScannerAPI
from .scans import ScanAPI
from .scan_instances import ScanResultAPI
from .scan_zones import ScanZoneAPI
from .status import StatusAPI
from .system import SystemAPI
from .users import UserAPI
import warnings, logging


[docs]class TenableSC(APISession): '''TenableSC API Wrapper The Tenable.sc object is the primary interaction point for users to interface with Tenable.sc via the pyTenable library. All of the API endpoint classes that have been written will be grafted onto this class. Args: host (str): The address of the Tenable.sc instance to connect to. adapter (requests.Adaptor, optional): If a requests session adaptor is needed to ensure connectivity to the Tenable.sc host, one can be provided here. backoff (float, optional): If a 429 response is returned, how much do we want to backoff if the response didn't send a Retry-After header. The default backoff is ``1`` second. cert (tuple, optional): The client-side SSL certificate to use for authentication. This format could be either a tuple or a string pointing to the certificate. For more details, please refer to the `Requests Client-Side Certificates`_ documentation. port (int, optional): The port number to connect to on the specified host. The default is port ``443``. retries (int, optional): The number of retries to make before failing a request. The default is ``3``. scheme (str, optional): What HTTP scheme should be used for URI path construction. The default is ``https``. session (requests.Session, optional): If a requests Session is provided, the provided session will be used instead of constructing one during initialization. ssl_verify (bool, optional): Should the SSL certificate on the Tenable.sc instance be verified? Default is False. ua_identity (str, optional): An application identifier to be added into the User-Agent string for the purposes of application identification. Examples: A direct connection to TenableSC: >>> from tenable.sc import TenableSC >>> sc = TenableSC('securitycenter.company.tld') A connection to TenableSC using SSL certificates: >>> sc = TenableSC('securitycenter.company.tld', ... cert=('/path/client.cert', '/path/client.key')) Using an adaptor to use a passworded certificate (via the immensely useful `requests_pkcs12`_ adaptor): >>> from requests_pkcs12 import Pkcs12Adapter >>> adapter = Pkcs12Adapter( ... pkcs12_filename='certificate.p12', ... pkcs12_password='omgwtfbbq!') >>> sc = TenableSC('securitycenter.company.tld', adapter=adapter) For more information, please See Tenable's `SC API documentation`_ and the `SC API Best Practices Guide`_. .. _SC API documentation: https://docs.tenable.com/sccv/api/index.html .. _SC API Best Practices Guide: https://docs.tenable.com/sccv/api_best_practices/Content/ScApiBestPractices/AboutScApiBestPrac.htm .. _Requests Client-Side Certificates: http://docs.python-requests.org/en/master/user/advanced/#client-side-certificates .. _requests_pkcs12: https://github.com/m-click/requests_pkcs12 ''' _restricted_paths = ['token'] _error_codes = { 400: InvalidInputError, 403: APIError, 404: NotFoundError, 500: ServerError, } def __init__(self, host, port=443, ssl_verify=False, cert=None, adapter=None, scheme='https', retries=None, backoff=None, ua_identity=None, session=None, proxies=None, vendor=None, product=None, build=None): # As we will always be passing a URL to the APISession class, we will # want to construct a URL that APISession (and further requests) # understands. base = '{}://{}:{}'.format(scheme, host, port) url = '{}/rest'.format(base) # Setting the SSL Verification flag on the object itself so that it's # reusable if the user logs out and logs back in. self._ssl_verify = ssl_verify # Now lets pass the relevent parts off to the APISession's constructor # to make sure we have everything lined up as we expect. super(TenableSC, self).__init__(url, retries=retries, backoff=backoff, ua_identity=ua_identity, session=session, proxies=proxies, vendor=vendor, product=product, build=build) # If a client-side certificate is specified, then we will want to add # it into the session object as well. The cert parameter is expecting # a path pointing to the client certificate file. if cert: self._session.cert = cert # If an adapter for requests was provided, we should pull that in as # well. if adapter: self._session.mount(base, adapter) # We will attempt to make the first call to the Tenable.sc instance # and get the system information. If this call fails, then we likely # aren't pointing to a SecurityCenter at all and should throw an error # stating this. try: self.info = self.system.details() except: raise ConnectionError('No Tenable.sc Instance at {}:{}'.format(host, port)) # Now we will try to interpret the Tenable.sc information into # something usable. try: self.version = self.info['version'] self.build_id = self.info['buildID'] self.license = self.info['licenseStatus'] self.uuid = self.info['uuid'] if 'token' in self.info: # if a token was passed in the system info page, then we should # update the X-SecurityCenter header with the token info. self._session.headers.update({ 'X-SecurityCenter': str(self.info['token']) }) except: raise ConnectionError('Invalid Tenable.sc Instance') def _build_session(self, session=None): super(TenableSC, self)._build_session(session) # As Tenable.sc is generally installed without a certificate chain that # we can validate, we will want to turn off verification and the # associated warnings unless told to otherwise: self._session.verify = self._ssl_verify if not self._ssl_verify: warnings.filterwarnings('ignore', 'Unverified HTTPS request') def _resp_error_check(self, response, **kwargs): if not kwargs.get('stream', False): try: d = response.json() if d['error_code']: raise APIError(d['error_code'], d['error_msg']) except ValueError: pass return response
[docs] def login(self, user, passwd): ''' Logs the user into Tenable.sc Args: user (str): Username passwd (str): Password Returns: None Examples: >>> sc = TenableSC('127.0.0.1', port=8443) >>> sc.login('username', 'password') ''' resp = self.post('token', json={'username': user, 'password': passwd}) self._session.headers.update({ 'X-SecurityCenter': str(resp.json()['response']['token']) })
[docs] def logout(self): ''' Logs out of Tenable.sc and resets the session. Returns: None Examples: >>> sc.logout() ''' resp = self.delete('token') self._build_session()
@property def accept_risks(self): return AcceptRiskAPI(self) @property def alerts(self): return AlertAPI(self) @property def analysis(self): return AnalysisAPI(self) @property def asset_lists(self): return AssetListAPI(self) @property def audit_files(self): return AuditFileAPI(self) @property def credentials(self): return CredentialAPI(self) @property def current(self): return CurrentSessionAPI(self) @property def feeds(self): return FeedAPI(self) @property def files(self): return FileAPI(self) @property def groups(self): return GroupAPI(self) @property def organizations(self): return OrganizationAPI(self) @property def plugins(self): return PluginAPI(self) @property def policies(self): return ScanPolicyAPI(self) @property def queries(self): return QueryAPI(self) @property def recast_risks(self): return RecastRiskAPI(self) @property def repositories(self): return RepositoryAPI(self) @property def roles(self): return RoleAPI(self) @property def scanners(self): return ScannerAPI(self) @property def scans(self): return ScanAPI(self) @property def scan_instances(self): return ScanResultAPI(self) @property def scan_zones(self): return ScanZoneAPI(self) @property def status(self): return StatusAPI(self) @property def system(self): return SystemAPI(self) @property def users(self): return UserAPI(self)
class SecurityCenter(TenableSC): ''' The historical name for TenableSC prior to the rename in Nov 2018. Usage is identical to using TenableSC, however we will throw a deprecation warning when using the SecurityCenter class. Please use ``TenableSC``. ''' def __init__(self, host, port=443, ssl_verify=False, cert=None, scheme='https', retries=None, backoff=None): warnings.warn( ' '.join([ 'The SecurityCenter class has been replaced by the TenableSC', 'class. The existing SecurityCenter class will be removed in', 'the first stable version (1.0).']), Warning) TenableSC.__init__(self, host, port, ssl_verify, cert, scheme, retries, backoff)