Source code for tenable.io.filters

"""
Filters
=======

The following methods allow for interaction into the Tenable Vulnerability Management
:devportal:`filters <filters-1>` API endpoints.

Methods available on ``tio.filters``:

.. rst-class:: hide-signature
.. autoclass:: FiltersAPI
    :members:
"""

import time
from typing import Any

from tenable.io.base import TIOEndpoint


[docs] class FiltersAPI(TIOEndpoint): """ This will contain all methods related to filters """ _cache = {} def _normalize(self, filterset: list[dict[str, Any]]) -> dict[str, Any]: """ Converts the filters into an easily pars-able dictionary """ filters = dict() for item in filterset: datablock = { 'operators': item['operators'], 'choices': None, 'pattern': None, } # If there is a list of choices available, then we need to parse # them out and only pull back the usable values as a list if 'list' in item['control']: # There is a lack of consistency here. In some cases the "list" # is a list of dictionary items, and in other cases the "list" # is a list of string values. if isinstance(item['control']['list'][0], dict): key = 'value' if 'value' in item['control']['list'][0] else 'id' datablock['choices'] = [ str(i[key]) for i in item['control']['list'] ] elif isinstance(item['control']['list'], list): datablock['choices'] = [str(i) for i in item['control']['list']] if 'regex' in item['control']: datablock['pattern'] = item['control']['regex'] filters[item['name']] = datablock return filters def _use_cache( self, name: str, path: str, field_name: str = 'filters', normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Leverages the filter cache and will return the results as expected. """ if name not in self._cache or self._cache[name]['ts'] + expire_age <= int( time.time() ): self._cache[name] = { 'ts': int(time.time()), 'data': self._api.get(path).json()[field_name], } if normalize: return self._normalize(self._cache[name]['data']) return self._cache[name]['data']
[docs] def access_group_asset_rules_filters( self, normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Returns access group rules filters. :devportal:`filters: access-control-rules-filters <access-groups-list-rule-filters>` Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.access_group_rules_filters() """ return self._use_cache( 'access_group_asset_filters', 'access-groups/rules/filters', field_name='rules', normalize=normalize, expire_age=expire_age, )
[docs] def access_group_filters( self, normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Returns access group filters. :devportal:`filters: access-group-filters <access-groups-list-filters>` Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.access_group_filters() """ return self._use_cache( 'access_groups', 'access-groups/filters', normalize=normalize, expire_age=expire_age, )
[docs] def access_group_filters_v2(self, normalize=True): """ Returns access group filters v2. :devportal:`filters: access_group_filters_v2 <v2-access-groups-list-filters>` Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.access_group_filters_v2() """ return self._use_cache( 'access_groups_v2', 'v2/access-groups/filters', normalize=normalize )
[docs] def access_group_asset_rules_filters_v2( self, normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Returns access group rules filters v2. :devportal:`filters: access_group_asset_rules_filters_v2 <v2-access-groups-list-rule-filters>` Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.access_group_rules_filters_v2() """ return self._use_cache( 'access_group_asset_filters_v2', 'v2/access-groups/rules/filters', field_name='rules', normalize=normalize, expire_age=expire_age, )
[docs] def agents_filters( self, normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Returns agent filters. :devportal:`filters: agents-filters <filters-agents-filters>` Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.agents_filters() """ return self._use_cache( 'agents', 'filters/scans/agents', normalize=normalize, expire_age=expire_age, )
[docs] def workbench_vuln_filters( self, normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Returns the vulnerability workbench filters :devportal:`workbenches: vulnerabilities-filters <workbenches-vulnerabilities-filters>` Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.workbench_vuln_filters() """ return self._use_cache( 'vulns', 'filters/workbenches/vulnerabilities', normalize=normalize, expire_age=expire_age, )
[docs] def workbench_asset_filters( self, normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Returns the asset workbench filters. :devportal:`workbenches: assets-filters <filters-assets-filter>` Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.workbench_asset_filters() """ return self._use_cache( 'asset', 'filters/workbenches/assets', normalize=normalize, expire_age=expire_age, )
[docs] def scan_filters( self, normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Returns the individual scan filters. Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.scan_filters() """ return self._use_cache('scan', 'filters/scans/reports', normalize=normalize)
[docs] def credentials_filters( self, normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Returns the individual scan filters. :devportal:`filters: credentials <credentials-filters>` Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.scan_filters() """ return self._use_cache( 'scan', 'filters/credentials', normalize=normalize, expire_age=expire_age, )
[docs] def networks_filters(self) -> dict[str, Any]: """ Returns the networks filters. Returns: :obj:`dict`: Filter resource dictionary Examples: >>> filters = tio.filters.network_filters() """ return { 'name': { 'operators': ['eq', 'neq', 'match'], 'choices': None, 'pattern': None, } }
[docs] def asset_tag_filters( self, normalize: bool = True, expire_age: int = 60, ) -> dict[str, Any]: """ Returns a list of filters that you can use to create the rules for applying dynamic tags. :devportal:`tag: list asset tag filters <tags-list-asset-filters>` Args: normalize: Should the response be converted into the same structure used for the filter cache? expire_age: How many seconds old can the cache be before forcing a refresh? Returns: :obj:`dict`: Filter resource dictionary Examples: >>> tio.filters.asset_tag_filters() """ return self._use_cache( 'tags', 'tags/assets/filters', normalize=normalize, expire_age=expire_age, )