Tenable.sc
With Tenable.sc (formerly SecurityCenter) you get a real-time, continuous assessment of your security posture so you can find and fix vulnerabilities faster.
Vulnerability Management · Tenable.sc
Details
| ID | Tenable.sc |
|---|---|
| Provider | Tenable |
| Category | Vulnerability Management |
| From Version | 5.0.0 |
| Docker Image | demisto/python3:3.12.13.10116658 |
| Supported Modules | Agentix XSIAM Exposure Management |
README
Use the Tenable.sc integration to get a real-time, continuous assessment of your security posture so you can find and fix vulnerabilities faster.
All data in Tenable.sc is managed using group level permissions. If you have several groups, data (scans, scan results, assets, etc) can be viewable but not manageable. Users with Security Manager role can manage everything. These permissions come into play when multiple groups are in use.
It is important to know what data is manageable for the user in order to work with the integration.
This integration was integrated and tested with Tenable.sc v5.7.0.
Use cases
* Create and run scans.
* Launch and manage scan results and the found vulnerabilities.
* Create and view assets.
* View policies, repositories, credentials, users and more system information.
* View and real-time receiving of alerts.
Configure Tenable.sc in Cortex
| Parameter | Description | Required |
|---|---|---|
| Server URL (e.g. https://192.168.0.1) | The server URL. | True |
| Access key | See the help for instructions to generate the access key. | False |
| Secret key | False | |
| Username | The Username is either admin or secman (depend on the role you want to log into) and your password to the tenable server. | False |
| Password | False | |
| Trust any certificate (not secure) | False | |
| Use system proxy settings | False | |
| Fetch incidents | False | |
| Incident type | False | |
| First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days) | The timestamp to start the fetch from. | False |
Commands
You can execute these commands from the CLI, as part of an automation, or in a playbook.
After you successfully execute a command, a DBot message appears in the War Room with the command details.
tenable-sc-list-scans
Requires security manager role. Get a list of Tenable.sc existing scans.
Base Command
tenable-sc-list-scans
Input
| Argument Name | Description | Required |
|---|---|---|
| manageable | Whether to return only manageable scans. Returns both usable and manageable scans by default. Possible values are: true, false. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Scan.Name | string | Scan name. |
| TenableSC.Scan.ID | number | Scan ID. |
| TenableSC.Scan.Description | string | Scan description. |
| TenableSC.Scan.Policy | string | Scan policy name. |
| TenableSC.Scan.Group | string | Scan policy owner group name. |
| TenableSC.Scan.Owner | string | Scan policy owner user name. |
Human Readable Output
Tenable.sc Scans
| ID | Name | Description | Policy | Group | Owner |
|---|---|---|---|---|---|
| 3 | test_scan_2023 | Test scan | Network Scan | Full Access | secman |
tenable-sc-launch-scan
Requires security manager role. Launch an existing scan from Tenable.sc. Set polling to true to follow the scan and receive results when scan is over.
Base Command
tenable-sc-launch-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| scan_id | Scan ID, can be retrieved from list-scans command. | Required |
| diagnostic_target | Valid IP/Hostname of a specific target to scan. Must be provided with diagnosticPassword. | Optional |
| diagnostic_password | Non empty string password. | Optional |
| timeout_in_seconds | Relevant only when polling is true. Default is 3 hours. The timeout in seconds until polling ends. Default is 10800. | Optional |
| polling | Default is false. When set to true, will keep polling results until scan is done and return the formatted scan results. Possible values are: true, false. Default is false. | Optional |
| scan_results_id | Deprecated. Scan results ID. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ScanResults.Name | string | Scan name. |
| TenableSC.ScanResults.Status | string | Scan status. |
| TenableSC.ScanResults.ID | string | Scan Results ID. |
| TenableSC.ScanResults.OwnerID | string | Relevant only when polling is false. Scan owner ID. |
| TenableSC.ScanResults.JobID | string | Relevant only when polling is false. Job ID. |
| TenableSC.ScanResults.ScannedIPs | number | Relevant only when polling is true. Scan number of scanned IPs. |
| TenableSC.ScanResults.StartTime | date | Relevant only when polling is true. Scan start time. |
| TenableSC.ScanResults.EndTime | date | Relevant only when polling is true. Scan end time. |
| TenableSC.ScanResults.Checks | number | Relevant only when polling is true. Scan completed checks. |
| TenableSC.ScanResults.RepositoryName | string | Relevant only when polling is true. Scan repository name. |
| TenableSC.ScanResults.Description | string | Relevant only when polling is true. Scan description. |
| TenableSC.ScanResults.Vulnerability.ID | number | Relevant only when polling is true. Scan vulnerability ID. |
| TenableSC.ScanResults.Vulnerability.Name | string | Relevant only when polling is true. Scan vulnerability Name. |
| TenableSC.ScanResults.Vulnerability.Family | string | Relevant only when polling is true. Scan vulnerability family. |
| TenableSC.ScanResults.Vulnerability.Severity | string | Relevant only when polling is true. Scan vulnerability severity. |
| TenableSC.ScanResults.Vulnerability.Total | number | Relevant only when polling is true. Scan vulnerability total hosts. |
| TenableSC.ScanResults.Policy | string | Relevant only when polling is true. Scan policy. |
| TenableSC.ScanResults.Group | string | Relevant only when polling is true. Scan owner group name. |
| TenableSC.ScanResults.Owner | string | Relevant only when polling is true. Scan owner user name. |
| TenableSC.ScanResults.Duration | number | Relevant only when polling is true. Scan duration in minutes. |
| TenableSC.ScanResults.ImportTime | date | Relevant only when polling is true. Scan import time. |
Human Readable Output
When polling is set to false:
Tenable.sc Scan
| Name | ID | OwnerID | JobID | Status |
|---|---|---|---|---|
| test_scan_2023 | 169 | 38 | 118864 | Queued |
When polling is set to true:
Tenable.sc Scan 130 Report
| ID | Name | Description | Policy | Group | Owner | ScannedIPs | StartTime | EndTime | Duration | Checks | ImportTime | RepositoryName | Status | Scan Type | Completed IPs |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 130 | test_scan_2023 | Test scan 2023 | Network Scan | Full Access | hayun_test_sec_man | 156 | 2023-05-16T12:18:10Z | 2023-05-16T17:20:00Z | 301.8333333333333 | 22649640 | 2023-05-16T17:20:02Z | Local | Completed | regular | 156 |
tenable-sc-get-vulnerability
Requires security manager role. Get details about a given vulnerability from a given Tenable.sc scan.
Base Command
tenable-sc-get-vulnerability
Input
| Argument Name | Description | Required |
|---|---|---|
| vulnerability_id | Vulnerability ID from the scan-report command. | Required |
| scan_results_id | Scan results ID from the scan-report command. | Optional |
| query_id | Can be created via the Tenable.sc UI > Analysis > queries. Can be retrieved from the tenable-sc-list-query command. | Optional |
| sort_direction | The direction in which the results should be sorted. Requires companion parameter, sort_field. Possible values are: ASC, DESC. Default is ASC. | Optional |
| sort_field | Which field to sort by, For vulnerabilities data, Tenable recommends you sort by severity. Default is severity. | Optional |
| source_type | When the source_type is “individual”, a scan_results_id must be provided, otherwise “query_id” must be provided. cumulative — Analyzes cumulative vulnerabilities. patched — Analyzes mitigated vulnerabilities. Possible values are: individual, cumulative, patched. Default is individual. | Optional |
| limit | The number of objects to return in one response (maximum limit is 200). Default is 50. | Optional |
| page | The page to return, starting from 0. Default is 0. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ScanResults.ID | number | Scan results ID. |
| TenableSC.ScanResults.Vulnerability.ID | number | Vulnerability plugin ID. |
| TenableSC.ScanResults.Vulnerability.Name | string | Vulnerability name. |
| TenableSC.ScanResults.Vulnerability.Description | string | Vulnerability description. |
| TenableSC.ScanResults.Vulnerability.Type | string | Vulnerability type. |
| TenableSC.ScanResults.Vulnerability.Severity | string | Vulnerability Severity. |
| TenableSC.ScanResults.Vulnerability.Synopsis | string | Vulnerability Synopsis. |
| TenableSC.ScanResults.Vulnerability.Solution | string | Vulnerability Solution. |
| TenableSC.ScanResults.Vulnerability.Published | date | Vulnerability publish date. |
| TenableSC.ScanResults.Vulnerability.CPE | string | Vulnerability CPE. |
| TenableSC.ScanResults.Vulnerability.CVE | Unknown | Vulnerability CVE. |
| TenableSC.ScanResults.Vulnerability.ExploitAvailable | boolean | Vulnerability exploit available. |
| TenableSC.ScanResults.Vulnerability.ExploitEase | string | Vulnerability exploit ease. |
| TenableSC.ScanResults.Vulnerability.RiskFactor | string | Vulnerability risk factor. |
| TenableSC.ScanResults.Vulnerability.CVSSBaseScore | number | Vulnerability CVSS base score. |
| TenableSC.ScanResults.Vulnerability.CVSSTemporalScore | number | Vulnerability CVSS temporal score. |
| TenableSC.ScanResults.Vulnerability.CVSSVector | string | Vulnerability CVSS vector. |
| TenableSC.ScanResults.Vulnerability.PluginDetails | Unknown | Vulnerability plugin details. |
| CVE.ID | Unknown | CVE ID. |
| TenableSC.ScanResults.Vulnerability.Host.IP | string | Vulnerability Host IP. |
| TenableSC.ScanResults.Vulnerability.Host.MAC | string | Vulnerability Host MAC. |
| TenableSC.ScanResults.Vulnerability.Host.Port | number | Vulnerability Host Port. |
| TenableSC.ScanResults.Vulnerability.Host.Protocol | string | Vulnerability Host Protocol. |
Human Readable Output
Vulnerability: FTP Server Detection (10092)
Synopsis
An FTP server is listening on a remote port.
Description
It is possible to obtain the banner of the remote FTP server by connecting to a remote port.
Solution
Hosts
| IP | MAC | Port | Protocol |
|---|---|---|---|
| {IP} | {MAC} | 21 | TCP |
Risk Information
| RiskFactor |
|---|
| None |
Exploit Information
| ExploitAvailable |
|---|
| false |
Plugin Details
| CheckType | Family | Modified | Published |
|---|---|---|---|
| remote | Service detection | 2019-11-22T17:00:00Z | 1999-10-12T16:00:00Z |
Vulnerability Information
No entries.
tenable-sc-get-scan-status
Requires security manager role. Get the status of a specific scan in Tenable.sc.
Base Command
tenable-sc-get-scan-status
Input
| Argument Name | Description | Required |
|---|---|---|
| scan_results_id | Scan results ID from the launch-scan command. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ScanResults.Status | string | Scan status. |
| TenableSC.ScanResults.Name | string | Scan Name. |
| TenableSC.ScanResults.Description | string | Scan description. |
| TenableSC.ScanResults.ID | string | Scan results ID. |
| TenableSC.ScanResults.Error | string | Will appear only in case of error in the scan, include the cause for the failure. |
Human Readable Output
Tenable.sc Scan Status
| ID | Name | Status | Description |
|---|---|---|---|
| 169 | test_scan_2023 | Running | Test scan 2023 |
tenable-sc-get-scan-report
Requires security manager role. Get a single report with Tenable.sc scan results. In case of Importstatus = Error (The results import wasn’t finished), the vulnerabilities section will not be added to the results.
Base Command
tenable-sc-get-scan-report
Input
| Argument Name | Description | Required |
|---|---|---|
| scan_results_id | Scan results ID. | Required |
| vulnerability_severity | Comma-separated list of severity values of vulnerabilities to retrieve. Default is Critical,High,Medium,Low,Info. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ScanResults.ID | number | Scan results ID. |
| TenableSC.ScanResults.Name | string | Scan name. |
| TenableSC.ScanResults.Status | string | Scan status. |
| TenableSC.ScanResults.ScannedIPs | number | Scan number of scanned IPs. |
| TenableSC.ScanResults.StartTime | date | Scan start time. |
| TenableSC.ScanResults.EndTime | date | Scan end time. |
| TenableSC.ScanResults.Checks | number | Scan completed checks. |
| TenableSC.ScanResults.RepositoryName | string | Scan repository name. |
| TenableSC.ScanResults.Description | string | Scan description. |
| TenableSC.ScanResults.Vulnerability.ID | number | Scan vulnerability ID. |
| TenableSC.ScanResults.Vulnerability.Name | string | Scan vulnerability Name. |
| TenableSC.ScanResults.Vulnerability.Family | string | Scan vulnerability family. |
| TenableSC.ScanResults.Vulnerability.Severity | string | Scan vulnerability severity. |
| TenableSC.ScanResults.Vulnerability.Total | number | Scan vulnerability total hosts. |
| TenableSC.ScanResults.Policy | string | Scan policy. |
| TenableSC.ScanResults.Group | string | Scan owner group name. |
| TenableSC.ScanResults.Owner | string | Scan owner user name. |
| TenableSC.ScanResults.Duration | number | Scan duration in minutes. |
| TenableSC.ScanResults.ImportTime | date | Scan import time. |
| TenableSC.ScanResults.IsScanRunning | boolean | Whether the scan is still running. |
| TenableSC.ScanResults.ImportStatus | string | Scan import status. |
Human Readable Output
Tenable.sc Scan 150 Report
| ID | Name | Policy | Group | Owner | ScannedIPs | StartTime | EndTime | Duration | Checks | ImportTime | RepositoryName | Status | Scan Type | Completed IPs |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 150 | my_Test_scan | Plugin #1 | Full Access | yuv | 115 | 2023-05-18T13:12:51Z | 2023-05-18T13:45:53Z | 33.03333333333333 | 21275 | 2023-05-18T13:45:57Z | Local | Completed | regular | 115 |
Vulnerabilities
| ID | Name | Family | Severity | Total |
|---|---|---|---|---|
| 11219 | Nessus SYN scanner | Port scanners | Info | 109 |
tenable-sc-list-credentials
Requires security manager role. Get a list of Tenable.sc credentials.
Base Command
tenable-sc-list-credentials
Input
| Argument Name | Description | Required |
|---|---|---|
| manageable | Whether to return only manageable scan credentials. Returns both usable and manageable by default. Possible values are: true, false. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Credential.Name | string | Credential name. |
| TenableSC.Credential.ID | number | Credential ID. |
| TenableSC.Credential.Description | string | Credential description. |
| TenableSC.Credential.Type | string | Credential type. |
| TenableSC.Credential.Tag | string | Credential tag. |
| TenableSC.Credential.Group | string | Credential owner group name. |
| TenableSC.Credential.Owner | string | Credential owner user name. |
| TenableSC.Credential.LastModified | date | Credential last modified time. |
Human Readable Output
Tenable.sc Credentials
| ID | Name | Type | Group | LastModified |
|---|---|---|---|---|
| 1 | Windows server | windows | 2023-02-14T11:44:12Z | |
| 2 | SSH linux | ssh | 2023-02-15T09:11:10Z | |
| 3 | Windows clients | windows | 2023-02-15T12:32:45Z |
tenable-sc-list-policies
Requires security manager role. Get a list of Tenable.sc scan policies.
Base Command
tenable-sc-list-policies
Input
| Argument Name | Description | Required |
|---|---|---|
| manageable | Whether to return only manageable scan policies. Returns both usable and manageable by default. Possible values are: true, false. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ScanPolicy.Name | string | Scan policy name. |
| TenableSC.ScanPolicy.ID | number | Scan policy ID. |
| TenableSC.ScanPolicy.Description | string | Scan policy description. |
| TenableSC.ScanPolicy.Tag | string | Scan policy tag. |
| TenableSC.ScanPolicy.Group | string | Scan policy owner group name. |
| TenableSC.ScanPolicy.Owner | string | Scan policy owner user name. |
| TenableSC.ScanPolicy.LastModified | date | Scan policy last modified time. |
| TenableSC.ScanPolicy.Type | string | Scan policy type. |
Human Readable Output
Tenable.sc Scan Policies
| ID | Name | Description | Type | Group | Owner | LastModified |
|---|---|---|---|---|---|---|
| 1 | Network Scan | Basic Network Scan | 2023-02-09T14:58:26Z | |||
| 2 | D Advanced Scan | D Advanced Scan | Advanced Scan | 2023-02-13T13:02:22Z |
tenable-sc-list-report-definitions
Requires security manager role. Get a list of Tenable.sc report definitions.
Base Command
tenable-sc-list-report-definitions
Input
| Argument Name | Description | Required |
|---|---|---|
| manageable | Whether to return only manageable reports. Returns both usable and manageable by default. Possible values are: true, false. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ReportDefinition.Name | string | Report definition name. |
| TenableSC.ReportDefinition.ID | number | Report definition ID. |
| TenableSC.ReportDefinition.Description | string | Report definition description. |
| TenableSC.ReportDefinition.Type | string | Report definition type. |
| TenableSC.ReportDefinition.Group | string | Report definition owner group name. |
| TenableSC.ReportDefinition.Owner | string | Report definition owner user name. |
Human Readable Output
Tenable.sc Report Definitions
| ID | Name | Description | Type | Group | Owner |
|---|---|---|---|---|---|
| 2 | Critical and Exploitable Vulnerabilities Report | Test | Full Access | test |
tenable-sc-list-repositories
Requires security manager role. Get a list of Tenable.sc scan repositories.
Base Command
tenable-sc-list-repositories
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ScanRepository.Name | string | Scan Repository name. |
| TenableSC.ScanRepository.ID | number | Scan Repository ID. |
| TenableSC.ScanRepository.Description | string | Scan Repository. |
Human Readable Output
Tenable.sc Scan Repositories
| ID | Name |
|---|---|
| 1 | Local |
tenable-sc-list-zones
Requires admin role. Get a list of Tenable.sc scan zones.
Base Command
tenable-sc-list-zones
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ScanZone.Name | string | Scan Zone name. |
| TenableSC.ScanZone.ID | number | Scan Zone ID. |
| TenableSC.ScanZone.Description | string | Scan Zone description. |
| TenableSC.ScanZone.IPList | unknown | Scan Zone IP list. |
| TenableSC.ScanZone.ActiveScanners | number | Scan Zone active scanners. |
| TenableSC.ScanZone.Scanner.Name | string | Scanner name. |
| TenableSC.ScanZone.Scanner.ID | number | Scanner ID. |
| TenableSC.ScanZone.Scanner.Description | string | Scanner description. |
| TenableSC.ScanZone.Scanner.Status | number | Scanner status. |
Human Readable Output
Tenable.sc Scan Zones
| ID | Name | IPList | activeScanners |
|---|---|---|---|
| 1 | Default Scan Zone | ip | 1 |
Tenable.sc Scanners
| ID | Name | Status |
|---|---|---|
| 2 | RHEL6 Scanner | 1 |
tenable-sc-create-scan
Requires security manager role. Create a scan on Tenable.sc
Base Command
tenable-sc-create-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Scan name. | Required |
| policy_id | Policy ID, can be retrieved from the list-policies command. | Required |
| plugin_id | Plugin ID. | Optional |
| description | Scan description. | Optional |
| repository_id | Scan Repository ID. Can be retrieved from the list-repositories command. | Required |
| zone_id | Scan zone ID (default is all zones). Can be retrieved from the list-zones command. | Optional |
| schedule | Schedule for the scan. Possible values are: dependent, ical, never, rollover, now. | Optional |
| asset_ids | Either all assets or comma-separated asset IDs to scan. Can be retrieved from the list-assets command. Possible values are: All, AllManageable. | Optional |
| scan_virtual_hosts | Whether to include virtual hosts. Default is false. Possible values are: true, false. | Optional |
| ip_list | Comma-separated IPs to scan, e.g., 10.0.0.1,10.0.0.2 . | Optional |
| report_ids | Comma- separated list of report definition IDs to create post-scan. Can be retrieved from the list-report-definitions command. | Optional |
| credentials | Comma-separated credentials IDs to use. Can be retrieved from the list-credentials command. | Optional |
| timeout_action | Scan timeout action. Default is import. Possible values are: discard, import, rollover. | Optional |
| max_scan_time | Maximum scan run time in hours, Default is 1. | Optional |
| dhcp_tracking | Track hosts which have been issued new IP address, (e.g., DHCP). Possible values are: true, false. | Optional |
| rollover_type | Scan rollover type. Possible values are: nextDay. | Optional |
| dependent_id | Dependent scan ID in case of a dependent schedule. Can be retrieved from the list-scans command. | Optional |
| time_zone | The timezone for the given start_time, Possible values can be found here: https://docs.oracle.com/middleware/1221/wcs/tag-ref/MISC/TimeZones.html. | Optional |
| start_time | The scan start time in the format of YYYY-MM-DD:HH:MM:SS or relative timestamp (i.e., now, 3 days). | Optional |
| repeat_rule_freq | Specifies repeating events based on an interval of a repeat_rule_freq or more. Possible values are: HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY. | Optional |
| repeat_rule_interval | The number of repeat_rule_freq between each interval (for example: If repeat_rule_freq=DAILY and repeat_rule_interval=8 it means every eight days.). | Optional |
| repeat_rule_by_day | A comma-separated list of days of the week to run the schedule. Possible values are: SU,MO,TU,WE,TH,FR,SA. | Optional |
| enabled | The “enabled” field can only be set to “false” for schedules of type “ical”. For all other schedules types, “enabled” is set to “true”. Possible values are: true, false. Default is true. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Scan.ID | string | Scan ID. |
| TenableSC.Scan.CreatorID | string | Scan’s creator ID. |
| TenableSC.Scan.Name | string | Scan Name. |
| TenableSC.Scan.Type | string | Scan type. |
| TenableSC.Scan.CreatedTime | date | Scan creation time. |
| TenableSC.Scan.OwnerName | string | Scan owner Username. |
| TenableSC.Scan.Reports | unknown | Scan report definition IDs. |
Human Readable Output
Scan created successfully
| ID | CreatorID | Name | Type | CreationTime |
|---|---|---|---|---|
| 70 | 39 | my_name | policy | 2023-05-24T12:33:03Z |
tenable-sc-delete-scan
Requires security manager role. Delete a scan in Tenable.sc.
Base Command
tenable-sc-delete-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| scan_id | Scan ID. Can be retrieved from the the list-scans command. | Required |
Context Output
There is no context output for this command.
Human Readable Output
Scan {scan_id} was deleted successfully.
tenable-sc-list-assets
Requires security manager role. Get a list of Tenable.sc assets.
Base Command
tenable-sc-list-assets
Input
| Argument Name | Description | Required |
|---|---|---|
| manageable | Whether to return only manageable assets. Returns both usable and manageable by default. Possible values are: true, false. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Asset.ID | string | Asset ID. |
| TenableSC.Asset.Name | string | Asset name. |
| TenableSC.Asset.HostCount | number | Asset host IPs count. |
| TenableSC.Asset.Type | string | Asset type. |
| TenableSC.Asset.Tag | string | Asset tag. |
| TenableSC.Asset.Owner | string | Asset owner username. |
| TenableSC.Asset.Group | string | Asset group. |
| TenableSC.Asset.LastModified | date | Asset last modified time. |
Human Readable Output
Tenable.sc Assets
| ID | Name | Tag | Owner | Type | HostCount | LastModified |
|---|---|---|---|---|---|---|
| 0 | All Defined Ranges | static | 0 | 2023-01-09T13:13:52Z | ||
| 1 | asset_1_name | test | dynamic | 106 | 2023-05-21T09:12:52Z | |
| 2 | Systems that have been Scanned | test | dynamic | 152 | 2023-01-09T13:14:43Z |
tenable-sc-create-asset
Requires security manager role. Create an asset in Tenable.sc with provided IP addresses.
Base Command
tenable-sc-create-asset
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Asset name. | Required |
| description | Asset description. | Optional |
| owner_id | Asset owner ID. Default is the Session User ID. Can be retrieved from the list-users command. | Optional |
| tag | Asset tag. | Optional |
| ip_list | Comma-separated list of IPs to include in the asset, e.g., 10.0.0.2,10.0.0.4. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Asset.Name | string | Asset name. |
| TenableSC.Asset.ID | string | Asset ID. |
| TenableSC.Asset.OwnerName | string | Asset owner name. |
| TenableSC.Asset.Tags | string | Asset tags. |
Human Readable Output
Asset created successfully
| ID | Name | OwnerName |
|---|---|---|
| 42 | example output | yuv |
tenable-sc-get-asset
Requires security manager role. Get details for a given asset in Tenable.sc.
Base Command
tenable-sc-get-asset
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | Asset ID that can be retrieved from the list-assets command. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Asset.ID | number | Asset ID. |
| TenableSC.Asset.Name | string | Asset name. |
| TenableSC.Asset.Description | string | Asset description. |
| TenableSC.Asset.Tag | string | Asset tag. |
| TenableSC.Asset.Modified | date | Asset last modified time. |
| TenableSC.Asset.Owner | string | Asset owner user name. |
| TenableSC.Asset.Group | string | Asset owner group. |
| TenableSC.Asset.IPs | unknown | Asset viewable IPs. |
Human Readable Output
Tenable.sc Asset
| ID | Name | Description | Created | Modified | Owner | Group | IPs |
|---|---|---|---|---|---|---|---|
| 1 | asset_1_name | asset_1_description | 2023-01-09T13:14:43Z | 2023-05-21T09:12:52Z | test | Full Access | {IPs_list} |
tenable-sc-delete-asset
Requires security manager role. Delete the asset with the given ID from Tenable.sc.
Base Command
tenable-sc-delete-asset
Input
| Argument Name | Description | Required |
|---|---|---|
| asset_id | Asset ID. | Required |
Context Output
There is no context output for this command.
Human Readable Output
Asset {asset_id} was deleted successfully.
tenable-sc-list-alerts
Requires security manager role. List alerts from Tenable.sc.
Base Command
tenable-sc-list-alerts
Input
| Argument Name | Description | Required |
|---|---|---|
| manageable | Whether to return only manageable alerts. Returns both usable and manageable by default. Possible values are: true, false. Default is false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Alert.ID | string | Alert ID. |
| TenableSC.Alert.Name | string | Alert name. |
| TenableSC.Alert.Description | string | Alert description. |
| TenableSC.Alert.State | string | Alert state. |
| TenableSC.Alert.Actions | string | Alert actions. |
| TenableSC.Alert.LastTriggered | date | Alert last triggered time. |
| TenableSC.Alert.LastEvaluated | date | Alert last evaluated time. |
| TenableSC.Alert.Group | string | Alert owner group name. |
| TenableSC.Alert.Owner | string | Alert owner user name. |
Human Readable Output
Tenable.sc Alerts
| ID | Name | Actions | State | LastTriggered | LastEvaluated | Group | Owner |
|---|---|---|---|---|---|---|---|
| 1 | Test Alert 1 | ticket | Triggered | 2023-02-16T07:13:08Z | 2023-05-23T13:30:01Z | Full Access | lmanager |
| 2 | Test Alert 2 | scan | Triggered | 2023-02-16T07:14:07Z | 2023-05-24T12:14:08Z | Full Access | lmanager |
tenable-sc-get-alert
Requires security manager role. Get information about a given alert in Tenable.sc.
Base Command
tenable-sc-get-alert
Input
| Argument Name | Description | Required |
|---|---|---|
| alert_id | Alert ID. Can be retrieved from the list-alerts command. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Alert.ID | string | Alert ID. |
| TenableSC.Alert.Name | string | Alert name. |
| TenableSC.Alert.Description | string | Alert description. |
| TenableSC.Alert.State | string | Alert state. |
| TenableSC.Alert.Condition.Trigger | string | Alert trigger. |
| TenableSC.Alert.LastTriggered | date | Alert last triggered time. |
| TenableSC.Alert.Condition.Query | string | Alert query name. |
| TenableSC.Alert.Condition.Filter.Name | string | Alert query filter name. |
| TenableSC.Alert.Condition.Filter.Values | Unknown | Alert query filter values. |
| TenableSC.Alert.Action.Type | string | Alert action type. |
| TenableSC.Alert.Action.Values | Unknown | Alert action values. |
Human Readable Output
Tenable.sc Alert
| ID | Name | LastTriggered | State | Behavior | |
|---|---|---|---|---|---|
| 1 | Test Alert 1 | 2023-02-16T07:13:08Z | Triggered | Execute only on first trigger |
Condition
| Trigger | Query |
|---|---|
| sumip \u003e= 10 | Query for alert ‘Test Alert 1’ at 1676531587 |
Actions
| Type | Values |
|---|---|
| ticket | lmanager |
tenable-sc-get-device
Requires security manager role. Gets the specified device information.
Base Command
tenable-sc-get-device
Input
| Argument Name | Description | Required |
|---|---|---|
| ip | A valid IP address of a device. | Optional |
| dns_name | DNS name of a device. | Optional |
| repository_id | Repository ID to get the device from. Can be retrieved from the list-repositories command. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Device.IP | string | Device IP address. |
| TenableSC.Device.UUID | string | Device UUID. |
| TenableSC.Device.RepositoryID | string | Device repository ID. |
| TenableSC.Device.MacAddress | string | Device Mac address. |
| TenableSC.Device.NetbiosName | string | Device Netbios name. |
| TenableSC.Device.DNSName | string | Device DNS name. |
| TenableSC.Device.OS | string | Device operating system. |
| TenableSC.Device.OsCPE | string | Device Common Platform Enumeration. |
| TenableSC.Device.LastScan | date | Device’s last scan time. |
| TenableSC.Device.RepositoryName | string | Device repository name. |
| TenableSC.Device.TotalScore | number | Device total threat score. |
| TenableSC.Device.LowSeverity | number | Device total threat scores with low severity. |
| TenableSC.Device.MediumSeverity | number | Device total threat scores with medium severity. |
| TenableSC.Device.HighSeverity | number | Device total threat scores with high severity. |
| TenableSC.Device.CriticalSeverity | number | Device total threat scores with critical severity. |
| Endpoint.IPAddress | string | Endpoint IP address. |
| Endpoint.Hostname | string | Endpoint DNS name. |
| Endpoint.MACAddress | string | Endpoint MAC address. |
| Endpoint.OS | string | Endpoint OS. |
Human Readable Output
Tenable.sc Device
| IP | UUID | MacAddress |
|---|---|---|
| {IP} | {UUID} | {MacAddress} |
tenable-sc-list-users
List users in Tenable.sc. Results may vary based on the role type (admin or security manager).
Base Command
tenable-sc-list-users
Input
| Argument Name | Description | Required |
|---|---|---|
| id | Filter by user ID. | Optional |
| username | Filter by user username. | Optional |
| Filter by user email address. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.User.ID | string | User ID. |
| TenableSC.User.Username | string | Username. |
| TenableSC.User.FirstName | string | User first name. |
| TenableSC.User.LastName | string | User last name. |
| TenableSC.User.Title | string | User title. |
| TenableSC.User.Email | string | User email address. |
| TenableSC.User.Created | date | The creation time of the user. |
| TenableSC.User.Modified | date | Last modification time of the user. |
| TenableSC.User.Login | date | User last login. |
| TenableSC.User.Role | string | User role name. |
Human Readable Output
Tenable.sc Users
| ID | Username | Title | Created | Modified | LastLogin | Role | |
|---|---|---|---|---|---|---|---|
| 1 | test | 2023-01-09T13:13:53Z | 2023-05-24T10:23:29Z | Security Manager | |||
| 2 | secman | 2023-02-06T09:54:47Z | 2023-05-01T10:05:46Z | 2023-05-24T12:43:35Z | Security Manager |
tenable-sc-get-system-licensing
Retrieve licensing information from Tenable.sc. Requires admin role.
Base Command
tenable-sc-get-system-licensing
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Status.ActiveIPS | number | Number of active IP addresses. |
| TenableSC.Status.LicensedIPS | Unknown | Number of licensed IP addresses. |
| TenableSC.Status.License | Unknown | License status. |
Human Readable Output
Tenable.sc Licensing information
| License | LicensedIPS | ActiveIPS |
|---|---|---|
| Valid | 512 | 152 |
tenable-sc-get-system-information
Get the system information and diagnostics from Tenable.sc. Requires admin role.
Base Command
tenable-sc-get-system-information
Input
There are no input arguments for this command.
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.System.Version | string | System version. |
| TenableSC.System.BuildID | string | System build ID. |
| TenableSC.System.ReleaseID | string | System release ID. |
| TenableSC.System.License | string | System license status. |
| TenableSC.System.JavaStatus | boolean | Server Java status. |
| TenableSC.System.RPMStatus | boolean | Server RPM status. |
| TenableSC.System.DiskStatus | boolean | Server disk status. |
| TenableSC.System.DiskThreshold | number | Disk threshold. |
| TenableSC.System.LastCheck | date | System last check time. |
Human Readable Output
Tenable.sc System information
| RPMStatus | JavaStatus | DiskStatus | DiskThreshold | LastCheck |
|---|---|---|---|---|
| true | true | true | 5% | 2023-05-24T04:10:02Z |
tenable-sc-get-all-scan-results
Returns all scan results in Tenable.sc. Requires security manager role.
Base Command
tenable-sc-get-all-scan-results
Input
| Argument Name | Description | Required |
|---|---|---|
| manageable | Filter only manageable alerts. By default, returns both usable and manageable alerts. Possible values are: true, false. Default is false. | Optional |
| page | The page to return, starting from 0. Default is 0. | Optional |
| limit | The number of objects to return in one response (maximum limit is 200). Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ScanResults.ID | Number | Scan ID. |
| TenableSC.ScanResults.Name | string | Scan name. |
| TenableSC.ScanResults.Status | string | Scan status. |
| TenableSC.ScanResults.Description | string | Scan description. |
| TenableSC.ScanResults.Policy | string | Scan policy. |
| TenableSC.ScanResults.Group | string | Scan group name. |
| TenableSC.ScanResults.Checks | number | Scan completed number of checks. |
| TenableSC.ScanResults.StartTime | date | Scan results start time. |
| TenableSC.ScanResults.EndTime | date | Scan results end time. |
| TenableSC.ScanResults.Duration | number | Scan duration in minutes. |
| TenableSC.ScanResults.ImportTime | date | Scan import time. |
| TenableSC.ScanResults.ScannedIPs | number | Number of scanned IPs. |
| TenableSC.ScanResults.Owner | string | Scan owner name. |
| TenableSC.ScanResults.RepositoryName | string | Scan repository name. |
| TenableSC.ScanResults.ImportStatus | string | Scan import status. |
Human Readable Output
Tenable.sc Scan results - 0-1
Total number of elements is 77
| ID | Name | Status | Description | Policy | Group | Owner | ScannedIPs | StartTime | EndTime | Duration | Checks | ImportTime | RepositoryName |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 92 | test_scan_2023-mart-05-1950 | Error | Test scan 2023 | Network Scan | Full Access | secman | 0 | 2023-04-24T23:50:07Z | 2023-04-25T01:10:13Z | 80.1 | 22639720 | Local | |
| 93 | test_scan_2023-mart-05-1950 | Error | Test scan 2023 | Network Scan | Full Access | secman | 0 | 2023-04-25T23:50:07Z | 2023-04-26T00:30:44Z | 40.61666666666667 | 12624659 | Local |
tenable-sc-list-groups
List all groups. Requires security manager role.
Base Command
tenable-sc-list-groups
Input
| Argument Name | Description | Required |
|---|---|---|
| show_users | Whether to show group member. Possible values are: true, false. Default is true. | Optional |
| limit | The number of objects to return in one response. Default is 50. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Group.Name | string | Group name. |
| TenableSC.Group.ID | number | Group ID. |
| TenableSC.Group.Description | string | Group description. |
| TenableSC.Group.Users.Firstname | string | Group’s user’s first name. |
| TenableSC.Group.Users.Lastname | string | Group’s user’s last name. |
| TenableSC.Group.Users.ID | string | Group’s user’s ID. |
| TenableSC.Group.Users.UUID | string | Group’s user’s UUID. |
| TenableSC.Group.Users.Username | string | Group’s user’s username. |
Human Readable Output
Tenable.sc groups
| ID |
|---|
| 0 |
Group id:0
| Username | Firstname | Lastname |
|---|---|---|
| test | test | |
| secman | ||
| testuser1 | fname | lname |
| testuser444 | fname2 | lname2 |
| testuser3 | fname3 | lname3 |
tenable-sc-create-user
Creates a new user. This command can be executed with both roles (admin or security manager) based on the role_id you choose.
Base Command
tenable-sc-create-user
Input
| Argument Name | Description | Required |
|---|---|---|
| first_name | The user’s first name. | Optional |
| last_name | The user’s last name. | Optional |
| user_name | The user’s username. | Required |
| The user’s email address. Required if email_notice is given. | Optional | |
| address | The user’s postal address. | Optional |
| phone | The user’s phone number. | Optional |
| city | The city the user is living in. | Optional |
| state | The state the user is living in. | Optional |
| country | The country the user is living in. | Optional |
| locked | Whether the user should be locked. Possible values are: true, false. Default is false. | Optional |
| email_notice | If different from None, a valid email address must be given. Possible values are: both, password, id, none. Default is none. | Optional |
| auth_type | The authentication type. Tenable (TNS). Lightweight Directory Access Protocol (LDAP). Security Assertion Markup Language (SAML). LDAP server or SAML authentication needs to be configured in order to select LDAP or SAML. Possible values are: ldap, legacy, linked, saml, tns. Default is tns. | Required |
| password | The user’s password. Must be at least 3 characters. | Required |
| time_zone | The user timezone, possible values can be found here: https://docs.oracle.com/middleware/1221/wcs/tag-ref/MISC/TimeZones.html. | Optional |
| role_id | The user’s role. Only an Administrator can create Administrator accounts. Possible values are: Administrator, Security Manager, Security Analyst, Vulnerability Analyst, Executive, Credential Manager, Auditor. | Required |
| must_change_password | Whether the password must be changed. When choosing LDAP or SAML auth types, ‘must_change_password’ must be set to False. For all other cases can be either True or False. Possible values are: false, true. Default is false. | Optional |
| managed_users_groups | Comma-separated list of session user’s role that can manage groups. Use tenable-sc-list-groups to get all available groups. | Optional |
| managed_objects_groups | Comma-separated list of the session user’s role that can manage groups. Use tenable-sc-list-groups to get all available groups. | Optional |
| group_id | Valid group ID whose users can be managed by the created user. | Required |
| responsible_asset_id | Default is 0. ID of a valid, usable, accessible asset. Use tenable-sc-list-assets to get all available assets. -1 is not set, 0 is all assets, and other numbers are asset ID. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.User.Address | String | User address. |
| TenableSC.User.ApiKeys | Unknown | User API keys. |
| TenableSC.User.AuthType | String | User auth type. |
| TenableSC.User.CanManage | Boolean | Whether the user has manage permissions. |
| TenableSC.User.CanUse | Boolean | Whether the user has use permissions. |
| TenableSC.User.City | String | User city of residence. |
| TenableSC.User.Country | String | User country of residence. |
| TenableSC.User.CreatedTime | Date | User creation time. |
| TenableSC.User.Email | String | User email address. |
| TenableSC.User.FailedLogins | String | Number of failed user logins. |
| TenableSC.User.Fax | String | User fax. |
| TenableSC.User.Fingerprint | Unknown | User fingerprint. |
| TenableSC.User.Firstname | String | User first name. |
| TenableSC.User.group.Description | String | User group’s description. |
| TenableSC.User.Group.ID | String | User group’s ID. |
| TenableSC.User.Group.Name | String | User group’s name. |
| TenableSC.User.ID | String | User ID. |
| TenableSC.User.LastLogin | String | User last login time. |
| TenableSC.User.LastLoginIP | String | User last login IP. |
| TenableSC.User.Lastname | String | User last name. |
| TenableSC.User.Ldap.Description | String | User LDAP description. |
| TenableSC.User.Ldap.ID | Number | User LDAP ID. |
| TenableSC.User.Ldap.Name | String | User LDAP name. |
| TenableSC.User.LdapUsername | String | user LDAP username. |
| TenableSC.User.Locked | String | Whether user is locked. |
| TenableSC.User.ManagedObjectsGroups.Description | String | User managed object groups description. |
| TenableSC.User.ManagedObjectsGroups.ID | String | User managed object groups ID. |
| TenableSC.User.ManagedObjectsGroups.Name | String | User managed object groups name. |
| TenableSC.User.ManagedUsersGroups.Description | String | User managed users groups description. |
| TenableSC.User.ManagedUsersGroups.ID | String | User managed users groups ID. |
| TenableSC.User.ManagedUsersGroups.Name | String | User managed users groups name. |
| TenableSC.User.ModifiedTime | Date | User last modification time. |
| TenableSC.User.MustChangePassword | String | If user must change password. |
| TenableSC.User.Password | String | If user password is set. |
| TenableSC.User.Phone | String | User phone number. |
| TenableSC.User.Preferences.Name | String | User preferences name. |
| TenableSC.User.Preferences.Tag | String | User preferences tag. |
| TenableSC.User.Preferences.Value | String | User preferences value. |
| TenableSC.User.ResponsibleAsset.Description | String | User responsible asset description. |
| TenableSC.User.ResponsibleAsset.ID | String | User responsible asset ID. |
| TenableSC.User.ResponsibleAsset.Name | String | User responsible asset name. |
| TenableSC.User.ResponsibleAsset.UUID | Unknown | User responsible asset UUID. |
| TenableSC.User.Role.Description | String | User role description. |
| TenableSC.User.Role.ID | String | User role ID. |
| TenableSC.User.Role.Name | String | User role name. |
| TenableSC.User.State | String | User state. |
| TenableSC.User.Status | String | User status. |
| TenableSC.User.Title | String | User title. |
| TenableSC.User.Username | String | User username. |
| TenableSC.User.UUID | String | User UUID. |
Human Readable Output
User example_output was created successfully
| User type | User Id | User Status | User Name | User Role Name | User Group Name |
|---|---|---|---|---|---|
| regular | 57 | 0 | example_output | Security Analyst | Full Access |
tenable-sc-update-user
Update user details of the given user_id.
Base Command
tenable-sc-update-user
Input
| Argument Name | Description | Required |
|---|---|---|
| first_name | The user’s first name. | Optional |
| last_name | The user’s last name. | Optional |
| user_name | The user’s username. | Optional |
| The user’s email address. Required if email_notice is given. | Optional | |
| address | The user’s postal address. | Optional |
| phone | The user’s phone number. | Optional |
| city | The city the user is living in. | Optional |
| state | The state the user is living in. | Optional |
| country | The country the user is living in. | Optional |
| locked | Whether the user should be locked. Possible values are: true, false. Default is false. | Optional |
| time_zone | The user timezone. Possible values can be found here: https://docs.oracle.com/middleware/1221/wcs/tag-ref/MISC/TimeZones.html. | Optional |
| role_id | The user’s role. Only an Administrator can create Administrator accounts. Possible values are: Administrator, Security Manager, Security Analyst, Vulnerability Analyst, Executive, Credential Manager, Auditor. | Optional |
| must_change_password | Whether the password must be changed. When choosing LDAP or SAML auth types, ‘must_change_password’ must be set to False. For all other cases can be either True or False. Possible values are: false, true. Default is false. | Optional |
| managed_users_groups | Comma-separated list of session user’s role that can manage groups. Use tenable-sc-list-groups to get all available groups. | Optional |
| managed_objects_groups | Comma-separated list of session user’s role that can manage groups. Use tenable-sc-list-groups to get all available groups. | Optional |
| group_id | Valid group ID whose users can be managed by the created user. | Optional |
| responsible_asset_id | ID of a valid, usable, accessible asset. Use tenable-sc-list-assets to get all available assets. -1 is not set, 0 is all assets, and other numbers are asset ID. | Optional |
| password | The new password to set. Must be given with current_password. Must be at least 3 characters. | Optional |
| current_password | This is the admin/Security Manager password from the instance parameters. Required when attempting to change a user’s password. | Optional |
| user_id | The ID of the user whose details you want to update. | Required |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.User.Address | String | User address. |
| TenableSC.User.ApiKeys | Unknown | User API keys. |
| TenableSC.User.AuthType | String | User auth type. |
| TenableSC.User.CanManage | Boolean | Whether the user has manage permissions. |
| TenableSC.User.CanUse | Boolean | Whether the user has use permissions. |
| TenableSC.User.City | String | User city of residence. |
| TenableSC.User.Country | String | User country of residence. |
| TenableSC.User.CreatedTime | Date | User creation time. |
| TenableSC.User.Email | String | User email address. |
| TenableSC.User.FailedLogins | String | Number of failed user logins. |
| TenableSC.User.Fax | String | User fax. |
| TenableSC.User.Fingerprint | Unknown | User fingerprint. |
| TenableSC.User.Firstname | String | User first name. |
| TenableSC.User.group.Description | String | User group’s description. |
| TenableSC.User.Group.ID | String | User group’s ID. |
| TenableSC.User.Group.Name | String | User group’s name. |
| TenableSC.User.ID | String | User ID. |
| TenableSC.User.LastLogin | String | User last login time. |
| TenableSC.User.LastLoginIP | String | User last login IP. |
| TenableSC.User.Lastname | String | User last name. |
| TenableSC.User.Ldap.Description | String | User LDAP description. |
| TenableSC.User.Ldap.ID | Number | User LDAP ID. |
| TenableSC.User.Ldap.Name | String | User LDAP name. |
| TenableSC.User.LdapUsername | String | User LDAP username. |
| TenableSC.User.Locked | String | Whether user is locked. |
| TenableSC.User.ManagedObjectsGroups.Description | String | User managed object groups description. |
| TenableSC.User.ManagedObjectsGroups.ID | String | User managed object groups ID. |
| TenableSC.User.ManagedObjectsGroups.Name | String | User managed object groups name. |
| TenableSC.User.ManagedUsersGroups.Description | String | User managed users groups description. |
| TenableSC.User.ManagedUsersGroups.ID | String | User managed users groups ID. |
| TenableSC.User.ManagedUsersGroups.Name | String | User managed users groups name. |
| TenableSC.User.ModifiedTime | Date | User last modification time. |
| TenableSC.User.MustChangePassword | String | If user must change password. |
| TenableSC.User.Password | String | If user password is set. |
| TenableSC.User.Phone | String | User phone number. |
| TenableSC.User.Preferences.Name | String | User preferences name. |
| TenableSC.User.Preferences.Tag | String | User preferences tag. |
| TenableSC.User.Preferences.Value | String | User preferences value. |
| TenableSC.User.ResponsibleAsset.Description | String | User responsible asset description. |
| TenableSC.User.ResponsibleAsset.ID | String | User responsible asset ID. |
| TenableSC.User.ResponsibleAsset.Name | String | User responsible asset name. |
| TenableSC.User.ResponsibleAsset.UUID | Unknown | User responsible asset UUID. |
| TenableSC.User.Role.Description | String | User role description. |
| TenableSC.User.Role.ID | String | User role ID. |
| TenableSC.User.Role.Name | String | User role name. |
| TenableSC.User.State | String | User state. |
| TenableSC.User.Status | String | User status. |
| TenableSC.User.Title | String | User title. |
| TenableSC.User.Username | String | User username. |
| TenableSC.User.UUID | String | User UUID. |
Human Readable Output
user 23 was updated successfully
| User type | User Id | User Status | User Name | First Name | Lat Name | User Role Name | User Group Name | |
|---|---|---|---|---|---|---|---|---|
| regular | 23 | 0 | testuser30 | testuser30 | testuser30 | testuser30@mymail.com | Credential Manager | Full Access |
tenable-sc-delete-user
Delete a user by given user_id. This command can be executed with both roles (admin or security manager).
Base Command
tenable-sc-delete-user
Input
| Argument Name | Description | Required |
|---|---|---|
| user_id | The ID of the user we want to delete. | Required |
Context Output
There is no context output for this command.
Human Readable Output
User {user_id} was deleted successfully.
tenable-sc-list-plugin-family
List plugin families / return information about a plugin family given ID. Requires security manager role.
Base Command
tenable-sc-list-plugin-family
Input
| Argument Name | Description | Required |
|---|---|---|
| plugin_id | The ID of the plugin to search. If given, other arguments will be ignored. | Optional |
| limit | The number of objects to return in one response (maximum limit is 200). Ignored when plugin_id is given. Default is 50. | Optional |
| is_active | Default is none. none - both active and passive Plugin Families are returned. true - Only active Plugin Families will be returned. false - Only passive Plugin Families will be returned. Ignored when plugin_id is given. Possible values are: true, false. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.PluginFamily.ID | String | Plugin family ID. |
| TenableSC.PluginFamily.Name | String | Plugin family name. |
| TenableSC.PluginFamily.Count | String | Number of plugins in a family. |
| TenableSC.PluginFamily.Plugins | String | The plugins list. |
| TenableSC.PluginFamily.Type | String | Plugin family type. |
Human Readable Output
When plugin_id isn’t given:
Plugin families
| Plugin ID | Plugin Name |
|---|---|
| 0 | N/A |
| 1 | Red Hat Local Security Checks |
When plugin_id is given:
Plugin families
| Plugin ID | Plugin Name | Is Active |
|---|---|---|
| 2 | HP-UX Local Security Checks | true |
tenable-sc-create-policy
Creates a policy. Requires security manager role. This command is prerequisite for creating remediation scan.
Base Command
tenable-sc-create-policy
Input
| Argument Name | Description | Required |
|---|---|---|
| policy_name | The name of the policy to create. | Optional |
| policy_description | The description of the policy to create. | Optional |
| policy_template_id | Policy template id. Default is 1. Default is 1. | Required |
| port_scan_range | Possible values: default, all or a comma-separated list of values - 21,23,25,80,110. | Optional |
| tcp_scanner | Only possible if you are using Linux or FreeBSD. On Windows or macOS, the scanner does not do a TCP scan and instead uses the SYN scanner. If you enable this option, you can also set the syn_firewall_detection option. Possible values are: no, yes. Default is no. | Optional |
| syn_scanner | Identifies open TCP ports on the target hosts. If you enable this option, you can also set the syn_firewall_detection option. Possible values are: no, yes. Default is yes. | Optional |
| udp_scanner | Enabling the UDP port scanner may dramatically increase the scan time and produce unreliable results. Consider using the netstat or SNMP port enumeration options instead if possible. Possible values are: no, yes. Default is no. | Optional |
| family_id | Family ID. Can be retrieved from the result of the tenable-sc-list-plugin-family command. | Required |
| plugins_id | Comma-separated list of plugin_ids, Can be retrieved from the result of the tenable-sc-list-plugin-family command with family_id as the argument. | Required |
| syn_firewall_detection | Rely on local port enumeration first before relying on network port scans. Possible values are: Automatic (normal), Do not detect RST rate limitation(soft), Ignore closed ports(aggressive), Disabled(softer). Default is Automatic (normal). | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.ScanPolicy.AuditFiles | Unknown | Policy audit files. |
| TenableSC.ScanPolicy.CanManage | String | Policy permissions. |
| TenableSC.ScanPolicy.CanUse | String | Policy permissions. |
| TenableSC.ScanPolicy.Context | String | Policy context. |
| TenableSC.ScanPolicy.CreatedTime | Date | Policy creation time. |
| TenableSC.ScanPolicy.Creator.Firstname | String | Policy creator first name. |
| TenableSC.ScanPolicy.Creator.ID | String | Policy creator ID. |
| TenableSC.ScanPolicy.Creator.Lastname | String | Policy creator last name. |
| TenableSC.ScanPolicy.Creator.Username | String | Policy creator user name. |
| TenableSC.ScanPolicy.Creator.UUID | String | Policy creator UUID. |
| TenableSC.ScanPolicy.Description | String | Policy description. |
| TenableSC.ScanPolicy.Families.Count | String | Policy number of families. |
| TenableSC.ScanPolicy.Families.ID | String | Policy family ID. |
| TenableSC.ScanPolicy.Families.Name | String | Policy family name. |
| TenableSC.ScanPolicy.Families.Plugins | Unknown | Policy family plugins. |
| TenableSC.ScanPolicy.GenerateXCCDFResults | String | Policy generated XCCDF results. |
| TenableSC.ScanPolicy.Groups | Unknown | Policy groups. |
| TenableSC.ScanPolicy.ID | String | Policy ID. |
| TenableSC.ScanPolicy.ModifiedTime | Date | Policy last modification time. |
| TenableSC.ScanPolicy.Name | String | Policy name. |
| TenableSC.ScanPolicy.Owner.Firstname | String | Policy owner first name. |
| TenableSC.ScanPolicy.Owner.ID | String | Policy owner ID. |
| TenableSC.ScanPolicy.Owner.Lastname | String | Policy owner last name. |
| TenableSC.ScanPolicy.Owner.Username | String | Policy owner username. |
| TenableSC.ScanPolicy.Owner.UUID | String | Policy owner UUID. |
| TenableSC.ScanPolicy.OwnerGroup.Description | String | Policy owner group description. |
| TenableSC.ScanPolicy.OwnerGroup.ID | String | Policy owner group ID. |
| TenableSC.ScanPolicy.OwnerGroup.Name | String | Policy owner group name. |
| TenableSC.ScanPolicy.PolicyTemplate.Agent | String | Policy template agent. |
| TenableSC.ScanPolicy.PolicyTemplate.Description | String | Policy template description. |
| TenableSC.ScanPolicy.PolicyTemplate.ID | String | Policy template ID. |
| TenableSC.ScanPolicy.PolicyTemplate.Name | String | Policy template name. |
| TenableSC.ScanPolicy.Preferences.PortscanRange | String | Policy port scan range. |
| TenableSC.ScanPolicy.Preferences.SynFirewallDetection | String | Policy SYN firewall detection. |
| TenableSC.ScanPolicy.Preferences.SynScanner | String | Policy SYN scanner. |
| TenableSC.ScanPolicy.Preferences.TcpScanner | String | Policy TCP scanner. |
| TenableSC.ScanPolicy.Preferences.UdpScanner | String | Policy UDP scanner. |
| TenableSC.ScanPolicy.Status | String | Policy status. |
| TenableSC.ScanPolicy.tags | String | Policy tags. |
| TenableSC.ScanPolicy.TargetGroup.Description | String | Policy target group description. |
| TenableSC.ScanPolicy.TargetGroup.ID | Number | Policy target group ID. |
| TenableSC.ScanPolicy.TargetGroup.Name | String | Policy target group name. |
| TenableSC.ScanPolicy.UUID | String | Policy UUID. |
Human Readable Output
Policy was created successfully
| Policy type | name | Created Time | Plugin Families | Policy Status | Policy UUID | Policy can Manage | Creator Username | policyTemplate Name |
|---|---|---|---|---|---|---|---|---|
| regular | scan_name | 1684923394 | {‘id’: ‘1’, ‘name’: ‘Red Hat Local Security Checks’, ‘count’: ‘9297’, ‘plugins’: []} | 0 | {policy UUID} | true | yuv | Advanced Scan |
tenable-sc-list-query
Lists the queries. Requires security manager role.
Base Command
tenable-sc-list-query
Input
| Argument Name | Description | Required |
|---|---|---|
| query_id | The ID of the query to search. | Optional |
| type | The query type to retrieve. When no type is set all queries are returned. Possible values are: alert, lce, mobile, ticket, user. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Query.Manageable.BrowseColumns | String | Relevant only when query_id is not given. Manageable Query browse columns. |
| TenableSC.Query.Manageable.BrowseSortColumn | String | Relevant only when query_id is not given. Manageable Query browse sort column. |
| TenableSC.Query.Manageable.BrowseSortDirection | String | Relevant only when query_id is not given. Manageable Query browse sort direction. |
| TenableSC.Query.Manageable.CanManage | String | Relevant only when query_id is not given. Manageable Query permissions. |
| TenableSC.Query.Manageable.CanUse | String | Relevant only when query_id is not given. Manageable Query permissions. |
| TenableSC.Query.Manageable.Context | String | Relevant only when query_id is not given. Manageable Query context. |
| TenableSC.Query.Manageable.CreatedTime | Date | Relevant only when query_id is not given. Manageable Query creation time. |
| TenableSC.Query.Manageable.Creator.Firstname | String | Relevant only when query_id is not given. Manageable Query Creator first name. |
| TenableSC.Query.Manageable.Creator.ID | String | Relevant only when query_id is not given. Manageable Query Creator ID. |
| TenableSC.Query.Manageable.Creator.Lastname | String | Relevant only when query_id is not given. Manageable Query Creator last name. |
| TenableSC.Query.Manageable.Creator.Username | String | Relevant only when query_id is not given. Manageable Query Creator user name. |
| TenableSC.Query.Manageable.Creator.UUID | String | Relevant only when query_id is not given. Manageable Query Creator UUID. |
| TenableSC.Query.Manageable.Description | String | Relevant only when query_id is not given. Manageable Query description. |
| TenableSC.Query.Manageable.Filters.FilterName | String | Relevant only when query_id is not given. Manageable Query filter name. |
| TenableSC.Query.Manageable.Filters.Operator | String | Relevant only when query_id is not given. Manageable Query filter operator. |
| TenableSC.Query.Manageable.Filters.Value | String | Relevant only when query_id is not given. Manageable Query filter value |
| TenableSC.Query.Manageable.Groups | Unknown | Relevant only when query_id is not given. Manageable Query groups. |
| TenableSC.Query.Manageable.ID | String | Relevant only when query_id is not given. Manageable Query ID. |
| TenableSC.Query.Manageable.ModifiedTime | Date | Relevant only when query_id is not given. Manageable Query modification time. |
| TenableSC.Query.Manageable.Name | String | Relevant only when query_id is not given. Manageable Query name. |
| TenableSC.Query.Manageable.Owner.Firstname | String | Relevant only when query_id is not given. Manageable Query owner first name. |
| TenableSC.Query.Manageable.Owner.ID | String | Relevant only when query_id is not given. Manageable Query owner ID. |
| TenableSC.Query.Manageable.Owner.Lastname | String | Relevant only when query_id is not given. Manageable Query owner last name. |
| TenableSC.Query.Manageable.Owner.Username | String | Relevant only when query_id is not given. Manageable Query owner user name. |
| TenableSC.Query.Manageable.Owner.UUID | String | Relevant only when query_id is not given. Manageable Query owner UUID. |
| TenableSC.Query.Manageable.OwnerGroup.Description | String | Relevant only when query_id is not given. Manageable Query owner group description. |
| TenableSC.Query.Manageable.OwnerGroup.ID | String | Relevant only when query_id is not given. Manageable Query owner group ID. |
| TenableSC.Query.Manageable.OwnerGroup.Name | String | Relevant only when query_id is not given. Manageable Query owner group name. |
| TenableSC.Query.Manageable.Status | String | Relevant only when query_id is not given. Manageable Query status. |
| TenableSC.Query.Manageable.Tags | String | Relevant only when query_id is not given. Manageable Query tags. |
| TenableSC.Query.Manageable.TargetGroup.Description | String | Relevant only when query_id is not given. Manageable Query target group description. |
| TenableSC.Query.Manageable.TargetGroup.ID | Number | Relevant only when query_id is not given. Manageable Query target group ID. |
| TenableSC.Query.Manageable.TargetGroup.Name | String | Relevant only when query_id is not given. Manageable Query target group name. |
| TenableSC.Query.Manageable.Tool | String | Relevant only when query_id is not given. Manageable Query tool. |
| TenableSC.Query.Manageable.Type | String | Relevant only when query_id is not given. Manageable Query type. |
| TenableSC.Query.Manageable.Filters.Value.Description | String | Relevant only when query_id is not given. Manageable Query filter value description. |
| TenableSC.Query.Manageable.Filters.Value.ID | String | Relevant only when query_id is not given. Manageable Query filter value ID. |
| TenableSC.Query.Manageable.Filters.Value.Name | String | Relevant only when query_id is not given. Manageable Query filter value name. |
| TenableSC.Query.Manageable.Filters.Value.Type | String | Relevant only when query_id is not given. Manageable Query filter value type. |
| TenableSC.Query.Manageable.Filters.Value.UUID | String | Relevant only when query_id is not given. Manageable Query filter value UUID |
| TenableSC.Query.Manageable.Filters | Unknown | Relevant only when query_id is not given. Manageable Query filters. |
| TenableSC.Query.Usable.BrowseColumns | String | Relevant only when query_id is not given. Usable Query browse columns. |
| TenableSC.Query.Usable.BrowseSortColumn | String | Relevant only when query_id is not given. Usable Query browse sort column. |
| TenableSC.Query.Usable.BrowseSortDirection | String | Relevant only when query_id is not given. Usable Query browse sort direction. |
| TenableSC.Query.Usable.CanManage | String | Relevant only when query_id is not given. Usable Query permissions. |
| TenableSC.Query.Usable.CanUse | String | Relevant only when query_id is not given. Usable Query permissions. |
| TenableSC.Query.Usable.Context | String | Relevant only when query_id is not given. Usable Query context. |
| TenableSC.Query.Usable.CreatedTime | Date | Relevant only when query_id is not given. Usable Query creation time. |
| TenableSC.Query.Usable.Creator.Firstname | String | Relevant only when query_id is not given. Usable Query Creator first name. |
| TenableSC.Query.Usable.Creator.ID | String | Relevant only when query_id is not given. Usable Query Creator ID. |
| TenableSC.Query.Usable.Creator.Lastname | String | Relevant only when query_id is not given. Usable Query Creator last name. |
| TenableSC.Query.Usable.Creator.Username | String | Relevant only when query_id is not given. Usable Query Creator user name. |
| TenableSC.Query.Usable.Creator.UUID | String | Relevant only when query_id is not given. Usable Query Creator UUID. |
| TenableSC.Query.Usable.Description | String | Relevant only when query_id is not given. Usable Query description. |
| TenableSC.Query.Usable.Filters.FilterName | String | Relevant only when query_id is not given. Usable Query filter name. |
| TenableSC.Query.Usable.Filters.Operator | String | Relevant only when query_id is not given. Usable Query filter operator. |
| TenableSC.Query.Usable.Filters.Value | String | Relevant only when query_id is not given. Usable Query filter value. |
| TenableSC.Query.Usable.Groups | Unknown | Relevant only when query_id is not given. Usable Query groups. |
| TenableSC.Query.Usable.ID | String | Relevant only when query_id is not given. Usable Query ID. |
| TenableSC.Query.Usable.ModifiedTime | Date | Relevant only when query_id is not given. Usable Query modification time. |
| TenableSC.Query.Usable.Name | String | Relevant only when query_id is not given. Usable Query name. |
| TenableSC.Query.Usable.Owner.Firstname | String | Relevant only when query_id is not given. Usable Query owner first name. |
| TenableSC.Query.Usable.Owner.ID | String | Relevant only when query_id is not given. Usable Query owner ID. |
| TenableSC.Query.Usable.Owner.Lastname | String | Relevant only when query_id is not given. Usable Query owner last name. |
| TenableSC.Query.Usable.Owner.Username | String | Relevant only when query_id is not given. Usable Query owner user name. |
| TenableSC.Query.Usable.Owner.UUID | String | Relevant only when query_id is not given. Usable Query owner UUID. |
| TenableSC.Query.Usable.OwnerGroup.Description | String | Relevant only when query_id is not given. Usable Query owner group description. |
| TenableSC.Query.Usable.OwnerGroup.ID | String | Relevant only when query_id is not given. Usable Query owner group ID. |
| TenableSC.Query.Usable.OwnerGroup.Name | String | Relevant only when query_id is not given. Usable Query owner group name. |
| TenableSC.Query.Usable.Status | String | Relevant only when query_id is not given. Usable Query status. |
| TenableSC.Query.Usable.Tags | String | Relevant only when query_id is not given. Usable Query tags. |
| TenableSC.Query.Usable.TargetGroup.Description | String | Relevant only when query_id is not given. Usable Query target group description. |
| TenableSC.Query.Usable.TargetGroup.ID | Number | Relevant only when query_id is not given. Usable Query target group ID. |
| TenableSC.Query.Usable.TargetGroup.Name | String | Relevant only when query_id is not given. Usable Query target group name. |
| TenableSC.Query.Usable.Tool | String | Relevant only when query_id is not given. Usable Query tool. |
| TenableSC.Query.Usable.Type | String | Relevant only when query_id is not given. Usable Query type. |
| TenableSC.Query.Usable.Filters.Value.Description | String | Relevant only when query_id is not given. Usable Query filter value description. |
| TenableSC.Query.Usable.Filters.Value.ID | String | Relevant only when query_id is not given. Usable Query filter value ID. |
| TenableSC.Query.Usable.Filters.Value.Name | String | Relevant only when query_id is not given. Usable Query filter value name. |
| TenableSC.Query.Usable.Filters.Value.Type | String | Relevant only when query_id is not given. Usable Query filter value type. |
| TenableSC.Query.Usable.Filters.Value.UUID | String | Relevant only when query_id is not given. Usable Query filter value UUID. |
| TenableSC.Query.Usable.Filters | Unknown | Relevant only when query_id is not given. Usable Query filters. |
| TenableSC.Query.BrowseColumns | String | Relevant only when query_id is given. Query browse columns. |
| TenableSC.Query.BrowseSortColumn | String | Relevant only when query_id is given. Query browse sort columns. |
| TenableSC.Query.BrowseSortDirection | String | Relevant only when query_id is given. Query browse sort direction |
| TenableSC.Query.CanManage | String | Relevant only when query_id is given. Query permissions. |
| TenableSC.Query.CanUse | String | Relevant only when query_id is given. Query permissions. |
| TenableSC.Query.Context | String | Relevant only when query_id is given. Query context. |
| TenableSC.Query.CreatedTime | Date | Relevant only when query_id is given. Query creation time. |
| TenableSC.Query.Creator.Firstname | String | Relevant only when query_id is given. Query creator first name. |
| TenableSC.Query.Creator.ID | String | Relevant only when query_id is given. Query creator ID. |
| TenableSC.Query.Creator.Lastname | String | Relevant only when query_id is given. Query creator last name. |
| TenableSC.Query.Creator.Username | String | Relevant only when query_id is given. Query creator user name. |
| TenableSC.Query.Creator.UUID | String | Relevant only when query_id is given. Query creator UUID. |
| TenableSC.Query.Description | String | Relevant only when query_id is given. Query description. |
| TenableSC.Query.Filters | Unknown | Relevant only when query_id is given. Query filters. |
| TenableSC.Query.Groups | Unknown | Relevant only when query_id is given. Query groups. |
| TenableSC.Query.ID | String | Relevant only when query_id is given. Query ID. |
| TenableSC.Query.ModifiedTime | Date | Relevant only when query_id is given. Query modification time. |
| TenableSC.Query.Name | String | Relevant only when query_id is given. Query name. |
| TenableSC.Query.Owner.Firstname | String | Relevant only when query_id is given. Query owner first name. |
| TenableSC.Query.Owner.ID | String | Relevant only when query_id is given. Query owner ID. |
| TenableSC.Query.Owner.Lastname | String | Relevant only when query_id is given. Query owner last name. |
| TenableSC.Query.Owner.Username | String | Relevant only when query_id is given. Query owner user name. |
| TenableSC.Query.Owner.UUID | String | Relevant only when query_id is given. Query owner UUID. |
| TenableSC.Query.OwnerGroup.Description | String | Relevant only when query_id is given. Query owner group description. |
| TenableSC.Query.OwnerGroup.ID | String | Relevant only when query_id is given. Query owner group ID. |
| TenableSC.Query.OwnerGroup.Name | String | Relevant only when query_id is given. Query owner group name. |
| TenableSC.Query.Status | String | Relevant only when query_id is given. Query status. |
| TenableSC.Query.Tags | String | Relevant only when query_id is given. Query tags. |
| TenableSC.Query.TargetGroup.Description | String | Relevant only when query_id is given. Query target group description. |
| TenableSC.Query.TargetGroup.ID | Number | Relevant only when query_id is given. Query target group ID. |
| TenableSC.Query.TargetGroup.Name | String | Relevant only when query_id is given. Query target group name. |
| TenableSC.Query.Tool | String | Relevant only when query_id is given. Query tool |
| TenableSC.Query.Type | String | Relevant only when query_id is given. Query type. |
Human Readable Output
If query_id isn’t given:
Queries
| Query Id | Query Name | Query Description | Query Filters | Query Manageable | Query Usable |
|---|---|---|---|---|---|
| 1 | test_name | test_description | filter | True | True |
| 2 | test_name | test_description | True | False |
If query_id is given:
Query {query_id}
| Query Id | Query Name | Query Description |
|---|---|---|
| test_id | test_name | test_description |
tenable-sc-update-asset
Requires security manager role. Update an asset.
Base Command
tenable-sc-update-asset
Input
| Argument Name | Description | Required |
|---|---|---|
| name | Asset name. | Optional |
| asset_id | The ID of the asset to update. | Required |
| description | The asset description. | Optional |
| owner_id | The asset owner ID. | Optional |
| tag | The asset tag. | Optional |
| ip_list | Comma-separated list of the asset IPs list. | Optional |
Context Output
There is no context output for this command.
Human Readable Output
asset {asset_id} was updated successfully.
tenable-sc-create-remediation-scan
Creates a remediation scan. Requires security manager role. This command is a prerequisite for creating remediation scan.
Base Command
tenable-sc-create-remediation-scan
Input
| Argument Name | Description | Required |
|---|---|---|
| policy_name | The name of the policy to create. | Optional |
| policy_description | The description of the policy to create. | Optional |
| port_scan_range | Possible values: default, all or a comma-separated list of values - 21,23,25,80,110. | Optional |
| tcp_scanner | Only possible if you are using Linux or FreeBSD. On Windows or macOS, the scanner does not do a TCP scan and instead uses the SYN scanner..If you enable this option, you can also set the syn_firewall_detection. Possible values are: no, yes. Default is no. | Optional |
| syn_scanner | Identifies open TCP ports on the target hosts. If you enable this option, you can also set the syn_firewall_detection option. Possible values are: no, yes. Default is yes. | Optional |
| udp_scanner | Enabling the UDP port scanner may dramatically increase the scan time and produce unreliable results. Consider using the netstat or SNMP port enumeration options instead if possible. Possible values are: no, yes. Default is no. | Optional |
| syn_firewall_detection | Default is Automatic (normal). Rely on local port enumeration first before relying on network port scans. Possible values are: Automatic (normal), Do not detect RST rate limitation(soft), Ignore closed ports(aggressive), Disabled(softer). Default is Automatic (normal). | Optional |
| family_id | Can be retrieved from the result of the tenable-sc-list-plugin-family command. | Required |
| plugins_id | Comma-separated list of plugin_ids, Can be retrieved from the result of the tenable-sc-list-plugin-family command with family_id as the argument. | Required |
| scan_name | Scan name. | Required |
| description | Scan description. | Optional |
| repository_id | Scan Repository ID, can be retrieved from the list-repositories command. Default is 1. | Required |
| time_zone | The timezone for the given start_time. Possible values can be found here: https://docs.oracle.com/middleware/1221/wcs/tag-ref/MISC/TimeZones.html. | Optional |
| start_time | The scan start time, in the format of YYYY-MM-DD:HH:MM:SS or relative timestamp (i.e., now, 3 days). | Optional |
| repeat_rule_freq | Specifies repeating events based on an interval of a repeat_rule_freq or more. Possible values are: HOURLY, DAILY, WEEKLY, MONTHLY, YEARLY. | Optional |
| repeat_rule_interval | The number of repeat_rule_freq between each interval (for example: If repeat_rule_freq=DAILY and repeat_rule_interval=8 it means every eight days.). | Optional |
| repeat_rule_by_day | A comma-separated list of days of the week to run the schedule. Possible values are: SU, MO, TU, WE, TH, FR, SA. | Optional |
| asset_ids | Either no assets or comma-separated list of asset IDs to scan. Can be retrieved from the list-assets command. | Optional |
| scan_virtual_hosts | Default is false. Whether to include virtual hosts. Possible values are: true, false. | Optional |
| ip_list | Comma-separated IPs to scan, e.g., 10.0.0.1,10.0.0.2 . | Optional |
| report_ids | Comma-separated list of report definition IDs to create post-scan. Can be retrieved from the list-report-definitions command. | Optional |
| credentials | Comma-separated credentials IDs to use. Can be retrieved from the list-credentials command. | Optional |
| timeout_action | discard - do not import any of the results obtained by the scan to the database. import - Import the results of the current scan and discard the information for any unscanned targets. rollover-Import the results from the scan into the database and create a rollover scan that may be launched at a later time to complete the scan. Possible values are: discard, import, rollover. Default is import. | Optional |
| max_scan_time | Maximum scan run time in hours. Default is 1. | Optional |
| dhcp_tracking | Track hosts which have been issued new IP address, (e.g., DHCP). Possible values are: true, false. | Optional |
| enabled | Whether the schedule is enabled. The “enabled” field can only be set to “false” for schedules of type “ical”. For all other schedules types, “enabled” is set to “true”. Possible values are: true, false. Default is true. | Optional |
| rollover_type | Create a rollover scan scheduled to launch the next day at the same start time as the just completed scan. template-Create a rollover scan as a template for users to launch manually This field is required if the timeout_action is set to rollover. Default is nextDay. | Optional |
Context Output
| Path | Type | Description |
|---|---|---|
| TenableSC.Scan.Assets | Unknown | Scan assets. |
| TenableSC.Scan.CanManage | String | Scan permissions. |
| TenableSC.Scan.CanUse | String | Scan permissions. |
| TenableSC.Scan.ClassifyMitigatedAge | String | Scan classify mitigated age. |
| TenableSC.Scan.CreatedTime | Date | Scan creation time. |
| TenableSC.Scan.Creator.Firstname | String | Scan creator first name. |
| TenableSC.Scan.Creator.ID | String | Scan creator ID. |
| TenableSC.Scan.Creator.Lastname | String | Scan creator last name. |
| TenableSC.Scan.Creator.Username | String | Scan creator username. |
| TenableSC.Scan.Creator.UUID | String | Scan creator UUID. |
| TenableSC.Scan.Credentials | Unknown | Scan credentials. |
| TenableSC.Scan.Description | String | Scan description. |
| TenableSC.Scan.DhcpTracking | String | Scan DHCP tracking. |
| TenableSC.Scan.EmailOnFinish | String | Scan email on finish. |
| TenableSC.Scan.EmailOnLaunch | String | Scan email on launch. |
| TenableSC.Scan.ID | String | Scan ID. |
| TenableSC.Scan.IpList | String | Scan IP list. |
| TenableSC.Scan.MaxScanTime | String | Scan max scan time. |
| TenableSC.Scan.ModifiedTime | Date | Scan last modification time. |
| TenableSC.Scan.Name | String | Scan name. |
| TenableSC.Scan.NumDependents | Number | Scan number of dependents. |
| TenableSC.Scan.Owner.Firstname | String | Scan owner first name. |
| TenableSC.Scan.Owner.ID | String | Scan owner ID. |
| TenableSC.Scan.Owner.Lastname | String | Scan owner last name. |
| TenableSC.Scan.Owner.Username | String | Scan owner username. |
| TenableSC.Scan.Owner.UUID | String | Scan owner UUID. |
| TenableSC.Scan.OwnerGroup.Description | String | Scan owner group description. |
| TenableSC.Scan.OwnerGroup.ID | String | Scan owner group ID. |
| TenableSC.Scan.OwnerGroup.Name | String | Scan owner group name. |
| TenableSC.Scan.Plugin.Description | String | Scan plugin description. |
| TenableSC.Scan.Plugin.ID | String | Scan plugin ID. |
| TenableSC.Scan.Plugin.Name | String | Scan plugin name. |
| TenableSC.Scan.Plugin.Type | String | Scan plugin type. |
| TenableSC.Scan.Policy.Context | String | Scan policy context. |
| TenableSC.Scan.Policy.Description | String | Scan policy description. |
| TenableSC.Scan.Policy.ID | String | Scan policy ID. |
| TenableSC.Scan.Policy.Name | String | Scan policy name. |
| TenableSC.Scan.Policy.Owner.Firstname | String | Scan policy owner first name. |
| TenableSC.Scan.Policy.Owner.ID | String | Scan policy owner ID. |
| TenableSC.Scan.Policy.Owner.Lastname | String | Scan policy owner last name. |
| TenableSC.Scan.Policy.Owner.Username | String | Scan policy owner username. |
| TenableSC.Scan.Policy.Owner.UUID | String | Scan policy owner UUID. |
| TenableSC.Scan.Policy.OwnerGroup.Description | String | Scan policy owner group description. |
| TenableSC.Scan.Policy.OwnerGroup.ID | String | Scan policy owner group ID. |
| TenableSC.Scan.Policy.OwnerGroup.Name | String | Scan policy owner group name. |
| TenableSC.Scan.Policy.Tags | String | Scan policy tags. |
| TenableSC.Scan.Policy.UUID | String | Scan policy UUID. |
| TenableSC.Scan.PolicyPrefs.Name | String | Scan policy preferation name. |
| TenableSC.Scan.PolicyPrefs.Value | String | Scan policy preferation value. |
| TenableSC.Scan.Reports | Unknown | Scan reports. |
| TenableSC.Scan.Repository.Description | String | Scan repository description. |
| TenableSC.Scan.Repository.ID | String | Scan repository ID. |
| TenableSC.Scan.Repository.Name | String | Scan repository name. |
| TenableSC.Scan.Repository.Type | String | Scan repository type. |
| TenableSC.Scan.Repository.UUID | String | Scan repository UUID. |
| TenableSC.Scan.RolloverType | String | Scan rollover type. |
| TenableSC.Scan.ScanResultID | String | Scan results ID. |
| TenableSC.Scan.ScanningVirtualHosts | String | Scan virtual hosts. |
| TenableSC.Scan.Schedule.Dependent.Description | String | Scan schedule dependent description. |
| TenableSC.Scan.Schedule.Dependent.ID | Number | Scan schedule dependent ID. |
| TenableSC.Scan.Schedule.Dependent.Name | String | Scan schedule dependent name. |
| TenableSC.Scan.Schedule.Enabled | String | Scan schedule enabled. |
| TenableSC.Scan.Schedule.ID | Number | Scan schedule ID. |
| TenableSC.Scan.Schedule.NextRun | Number | Scan schedule next run. |
| TenableSC.Scan.Schedule.ObjectType | Number | Scan schedule object type. |
| TenableSC.Scan.Schedule.RepeatRule | String | Scan schedule repeat rule. |
| TenableSC.Scan.Schedule.Start | String | Scan schedule start time. |
| TenableSC.Scan.Schedule.Type | String | Scan schedule type. |
| TenableSC.Scan.Status | String | Scan status. |
| TenableSC.Scan.TimeoutAction | String | Scan timeout action. |
| TenableSC.Scan.Type | String | Scan type. |
| TenableSC.Scan.UUID | String | Scan UUID. |
| TenableSC.Scan.Zone.Description | String | Scan zone description. |
| TenableSC.Scan.Zone.ID | Number | Scan zone ID. |
| TenableSC.Scan.Zone.Name | String | Scan zone name. |
Human Readable Output
Remediation scan created successfully
| Scan ID | Scan Name | Scan Type | Dhcp Tracking status | Created Time | Modified Time | Max Scan Time | Policy id | Policy context | Schedule type | Group | Owner |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 69 | my_Test_scan | policy | false | 2023-05-24T10:12:27Z | 1684923147 | 3600 | 1000044 | scan | now | Full Access | yuv |
Vulnerabilities
| ID | Name | Family | Severity | Total |
|---|---|---|---|---|
| 10092 | FTP Server Detection | Service detection | Info | 6 |
| 10107 | HTTP Server Type and Version | Web Servers | Info | 61 |
Troubleshooting
For errors within Tenable.sc, the cause is generally specified, e.g., The currently logged in used is not an administrator, Unable to retrieve Asset #2412. Asset #2412 does not exist or Invalid login credentials. However there might be connection errors, for example when the server URL provided is incorrect.
tenable-sc-get-organization
Requires administrator role. Command to get a list of organizations’ information, depending on the comma-separated list of fields provided.
Base Command
tenable-sc-get-organization
Input
| Argument Name | Description | Required |
|---|---|---|
| fields | Optional fields to return specific values, example: restrictedIPs. | Optional |
Context Output
There is no context output for this command.
Configuration parameters
server— Server URL (e.g. https://192.168.0.1) (required)creds_keys— Access keycredentials— Usernameunsecure— Trust any certificate (not secure)proxy— Use system proxy settingsisFetch— Fetch incidentsincidentType— Incident typefetch_time— First fetch timestamp (<number> <time unit>, e.g., 12 hours, 7 days)incidentFetchInterval— Incidents Fetch IntervalisFetchAssets— Fetch assets and vulnerabilitiesassetsFetchInterval— Assets fetch interval in minutes.
Commands (33)
-
tenable-sc-create-assetRequires security manager role. Create an asset in Tenable.sc with provided IP addresses.
-
tenable-sc-create-policyCreates a policy. Requires security manager role. This command is prerequisite for creating remediation scan.
-
tenable-sc-create-remediation-scanCreates a remediation scan. Requires security manager role. This command is a prerequisite for creating remediation scan.
-
tenable-sc-create-scanRequires security manager role. Create a scan on Tenable.sc
-
tenable-sc-create-userCreates a new user. This command can be executed with both roles (admin or security manager) based on the role_id you choose.
-
tenable-sc-delete-assetRequires security manager role. Delete the asset with the given ID from Tenable.sc.
-
tenable-sc-delete-scanRequires security manager role. Delete a scan in Tenable.sc.
-
tenable-sc-delete-userDelete a user by given user_id. This command can be executed with both roles (admin or security manager).
-
tenable-sc-get-alertRequires security manager role. Get information about a given alert in Tenable.sc.
-
tenable-sc-get-all-scan-resultsReturns all scan results in Tenable.sc. Requires security manager role.
-
tenable-sc-get-assetRequires security manager role. Get details for a given asset in Tenable.sc.
-
tenable-sc-get-deviceRequires security manager role. Gets the specified device information.
-
tenable-sc-get-organizationRequires administrator role. Command to get a list of organizations' information, depending on the comma-separated list of fields provided.
-
tenable-sc-get-scan-reportRequires security manager role. Get a single report with Tenable.sc scan results. In case of `Importstatus = Error` (The results import wasn't finished), the vulnerabilities section will not be added to the results.
-
tenable-sc-get-scan-statusRequires security manager role. Get the status of a specific scan in Tenable.sc.
-
tenable-sc-get-system-informationGet the system information and diagnostics from Tenable.sc. Requires admin role.
-
tenable-sc-get-system-licensingRetrieve licensing information from Tenable.sc. Requires admin role.
-
tenable-sc-get-vulnerabilityRequires security manager role. Get details about a given vulnerability from a given Tenable.sc scan.
-
tenable-sc-launch-scanRequires security manager role. Launch an existing scan from Tenable.sc. Set polling to true to follow the scan and receive results when scan is over.
-
tenable-sc-list-alertsRequires security manager role. List alerts from Tenable.sc.
-
tenable-sc-list-assetsRequires security manager role. Get a list of Tenable.sc assets.
-
tenable-sc-list-credentialsRequires security manager role. Get a list of Tenable.sc credentials.
-
tenable-sc-list-groupsList all groups. Requires security manager role.
-
tenable-sc-list-plugin-familyList plugin families / return information about a plugin family given ID. Requires security manager role.
-
tenable-sc-list-policiesRequires security manager role. Get a list of Tenable.sc scan policies.
-
tenable-sc-list-queryLists the queries. Requires security manager role.
-
tenable-sc-list-report-definitionsRequires security manager role. Get a list of Tenable.sc report definitions.
-
tenable-sc-list-repositoriesRequires security manager role. Get a list of Tenable.sc scan repositories.
-
tenable-sc-list-scansRequires security manager role. Get a list of Tenable.sc existing scans.
-
tenable-sc-list-usersList users in Tenable.sc. Results may vary based on the role type (admin or security manager).
-
tenable-sc-list-zonesRequires admin role. Get a list of Tenable.sc scan zones.
-
tenable-sc-update-assetRequires security manager role. Update an asset.
-
tenable-sc-update-userUpdate user details of the given user_id.
import json import time import pytest from Tenable_sc import ( Client, create_asset_command, create_get_device_request_params_and_path, create_policy_request_body, create_scan_command, create_user_request_body, delete_asset_command, delete_scan_command, delete_user_command, fetch_assets_page, fetch_vulnerabilities_page, generate_snapshot_id, get_alert_command, get_all_scan_results_command, get_asset_command, get_device_command, get_organization_command, get_query, get_scan_report_command, get_scan_status_command, get_system_information_command, get_system_licensing_command, is_assets_fetch_in_progress, is_vulns_fetch_in_progress, launch_scan, list_alerts_command, list_assets_command, list_credentials_command, list_groups_command, list_plugin_family_command, list_policies_command, list_queries, list_query_command, list_report_definitions_command, list_repositories_command, list_scans_command, list_users_command, list_zones_command, parse_vulnerabilities, skip_fetch_assets, update_asset_command, validate_create_scan_inputs, validate_user_body_params, ) client_mocker = Client( verify_ssl=False, proxy=True, access_key="access_key", secret_key="secret_key", url="www.tenable_sc_url_mock.com" ) def load_json(path): with open(path, encoding="utf-8") as f: return json.load(f) @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_update_asset_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, and expected hr. - Case 1: args with asset_id, name, and description to update. When: - Running update_asset_command. Then: - Ensure that the response was parsed correctly and right HR is returned. - Case 1: Should include the right asset_id in the hr. """ test_data = load_json("./test_data/test_update_asset_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = update_asset_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3"]) def test_list_zones_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: response mock, expected hr and ec outputs. - Case 1: A response with empty response field - Case 2: A response with 2 zones, where the zones also have the same scanners. - Case 3: A response with 3 zones, where the zones also have different scanners. When: - Running list_zones_command. Then: - Ensure that the response was parsed correctly and right HR and EC outputs are returned. - Case 1: Should create only scan zones table in HR, and include one zone with ID = 0 and name = all zones in EC. - Case 2: Should create both tables in HR, the second table should have only one entry. Should include two zones in the EC and each zone should have a scanner. - Case 3: Should create both tables in HR, the second table should have two entries. Should include two zones in the EC and each zone should have a scanner. """ test_data = load_json("./test_data/test_list_zones_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = list_zones_command(client_mocker, {}) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3"]) def test_list_groups_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr and ec outputs. - Case 1: Args with limit=1 and show_users=True, and a response with 2 groups where each have users. - Case 2: Args without limit (default is 50) and show_users=False, and a response with 2 groups where each have users. - Case 3: Args without limit, and show_users=True, and a response with 2 groups where each have users. When: - Running list_groups_command. Then: - Ensure that the response was parsed correctly and right HR and EC outputs are returned. - Case 1: Should return information about only 1 group in the HR and EC and include the users table. - Case 2: Should return information about both groups in the HR and EC, and exclude the users table and users field from EC. - Case 3: Should return information about both groups in the HR where each group has its own users table. And EC where each group include a user field. """ test_data = load_json("./test_data/test_list_groups_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = list_groups_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3", "test_case_4"]) def test_list_plugin_family_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr and ec outputs. - Case 1: Args with limit=1 and is_active=true, and a response with 2 plugin families. - Case 2: Empty args, and a response with 2 plugins. - Case 3: Args with plugin_id, and a response with the plugin family information where the plugin type is malware. - Case 4: Args with plugin_id, and a response with the plugin family information where the plugin type is active. When: - Running list_plugin_family_command. Then: - Ensure that the response was parsed correctly and right HR and EC outputs are returned. - Case 1: Should return a table with is_active column in the HR, and EC that include only the first plugin family. - Case 2: Should return a table with name column in the HR, and EC that include both plugin families. - Case 3: Should return a table with only id and name columns, and EC with plugin type in it. - Case 4: Should return a table with all columns (id, name, and is_active), and EC with plugin type in it. """ test_data = load_json("./test_data/test_list_plugin_family_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = list_plugin_family_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3", "test_case_4", "test_case_5", "test_case_6"]) def test_validate_user_body_params(test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, command_type flag and the expected error message. - Case 1: Args with group_id which is not a number, and a command_type flag that point to create. - Case 2: Args with invalid time_zone, and a command_type flag that point to create. - Case 3: Args with only password, and a command_type flag that point to update. - Case 4: Args with password string of length = 1, and a command_type flag that point to create. - Case 5: Args with invalid email address, and a command_type flag that point to create. - Case 6: Args with email_notice but no email field, and a command_type flag that point to create. When: - Running validate_user_body_params. Then: - Ensure that the right error was thrown. - Case 1: Should throw an error for none-number argument. - Case 2: Should throw an error for invalid time_zone. - Case 3: Should throw an error for missing current_password field. - Case 4: Should throw an error for too short password string. - Case 5: Should throw an error for invalid email address. - Case 6: Should throw an error for missing email field. """ test_data = load_json("./test_data/test_validate_user_body_params.json").get(test_case, {}) args = test_data.get("args") command_type = test_data.get("command_type") with pytest.raises(Exception) as e: validate_user_body_params(args, command_type) assert test_data.get("expected_error_msg") in str(e.value) @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_create_user_request_body(test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, and expected body. - Case 1: Args with first_name, role_id, managed_users_groups, and time_zone fields. When: - Running create_user_request_body. Then: - Ensure that the body was created correctly. - Case 1: Should create a body with all the given fields, first_name should be at the root, role_id should be translated to the correspondence number, managed_users_groups should be a list of ID dicts, and time_zone should be a list of one dict with name, value, and tags. """ test_data = load_json("./test_data/test_create_user_request_body.json").get(test_case, {}) args = test_data.get("args") body = create_user_request_body(args) assert test_data.get("expected_body") == body @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3"]) def test_validate_create_scan_inputs(test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, and the expected error message. - Case 1: Args with invalid time_zone. - Case 2: Empty args. - Case 3: args with ip_list and schedule = 'schedule'. When: - Running validate_create_scan_inputs. Then: - Ensure that the right error was thrown. - Case 1: Should throw an error for invalid time_zone. - Case 2: Should throw an error for missing ip_list and assets. - Case 3: Should throw an error for missing dependent scan ID. """ test_data = load_json("./test_data/test_validate_create_scan_inputs.json").get(test_case, {}) args = test_data.get("args") with pytest.raises(Exception) as e: validate_create_scan_inputs(args) assert test_data.get("expected_error_msg") in str(e.value) @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3", "test_case_4"]) def test_validate_credentials(test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, and the expected error message. - Case 1: Only access key filled. - Case 2: Only username filled. - Case 3: No argument filled. - Case 4: args with access key and username filled. When: - Running Client creator. Then: - Ensure that an error for missing credentials pair is thrown. """ test_data = load_json("./test_data/test_validate_credentials.json").get(test_case, {}) access_key = test_data.get("access_key") secret_key = test_data.get("secret_key") user_name = test_data.get("user_name") password = test_data.get("password") with pytest.raises(Exception) as e: Client(proxy=True, access_key=access_key, secret_key=secret_key, user_name=user_name, password=password) assert "Please provide either user_name and password or secret_key and access_key" in str(e.value) @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_create_policy_request_body(test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, and expected body. - Case 1: Args with policy_description, policy_template_id, family_id,and plugins_id. When: - Running create_policy_request_body. Then: - Ensure that the body was created correctly. - Case 1: Should create a body with all the given fields, and include default none-included (preference and context). """ test_data = load_json("./test_data/test_create_policy_request_body.json").get(test_case, {}) args = test_data.get("args") body = create_policy_request_body(args) assert test_data.get("expected_body") == body @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3"]) def test_create_scan_body(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, mock_response (for some test cases) and expected body. - Case 1: Args with scan_type, scan_name saved under "name", repository_id, asset_ids set to "AllManageable", schedule set to "rollover", and dependent_id. Also, a mock_response to get asses with two manageable assets. - Case 2: Args with policy_id, scan_name saved under "scan_name", credentials with few credentials, max_scan_time, schedule set to "ical", time_zone, start_time, repeat_rule_freq, repeat_rule_interval, and repeat_rule_by_day. - Case 3: Args with plugins_id, zone_id and a comma separated list of report_ids. When: - Running create_scan_body. Then: - Ensure that the body was created correctly. - Case 1: Should set type to be scan_type value, configure scan_name, add repository_id under repository dict, send a get_assets request and include the two assets from the response in the request body, set max_scan_time to 3600, and include dependent_id under schedule. - Case 2: Should set type to be policy, configure scan_name, create a list of credentials id dicts, calculate max_scan_time, and include time_zone, start_time, repeat_rule_freq, repeat_rule_interval, and repeat_rule_by_day under schedule. - Case 3: Should set type to be plugin, create a zone dict, a list of report ids dicts and set max_scan_time to 3600. """ test_data = load_json("./test_data/test_create_scan_body.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response", {})) body = client_mocker.create_scan_body(args) assert test_data.get("expected_body") == body @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3"]) def test_create_get_device_request_params_and_path(test_case): """ Given: - test case that point to the relevant test case in the json test data which include: function args (uuid, ip, dns_name, repo), expected path and params, and expected body. - Case 1: repo, uuid and dns_name. - Case 2: ip. - Case 3: ip and dns_name. When: - Running create_get_device_request_params_and_path. Then: - Ensure that the body was created correctly. - Case 1: Path should include repo, params should include uuid and ignore dns_name. - Case 2: Path should be deviceInfo, params should include ip. - Case 3: Path should be deviceInfo, params should include ip and dns_name. """ test_data = load_json("./test_data/test_create_get_device_request_params_and_path.json").get(test_case, {}) uuid = test_data.get("uuid") ip = test_data.get("ip") dns_name = test_data.get("dns_name") repo = test_data.get("repo") path, params = create_get_device_request_params_and_path(uuid, ip, dns_name, repo) assert test_data.get("expected_path") == path assert test_data.get("expected_params") == params @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2"]) def test_create_get_vulnerability_request_body(test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, query, scan_results_id, calling_command, and expected body. - Case 1: Args with scan_results_id, vulnerability_id, sort_field, and sort_direction. Empty query, scan_results_id, and calling_command. - Case 2: Args with scan_results_id, vulnerability_id, query_id, source_type and limit higher than 200. Empty query, scan_results_id, and calling_command. When: - Running create_get_vulnerability_request_body. Then: - Ensure that the body was created correctly. - Case 1: Should complete all the none-given fields, count source_type as individual, and add related fields. - Case 2: Should lower limit to 200, ignore scan_results_id and vulnerability_id. """ test_data = load_json("./test_data/test_create_get_vulnerability_request_body.json").get(test_case, {}) args = test_data.get("args", {}) body = client_mocker.create_get_vulnerability_request_body(args) assert test_data.get("expected_body") == body @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_get_query(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: query_id, response mock, expected hr, and expected_ec. - Case 1: response mock that misses filters section. When: - Running get_query. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should exclude the filters section from the HR but not from the EC. """ test_data = load_json("./test_data/test_get_query.json").get(test_case, {}) query_id = test_data.get("query_id") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) _, hr, query = get_query(client_mocker, query_id) assert test_data.get("expected_hr") == hr assert test_data.get("expected_ec") == query @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_list_queries(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: response mock, expected hr, and expected_ec. - Case 1: response mock with 2 manageable and 2 usable queries, one of the queries appears in both lists, some queries with filters and some don't. When: - Running list_queries. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should Include the filters section in the HR, should have "True" in both manageable and usable columns for the mutual query and fill False in the none-mutual queries. """ test_data = load_json("./test_data/test_list_queries.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) _, hr, query = list_queries(client_mocker, "") assert test_data.get("expected_hr") == hr assert test_data.get("expected_ec") == query @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2"]) def test_list_query_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, function to mock, response mock, expected hr, and expected_ec. - Case 1: empty args, mocked_function = list_queries, response mock with 2 manageable and 2 usable queries, one of the queries appears in both lists, some queries with filters and some don't. - Case 2: args with query_id, mocked_function = get_query, response mock that misses filters section. When: - Running list_query_command. Then: - Ensure that the right function is mocked and the response was parsed correctly and right HR and EC is returned. - Case 1: Should call list_queries, Include the filters section in the HR, should have "True" in both manageable and usable columns for the mutual query and fill False in the none-mutual queries. - Case 2: Should call get_query, exclude the filters section from the HR and EC. """ test_data = load_json("./test_data/test_list_query_command.json").get(test_case, {}) mocked_function = test_data.get("mocked_function") args = test_data.get("args") mocker.patch(f"Tenable_sc.Client.{mocked_function}", return_value=test_data.get("mock_response")) command_results = list_query_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3"]) def test_list_users_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with id and email pointing to an email different from the email in the response, response of a get user request. - Case 2: args with email and username, response of a list users request with 3 users. - Case 2: Empty args, response of a list users request with 3 users. When: - Running list_users_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should include the retrieved user in the response. - Case 2: Should filter out the user with un matched username and ignore the email argument. - Case 2: Should retrieve HR and EC including all 3 users. """ test_data = load_json("./test_data/test_list_users_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = list_users_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2", "test_case_3", "test_case_4", "test_case_5"]) def test_launch_scan_errors(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, command_type flag and the expected error message. - Case 1: Args with diagnostic_target but no diagnostic_password. - Case 2: Args with diagnostic_password but no diagnostic_target. - Case 3: Args with both diagnostic_password and diagnostic_target, and an empty mock response. - Case 4: Args without both diagnostic_password and diagnostic_target, and an empty mock response with empty response section. - Case 5: Args with both diagnostic_password and diagnostic_target, and a response with missing scanResult from response section. When: - Running launch_scan. Then: - Ensure that the right error was thrown. - Case 1: Should throw an error for none-number argument. - Case 2: Should throw an error for invalid time_zone. - Case 3: Should throw aCould not retrieve the scans error. - Case 4: Should throw aCould not retrieve the scans error. - Case 5: Should throw aCould not retrieve the scans error. """ test_data = load_json("./test_data/test_launch_scan_errors.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response", {})) with pytest.raises(Exception) as e: launch_scan(client_mocker, args) assert test_data.get("expected_error_msg") in str(e.value) @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_list_report_definitions_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with manageable = true, and mock response to response with 2 report definitions with the same name, where one report is later than the second. When: - Running list_report_definitions_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return only one report definition, the one that occurred later. """ test_data = load_json("./test_data/test_list_report_definitions_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = list_report_definitions_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs def test_delete_asset_command(mocker): """ Given: - Args with asset_id to delete. When: - Running delete_asset_command. Then: - Ensure that the response was parsed correctly and right HR is returned. """ args = {"asset_id": "test_id"} mocker.patch.object(client_mocker, "send_request", return_value={"code": 200}) command_results = delete_asset_command(client_mocker, args) assert command_results.readable_output == "Asset test_id was deleted successfully." def test_delete_scan_command(mocker): """ Given: - Args with scan_id to delete. When: - Running delete_scan_command. Then: - Ensure that the response was parsed correctly and right HR is returned. """ args = {"scan_id": "test_id"} mocker.patch.object(client_mocker, "send_request", return_value={"code": 200}) command_results = delete_scan_command(client_mocker, args) assert command_results.readable_output == "Scan test_id was deleted successfully." def test_delete_user_command(mocker): """ Given: - Args with user_id to delete. When: - Running delete_user_command. Then: - Ensure that the response was parsed correctly and right HR is returned. """ args = {"user_id": "test_id"} mocker.patch.object(client_mocker, "send_request", return_value={"code": 200}) command_results = delete_user_command(client_mocker, args) assert command_results.readable_output == "User test_id was deleted successfully." @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2"]) def test_list_scans_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with manageable = true, and mock response to response with 2 usable and 2 manageable scans. - Case 2: Empty args, and mock response to response with 2 usable and 2 manageable scans. When: - Running test_list_scans_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return only the manageable scans. - Case 2: Should return only the usable scans. """ test_data = load_json("./test_data/test_list_scans_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = list_scans_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2"]) def test_get_scan_status_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with manageable = true, and mock response to response with 2 usable and 2 manageable scans. - Case 2: Empty args, and mock response to response with 2 usable and 2 manageable scans. When: - Running get_scan_status_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return only the manageable scans. - Case 2: Should return only the usable scans. """ test_data = load_json("./test_data/test_get_scan_status_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = get_scan_status_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_get_device_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with ip, repo_id, dns_name, and uuid. When: - Running get_device_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should Include 2 Commands results objects, 1 for endpoint and 1 for device. """ test_data = load_json("./test_data/test_get_device_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = get_device_command(client_mocker, args) for i in range(2): assert test_data.get("expected_hr")[i] == command_results[i].readable_output assert test_data.get("expected_ec")[i] == command_results[i].outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2"]) def test_list_policies_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with manageable = true, and mock response to response with 2 usable and 2 manageable policies. - Case 2: Empty args, and mock response to response with 2 usable and 2 manageable policies. When: - Running list_policies_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return only the manageable policies. - Case 2: Should return only the usable policies. """ test_data = load_json("./test_data/test_list_policies_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = list_policies_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2"]) def test_list_credentials_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with manageable = true, and mock response to response with 1 usable and 1 manageable credentials. - Case 2: Empty args, and mock response to response with 1 usable and 1 manageable credentials. When: - Running list_credentials_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return only the manageable credentials. - Case 2: Should return only the usable credentials. """ test_data = load_json("./test_data/test_list_credentials_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = list_credentials_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_create_asset_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with name, description, and ip_list and a successful response. When: - Running create_asset_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return the created asset info. """ test_data = load_json("./test_data/test_create_asset_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = create_asset_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_create_scan_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with multiple scan args and a successful response. When: - Running create_scan_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return the created scan info. """ test_data = load_json("./test_data/test_create_scan_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = create_scan_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_get_scan_report_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with scan results id and a mock response. When: - Running get_scan_report_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return the parsed HR and EC. """ test_data = load_json("./test_data/test_get_scan_report_command.json").get(test_case, {}) args = test_data.get("args") mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = get_scan_report_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_get_system_information_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: response mock, and expected hr. - Case 1: A mock response. When: - Running get_system_information_command. Then: - Ensure that the response was parsed correctly and right HR is returned. - Case 1: Should return the parsed hr. """ test_data = load_json("./test_data/test_get_system_information_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = get_system_information_command(client_mocker, {}) assert test_data.get("expected_hr") == command_results.readable_output @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_get_system_licensing_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: response mock, and expected hr. - Case 1: A mock response. When: - Running get_system_licensing_command. Then: - Ensure that the response was parsed correctly and right HR and ec are returned. - Case 1: Should return the parsed hr and ec. """ test_data = load_json("./test_data/test_get_system_licensing_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = get_system_licensing_command(client_mocker, {}) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_get_all_scan_results_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with limit=1, and a mock response with 2 results. When: - Running get_all_scan_results_command. Then: - Ensure that the response was parsed correctly and right HR and ec are returned. - Case 1: Should return only the first scan result. """ test_data = load_json("./test_data/test_get_all_scan_results_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) args = test_data.get("args") command_results = get_all_scan_results_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2"]) def test_list_alerts_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with manageable = true, and mock response to response with 1 usable and 1 manageable alerts. - Case 2: Empty args, and mock response to response with 1 usable and 1 manageable alerts. When: - Running list_alerts_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return only the manageable alerts. - Case 2: Should return only the usable alerts. """ test_data = load_json("./test_data/test_list_alerts_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) args = test_data.get("args") command_results = list_alerts_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_list_repositories_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: response mock, expected hr, and expected_ec. - Case 1: Mock response with 1 repo. When: - Running list_repositories_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. """ test_data = load_json("./test_data/test_list_repositories_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) command_results = list_repositories_command(client_mocker, {}) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1", "test_case_2"]) def test_list_assets_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with manageable = true, and mock response to response with 1 usable and 1 manageable assets. - Case 2: Empty args, and mock response to response with 1 usable and 1 manageable assets. When: - Running list_assets_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return only the manageable assets. - Case 2: Should return only the usable assets. """ test_data = load_json("./test_data/test_list_assets_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) args = test_data.get("args") command_results = list_assets_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_get_asset_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with asset id, and a mock response. When: - Running get_asset_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should parse all the ips and return both HR and EC. """ test_data = load_json("./test_data/test_get_asset_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) args = test_data.get("args") command_results = get_asset_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_get_alert_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with alert id, and a mock response. When: - Running get_alert_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return all tables with parsed response. """ test_data = load_json("./test_data/test_get_alert_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) args = test_data.get("args") command_results = get_alert_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs @pytest.mark.parametrize("test_case", ["test_case_1"]) def test_get_organization_command(mocker, test_case): """ Given: - test case that point to the relevant test case in the json test data which include: args, response mock, expected hr, and expected_ec. - Case 1: args with fields vulnScoreMedium, repositories, restrictedIPs and a mock response. When: - Running get_organization_command. Then: - Ensure that the response was parsed correctly and right HR and EC is returned. - Case 1: Should return all tables with parsed response. """ test_data = load_json("./test_data/test_get_organization_command.json").get(test_case, {}) mocker.patch.object(client_mocker, "send_request", return_value=test_data.get("mock_response")) args = test_data.get("args") command_results = get_organization_command(client_mocker, args) assert test_data.get("expected_hr") == command_results.readable_output assert test_data.get("expected_ec") == command_results.outputs """ FETCH ASSETS TESTS """ def test_generate_snapshot_id(): """ Given: - Nothing. When: - Calling generate_snapshot_id. Then: - Ensure a string of digits is returned representing milliseconds timestamp. """ snapshot_id = generate_snapshot_id() assert isinstance(snapshot_id, str) assert snapshot_id.isdigit() assert len(snapshot_id) >= 13 # millisecond timestamp def test_is_assets_fetch_in_progress_true(): """ Given: - A last_run dict with current_offset set. When: - Calling is_assets_fetch_in_progress. Then: - Should return True. """ last_run = {"current_offset": 500, "snapshot_id": "123456"} assert is_assets_fetch_in_progress(last_run) is True def test_is_assets_fetch_in_progress_false(): """ Given: - A last_run dict without current_offset. When: - Calling is_assets_fetch_in_progress. Then: - Should return False. """ last_run = {"assets_last_fetch": 1709500000.0} assert is_assets_fetch_in_progress(last_run) is False def test_skip_fetch_assets_no_previous_fetch(): """ Given: - A last_run dict with no assets_last_fetch timestamp. When: - Calling skip_fetch_assets. Then: - Should return False (don't skip, this is the first fetch). """ last_run = {} assert skip_fetch_assets(last_run) is False def test_skip_fetch_assets_too_soon(): """ Given: - A last_run dict with assets_last_fetch set to 10 minutes ago. When: - Calling skip_fetch_assets. Then: - Should return True (skip, not enough time has passed). """ last_run = {"assets_last_fetch": time.time() - (10 * 60)} # 10 minutes ago assert skip_fetch_assets(last_run) is True def test_skip_fetch_assets_enough_time(): """ Given: - A last_run dict with assets_last_fetch set to 2 hours ago. When: - Calling skip_fetch_assets. Then: - Should return False (don't skip, enough time has passed). """ last_run = {"assets_last_fetch": time.time() - (120 * 60)} # 2 hours ago assert skip_fetch_assets(last_run) is False def test_skip_fetch_assets_in_progress(): """ Given: - A last_run dict with assets_last_fetch set to 10 minutes ago but fetch is in progress. When: - Calling skip_fetch_assets. Then: - Should return False (don't skip, there's an ongoing fetch). """ last_run = { "assets_last_fetch": time.time() - (10 * 60), "current_offset": 500, } assert skip_fetch_assets(last_run) is False def test_fetch_assets_page_first_page(mocker): """ Given: - A mock response with 2 results out of 3 total (first page). When: - Calling fetch_assets_page with offset 0. Then: - Should return 2 assets. - Should set current_offset to 2 in last_run (more pages to fetch). - Should set nextTrigger to "30". """ test_data = load_json("./test_data/test_search_hosts.json") mocker.patch.object(client_mocker, "send_request", return_value=test_data["first_page"]) last_run = {"current_offset": 0, "total_assets_fetched": 0, "snapshot_id": "123456"} assets = fetch_assets_page(client_mocker, last_run) assert len(assets) == 2 assert last_run["current_offset"] == 2 assert last_run["total_assets_fetched"] == 2 assert last_run["nextTrigger"] == "30" assert assets[0]["name"] == "TestHost1" assert assets[1]["name"] == "TestHost2" def test_fetch_assets_page_last_page(mocker): """ Given: - A mock response with 1 result out of 3 total (last page, offset=2). When: - Calling fetch_assets_page with offset 2. Then: - Should return 1 asset. - Should clear current_offset from last_run (no more pages). - Should clear total_records from last_run. """ test_data = load_json("./test_data/test_search_hosts.json") mocker.patch.object(client_mocker, "send_request", return_value=test_data["last_page"]) last_run = {"current_offset": 2, "total_assets_fetched": 2, "snapshot_id": "123456"} assets = fetch_assets_page(client_mocker, last_run) assert len(assets) == 1 assert "current_offset" not in last_run assert "total_records" not in last_run assert last_run["total_assets_fetched"] == 3 assert assets[0]["name"] == "TestHost3" def test_fetch_assets_page_empty_response(mocker): """ Given: - A mock response with 0 results. When: - Calling fetch_assets_page. Then: - Should return empty list. - Should clear pagination state from last_run. """ test_data = load_json("./test_data/test_search_hosts.json") mocker.patch.object(client_mocker, "send_request", return_value=test_data["empty_response"]) last_run = {"current_offset": 0, "total_assets_fetched": 0, "snapshot_id": "123456"} assets = fetch_assets_page(client_mocker, last_run) assert len(assets) == 0 assert "current_offset" not in last_run assert "total_records" not in last_run def test_fetch_assets_page_no_response(mocker): """ Given: - A None response from the API. When: - Calling fetch_assets_page. Then: - Should return empty list. - Should clear pagination state from last_run. """ mocker.patch.object(client_mocker, "send_request", return_value=None) last_run = {"current_offset": 0, "total_assets_fetched": 0, "snapshot_id": "123456"} assets = fetch_assets_page(client_mocker, last_run) assert len(assets) == 0 assert "current_offset" not in last_run def test_search_hosts_client_method(mocker): """ Given: - A client with search_hosts method. When: - Calling search_hosts with fields, offsets, and no filters. Then: - Should call send_request with correct path, method, params, and body. """ test_data = load_json("./test_data/test_search_hosts.json") mock_send = mocker.patch.object(client_mocker, "send_request", return_value=test_data["first_page"]) result = client_mocker.search_hosts( fields="id,uuid,name", start_offset=0, end_offset=500, ) mock_send.assert_called_once_with( path="hosts/search", method="POST", body={}, params={ "fields": "id,uuid,name", "startOffset": "0", "endOffset": "500", "pagination": "true", }, ) assert result == test_data["first_page"] """ VULNERABILITY FETCH TESTS """ def test_is_vulns_fetch_in_progress_true(): """ Given: - A last_run dict with vuln_current_offset set. When: - Calling is_vulns_fetch_in_progress. Then: - Should return True (vulnerability fetch is in progress). """ last_run = {"vuln_current_offset": 500} assert is_vulns_fetch_in_progress(last_run) is True def test_is_vulns_fetch_in_progress_false(): """ Given: - A last_run dict without vuln_current_offset. When: - Calling is_vulns_fetch_in_progress. Then: - Should return False (no vulnerability fetch in progress). """ last_run = {"assets_last_fetch": time.time()} assert is_vulns_fetch_in_progress(last_run) is False def test_skip_fetch_assets_vulns_in_progress(): """ Given: - A last_run dict with assets_last_fetch set to 10 minutes ago and vulns fetch in progress. When: - Calling skip_fetch_assets. Then: - Should return False (don't skip, there's an ongoing vulnerability fetch). """ last_run = { "assets_last_fetch": time.time() - (10 * 60), "vuln_current_offset": 500, } assert skip_fetch_assets(last_run) is False def test_fetch_vulnerabilities_page_first_page(mocker): """ Given: - A mock response with 2 vulnerability results out of 3 total (first page). When: - Calling fetch_vulnerabilities_page with offset 0. Then: - Should return 2 vulnerabilities. - Should set vuln_current_offset to 2 in last_run (more pages to fetch). - Should set nextTrigger to "30". """ mock_response = { "response": { "totalRecords": "3", "returnedRecords": 2, "results": [ { "pluginID": "10001", "name": "Test Vuln 1", "severity": {"id": "3", "name": "High"}, "family": {"name": "General"}, "lastSeen": "1709654400", "firstSeen": "1709568000", "pluginDescription": "Test description 1", }, { "pluginID": "10002", "name": "Test Vuln 2", "severity": {"id": "2", "name": "Medium"}, "family": {"name": "Web Servers"}, "lastSeen": "1709654400", "firstSeen": "1709568000", "pluginDescription": "Test description 2", }, ], } } mocker.patch.object(client_mocker, "send_request", return_value=mock_response) last_run = {"vuln_current_offset": 0, "total_vulns_fetched": 0} vulns = fetch_vulnerabilities_page(client_mocker, last_run) assert len(vulns) == 2 assert last_run["vuln_current_offset"] == 2 assert last_run["total_vulns_fetched"] == 2 assert last_run["nextTrigger"] == "30" assert vulns[0]["pluginID"] == "10001" assert vulns[1]["pluginID"] == "10002" def test_fetch_vulnerabilities_page_last_page(mocker): """ Given: - A mock response with 1 vulnerability result out of 3 total (last page, offset=2). When: - Calling fetch_vulnerabilities_page with offset 2. Then: - Should return 1 vulnerability. - Should clear vuln_current_offset from last_run (no more pages). """ mock_response = { "response": { "totalRecords": "3", "returnedRecords": 1, "results": [ { "pluginID": "10003", "name": "Test Vuln 3", "severity": {"id": "1", "name": "Low"}, "family": {"name": "DNS"}, "lastSeen": "1709654400", "firstSeen": "1709568000", "pluginDescription": "Test description 3", }, ], } } mocker.patch.object(client_mocker, "send_request", return_value=mock_response) last_run = {"vuln_current_offset": 2, "total_vulns_fetched": 2} vulns = fetch_vulnerabilities_page(client_mocker, last_run) assert len(vulns) == 1 assert "vuln_current_offset" not in last_run assert last_run["total_vulns_fetched"] == 3 assert vulns[0]["pluginID"] == "10003" def test_fetch_vulnerabilities_page_empty_response(mocker): """ Given: - A mock response with 0 vulnerability results. When: - Calling fetch_vulnerabilities_page. Then: - Should return empty list. - Should clear vuln pagination state from last_run. """ mock_response = { "response": { "totalRecords": "0", "returnedRecords": 0, "results": [], } } mocker.patch.object(client_mocker, "send_request", return_value=mock_response) last_run = {"vuln_current_offset": 0, "total_vulns_fetched": 0} vulns = fetch_vulnerabilities_page(client_mocker, last_run) assert len(vulns) == 0 assert "vuln_current_offset" not in last_run def test_fetch_vulnerabilities_page_no_response(mocker): """ Given: - A None response from the API. When: - Calling fetch_vulnerabilities_page. Then: - Should return empty list. - Should clear vuln pagination state from last_run. """ mocker.patch.object(client_mocker, "send_request", return_value=None) last_run = {"vuln_current_offset": 0, "total_vulns_fetched": 0} vulns = fetch_vulnerabilities_page(client_mocker, last_run) assert len(vulns) == 0 assert "vuln_current_offset" not in last_run assert "total_vulns_fetched" not in last_run def test_parse_vulnerabilities_normal(): """ Given: - A list of vulnerability records with lastSeen and firstSeen fields. When: - Calling parse_vulnerabilities. Then: - Should set isTruncated to False for normal-sized entries. """ vulns = [ { "pluginID": "10001", "name": "Test Vuln", "lastSeen": "1709654400", "firstSeen": "1709568000", "pluginDescription": "Short description", }, { "pluginID": "10002", "name": "Test Vuln 2", "lastSeen": "1709654400", "firstSeen": "1709568000", "pluginDescription": "Another description", }, ] result = parse_vulnerabilities(vulns) assert len(result) == 2 assert result[0]["_time"] == "1709568000" assert result[0]["isTruncated"] is False assert result[1]["_time"] == "1709568000" assert result[1]["isTruncated"] is False def test_parse_vulnerabilities_uses_firstseen_fallback(): """ Given: - A vulnerability record without lastSeen but with firstSeen. When: - Calling parse_vulnerabilities. Then: - Should use firstSeen as the _time field. """ vulns = [ { "pluginID": "10001", "name": "Test Vuln", "firstSeen": "1709568000", "pluginDescription": "Description", }, ] result = parse_vulnerabilities(vulns) assert result[0]["_time"] == "1709568000" def test_fetch_vulnerabilities_analysis_client_method(mocker): """ Given: - A client with fetch_vulnerabilities_analysis method. When: - Calling fetch_vulnerabilities_analysis with start_offset and end_offset. Then: - Should call send_request with correct path, method, and body. """ mock_response = { "response": { "totalRecords": "0", "returnedRecords": 0, "results": [], } } mock_send = mocker.patch.object(client_mocker, "send_request", return_value=mock_response) result = client_mocker.fetch_vulnerabilities_analysis( start_offset=0, end_offset=500, ) mock_send.assert_called_once_with( path="analysis", method="POST", body={ "type": "vuln", "sourceType": "cumulative", "view": "all", "wasVuln": "excludeWas", "startOffset": 0, "endOffset": 500, "sortField": "severity", "sortDir": "DESC", "tool": "vulndetails", "query": { "type": "vuln", "tool": "vulndetails", "filters": [], }, }, ) assert result == mock_response @pytest.mark.parametrize("proxy_param", [True, False]) def test_fetch_assets_passes_proxy_to_send_data_to_xsiam(mocker, proxy_param): """ Given: - The fetch-assets command with assets and vulnerabilities to send to XSIAM, and a configured "proxy" integration parameter. When: - Running main() for the fetch-assets command. Then: - send_data_to_xsiam should be called with add_proxy_to_request matching the configured proxy parameter for both the assets and the vulnerabilities calls (XSUP-71738). """ import demistomock as demisto import Tenable_sc mocker.patch.object( demisto, "params", return_value={ "server": "https://www.tenable_sc_url_mock.com", "unsecure": True, "proxy": proxy_param, "credentials": {"identifier": "_api_key_", "password": "secret_key"}, }, ) mocker.patch.object(demisto, "command", return_value="fetch-assets") mocker.patch.object(demisto, "getAssetsLastRun", return_value={}) mocker.patch.object(demisto, "setAssetsLastRun") mocker.patch.object(demisto, "updateModuleHealth") # Mock the Client (used as a context manager) so no real connection logic runs. mock_client = mocker.MagicMock() mock_client_class = mocker.patch.object(Tenable_sc, "Client") mock_client_class.return_value.__enter__.return_value = mock_client # Avoid running the real fetch logic; return one asset and one vulnerability. mocker.patch.object(Tenable_sc, "run_assets_fetch", return_value=[{"id": "1"}]) mocker.patch.object( Tenable_sc, "run_vulns_fetch", return_value=[{"id": "v1", "lastSeen": "1709568000"}], ) mocker.patch.object(Tenable_sc, "skip_fetch_assets", return_value=False) mocker.patch.object(Tenable_sc, "is_assets_fetch_in_progress", return_value=False) mocker.patch.object(Tenable_sc, "is_vulns_fetch_in_progress", return_value=False) send_data_mock = mocker.patch.object(Tenable_sc, "send_data_to_xsiam") Tenable_sc.main() # One call for assets, one call for vulnerabilities. assert send_data_mock.call_count == 2 for call in send_data_mock.call_args_list: assert call.kwargs["add_proxy_to_request"] is proxy_param # The Client itself should also receive the configured proxy parameter. assert mock_client_class.call_args.kwargs["proxy"] is proxy_param