Web Application Scanning APIs
WAS APIs return data on web apps in your subscription, as well as manage them.
After running:
You can use any of the endpoints currently supported:WAS Endpoints
API Call | Description |
---|---|
count_webapps |
Returns the number of web apps in the subscription that match given kwargs. |
get_webapps |
Returns a list of web apps in the subscription that match given kwargs. |
get_webapp_details |
Returns all attributes of a single web app. |
get_webapps_verbose |
Combines the functionality of get_webapps and get_webapp_details to return a list of web apps with all attributes. Great for SQL data uploads. |
create_webapp |
Creates a new web app in the subscription. |
update_webapp |
Updates a web app in the subscription. |
delete_webapp |
Deletes a web app in the subscription. |
purge_webapp |
Purges scan data for a web app in the subscription. |
get_selenium_script |
Returns the Selenium script associated with a web app |
count_authentication_records |
Returns the number of authentication records in the subscription that match given kwargs. |
get_authentication_records |
Returns a list of authentication records in the subscription that match given kwargs. |
get_authentication_record_details |
Returns all attributes of a single authentication record. |
create_authentication_record |
Creates a new authentication record in the subscription. |
delete_authentication_record |
Deletes an authentication record in the subscription. |
count_findings |
Returns the number of findings in the subscription that match given kwargs. |
get_findings |
Returns a list of findings in the subscription that match given kwargs. |
get_finding_details |
Returns all attributes of a single finding. |
get_findings_verbose |
Combines the functionality of get_findings and get_finding_details to return a list of findings with all attributes. Great for SQL data uploads. |
Count Webapps API
count_webapps
returns the number of web apps in the subscription that match the given kwargs.
Head's Up! This method is useful for quickly getting a count of webapps that match certain criteria. It does NOT return the webapps themselves, or any attributes of the webapps.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
id |
Union[str, int] |
Web app ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
name |
str |
Web app name | ❌ |
name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the name filter | ❌ |
url |
str |
Web app URL | ❌ |
url_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the URL filter | ❌ |
tags_name |
str |
Tag name | ❌ |
tags_name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the tag name filter | ❌ |
tags_id |
Union[str, int] |
Tag ID | ❌ |
tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tag ID filter | ❌ |
createdDate |
str |
Date created | ❌ |
createdDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the created date filter | ❌ |
updatedDate |
str |
Date updated | ❌ |
updatedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the updated date filter | ❌ |
isScheduled |
bool |
If the webapp has a scan scheduled | ❌ |
isScheduled_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScheduled filter | ❌ |
isScanned |
bool |
If the webapp has been scanned | ❌ |
isScanned_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScanned filter | ❌ |
lastScan_status |
Literal["SUBMITTED", "RUNNING", "FINISHED", "TIME_LIMIT_EXCEEDED", "SCAN_NOT_LAUNCHED", "SCANNER_NOT_AVAILABLE", "ERROR", "CANCELLED"] |
Status of the last scan | ❌ |
lastScan_status_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the lastScan_status filter | ❌ |
lastScan_date |
str |
Date of the last scan in UTC date/time format | ❌ |
lastScan_date_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the lastScan_date filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import count_webapps
auth = BasicAuth(<username>, <password>)
# Get the number of webapps that have a lastScan.status of "RUNNING":
webapps = count_webapps(auth, lastScan_status="RUNNING")
>>>5
# Get the number of webapps by searching by multiple tags:
webapps = count_webapps(auth, tags_id="12345,54321", tags_id_operator="IN")
>>>20
# Get the number of webapps where the name contains "prod":
webapps = count_webapps(auth, name="prod", name_operator="CONTAINS")
>>>10
List Webapps API
get_webapps
returns a list of web apps in the subscription that match the given kwargs.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
page_count |
Union[int, 'all'] = 'all' |
Number of pages to return. If 'all', returns all pages | ❌ |
id |
Union[str, int] |
Web app ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
name |
str |
Web app name | ❌ |
name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the name filter | ❌ |
url |
str |
Web app URL | ❌ |
url_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the URL filter | ❌ |
tags_name |
str |
Tag name | ❌ |
tags_name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the tag name filter | ❌ |
tags_id |
Union[str, int] |
Tag ID | ❌ |
tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tag ID filter | ❌ |
createdDate |
str |
Date created | ❌ |
createdDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the created date filter | ❌ |
updatedDate |
str |
Date updated | ❌ |
updatedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the updated date filter | ❌ |
isScheduled |
bool |
If the webapp has a scan scheduled | ❌ |
isScheduled_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScheduled filter | ❌ |
isScanned |
bool |
If the webapp has been scanned | ❌ |
isScanned_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScanned filter | ❌ |
lastScan_status |
Literal["SUBMITTED", "RUNNING", "FINISHED", "TIME_LIMIT_EXCEEDED", "SCAN_NOT_LAUNCHED", "SCANNER_NOT_AVAILABLE", "ERROR", "CANCELLED"] |
Status of the last scan | ❌ |
lastScan_status_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the lastScan_status filter | ❌ |
lastScan_date |
str |
Date of the last scan in UTC date/time format | ❌ |
lastScan_date_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the lastScan_date filter | ❌ |
verbose |
bool |
If True, returns all tags for the webapp | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import get_webapps
auth = BasicAuth(<username>, <password>)
# Get the webapps that have a lastScan.status of "RUNNING". Include tags:
webapps = get_webapps(auth, lastScan_status="RUNNING", verbose=True)
>>>[
WebApp(
id=12345678,
name="My Awesome Site",
url="https://example.com",
...
),
WebApp(
id=98765432,
...
),
...
]
Get Webapp Details API
get_webapp_details
returns all attributes of a single web app.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
webappId |
Union[str, int] |
Web app ID | ✅ |
from qualysdk import BasicAuth
from qualysdk.was import get_webapp_details, get_webapps
# First, get the ID of the webapp you want to get details for:
auth = BasicAuth(<username>, <password>)
webapps = get_webapps(auth, name="My Awesome Site", id=12345678)
webapp_id = webapps[0].id
# Get the details for the webapp:
webapp = get_webapp_details(auth, webappId=webapp_id)
>>>WebApp(
id=12345678,
name="My Awesome Site",
url="https://example.com",
riskScore=100,
owner_firstName="John",
owner_lastName="Doe",
...
)
Get Webapps Verbose API
get_webapps_verbose
combines the functionality of get_webapps
and get_webapp_details
to return a list of web apps with all attributes.
This method uses threading to speed up the process. Number of threads can be set with the thread_count
parameter.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
thread_count |
int |
Number of threads to use for the request | ❌ |
page_count |
Union[int, 'all'] = 'all' |
Number of pages to return. If 'all', returns all pages | ❌ |
id |
Union[str, int] |
Web app ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
name |
str |
Web app name | ❌ |
name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the name filter | ❌ |
url |
str |
Web app URL | ❌ |
url_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the URL filter | ❌ |
tags_name |
str |
Tag name | ❌ |
tags_name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the tag name filter | ❌ |
tags_id |
Union[str, int] |
Tag ID | ❌ |
tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tag ID filter | ❌ |
createdDate |
str |
Date created | ❌ |
createdDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the created date filter | ❌ |
updatedDate |
str |
Date updated | ❌ |
updatedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the updated date filter | ❌ |
isScheduled |
bool |
If the webapp has a scan scheduled | ❌ |
isScheduled_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScheduled filter | ❌ |
isScanned |
bool |
If the webapp has been scanned | ❌ |
isScanned_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScanned filter | ❌ |
lastScan_status |
Literal["SUBMITTED", "RUNNING", "FINISHED", "TIME_LIMIT_EXCEEDED", "SCAN_NOT_LAUNCHED", "SCANNER_NOT_AVAILABLE", "ERROR", "CANCELLED"] |
Status of the last scan | ❌ |
lastScan_status_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the lastScan_status filter | ❌ |
lastScan_date |
str |
Date of the last scan in UTC date/time format | ❌ |
lastScan_date_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the lastScan_date filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import get_webapps_verbose
auth = BasicAuth(<username>, <password>)
# Get all webapps with all attributes:
webapps = get_webapps_verbose(auth)
>>>[
WebApp(
id=12345678,
name="My Awesome Site",
url="https://example.com",
...
),
WebApp(
id=98765432,
...
),
...
]
# Get all webapps with all attributes
# that have "prod" in the name, using 10 threads:
webapps = get_webapps_verbose(
auth,
name="prod",
name_operator="CONTAINS",
thread_count=10
)
>>>[
WebApp(
id=12345678,
name="My Awesome Site (prod)",
url="https://example.com",
...
),
WebApp(
id=98765432,
name="My Other Site (prod)",
...
),
...
]
Create Webapp API
create_webapp
creates a new web app in the subscription.
Head's Up!: More optional attributes will be supported in the future.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
name |
str |
Web app name | ✅ |
url |
str |
Web app URL | ✅ |
authRecord_id |
Union[str, int] |
Auth record ID | ❌ |
uris |
Union[str, list[str]] |
Single URI string or a list of URI strings | ❌ |
tag_ids |
Union[int, list[int]] |
Single tag ID or a list of tag IDs | ❌ |
domains |
Union[str, list[str]] |
Single domain string or a list of domain strings | ❌ |
scannerTag_ids |
Union[int, list[int]] |
Single tag ID or a list of tag IDs associated with scanner appliances to assign | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import create_webapp
auth = BasicAuth(<username>, <password>)
# Create a new webapp with
# minimal attributes:
new_webapp = create_webapp(
auth,
name="My New Site",
url="https://newsite.com"
)
# Create a new webapp with
# URIs, tags, and an auth record:
new_webapp = create_webapp(
auth,
name="My New Site",
url="https://newsite.com",
uris=["https://newsite.com/admin", "https://newsite.com/blog", "https://newsite.com/contact"],
authRecord_id=12345678 # Only one auth record can be specified in the API call
tag_ids=[12345, 54321],
...
)
>>>WebApp(
id=12345678,
name="My New Site",
url="https://newsite.com",
uris=["https://newsite.com/admin", "https://newsite.com/blog", "https://newsite.com/contact"],
tags=[WASTag(id=12345, name='Prod'), WASTag(id=54321, name='News')],
...
)
# Create a new webapp with
# 2 default scanner tags:
new_webapp = create_webapp(
auth,
name="My New Site",
url="https://newsite.com",
scannerTag_ids=[12345, 54321],
...
)
Update Webapp API
update_webapp
updates a web app in the subscription.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
webappId |
Union[str, int] |
Web app ID | ✅ |
name |
str |
Web app name | ❌ |
url |
str |
Web app URL | ❌ |
attributes |
dict["add": {key: value}, "remove": list[str]] |
Attributes to add or remove. | ❌ |
defaultProfile_id |
int |
Default profile ID | ❌ |
urlExcludelist |
list[str] |
List of URLs to exclude | ❌ |
urlAllowlist |
list[str] |
List of URLs to allow | ❌ |
postDataExcludelist |
list[str] |
List of post data paths to exclude | ❌ |
useSitemap |
bool |
If True, use the sitemap | ❌ |
headers |
list["Header_name: Header_value"] |
List of headers | ❌ |
authRecord_id |
dict["add": int, "remove": int] |
Auth record ID to add or remove | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import update_webapp
auth = BasicAuth(<username>, <password>)
webapp_id = 12345678
# Update the name of a webapp:
updated_webapp = update_webapp(
auth,
webappId=webapp_id,
name="My Updated Site"
)
# Remove current auth record and add a new one:
updated_webapp = update_webapp(
auth,
webappId=webapp_id,
authRecord_id={"add": 98765432, "remove": 12345678}
)
# Add new headers:
updated_webapp = update_webapp(
auth,
webappId=webapp_id,
headers=["X-Frame-Options: DENY", "Content-Security-Policy: default-src 'self'"]
)
# Add/remove custom attributes:
updated_webapp = update_webapp(
auth,
webappId=webapp_id,
attributes={"add": {"custom_attribute": "custom_value"}, "remove": ["old_custom_attribute1", "old_custom_attribute2"]}
)
# add URLs to the exclude list:
updated_webapp = update_webapp(
auth,
webappId=webapp_id,
urlExcludelist=["https://example.com/admin", "https://example.com/blog"]
)
Delete Webapp API
delete_webapp
deletes a web app in the subscription.
Returns a list of webapp IDs that were deleted as a dictionary: {"id": <id>}
Head's Up!: Using this API may only remove the WAS-specific asset in the subscription. It may still be active in other Qualys modules, such as Global AssetView's web application view.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
removeFromSubscription |
bool=True |
If True , removes the webapp from the subscription. If False , removes webapp from WAS only |
❌ |
id |
Union[str, int] |
Web app ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
name |
str |
Web app name | ❌ |
name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the name filter | ❌ |
url |
str |
Web app URL | ❌ |
url_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the URL filter | ❌ |
tags_name |
str |
Tag name | ❌ |
tags_name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the tag name filter | ❌ |
tags_id |
Union[str, int] |
Tag ID | ❌ |
tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tag ID filter | ❌ |
createdDate |
str |
Date created | ❌ |
createdDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the created date filter | ❌ |
updatedDate |
str |
Date updated | ❌ |
updatedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the updated date filter | ❌ |
isScheduled |
bool |
If the webapp has a scan scheduled | ❌ |
isScheduled_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScheduled filter | ❌ |
isScanned |
bool |
If the webapp has been scanned | ❌ |
isScanned_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScanned filter | ❌ |
lastScan_status |
Literal["SUBMITTED", "RUNNING", "FINISHED", "TIME_LIMIT_EXCEEDED", "SCAN_NOT_LAUNCHED", "SCANNER_NOT_AVAILABLE", "ERROR", "CANCELLED"] |
Status of the last scan | ❌ |
lastScan_status_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the lastScan_status filter | ❌ |
lastScan_date |
str |
Date of the last scan in UTC date/time format | ❌ |
lastScan_date_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the lastScan_date filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import delete_webapp
auth = BasicAuth(<username>, <password>)
# Delete a webapp by ID:
delete_webapp(auth, id=12345678)
# Delete multiple webapps by ID:
delete_webapp(auth, id="12345678,98765432", id_operator="IN")
# Delete all webapps that have the "deprecated" tag:
delete_webapp(auth, tags_name="deprecated", tags_name_operator="EQUALS")
>>>[{"id": 12345678}, {"id": 98765432}, ...]
Purge Webapp Scan Data API
purge_webapp
purges scan data for a web app in the subscription.
Returns a list of webapp IDs that were purged as a dictionary: {"id": <id>}
Head's Up!: Using this API may de-activate the WAS-specific asset in the subscription. It may still be active in other Qualys modules.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
id |
Union[str, int] |
Web app ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
name |
str |
Web app name | ❌ |
name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the name filter | ❌ |
url |
str |
Web app URL | ❌ |
url_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the URL filter | ❌ |
tags_name |
str |
Tag name | ❌ |
tags_name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the tag name filter | ❌ |
tags_id |
Union[str, int] |
Tag ID | ❌ |
tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tag ID filter | ❌ |
createdDate |
str |
Date created | ❌ |
createdDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the created date filter | ❌ |
updatedDate |
str |
Date updated | ❌ |
updatedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the updated date filter | ❌ |
isScheduled |
bool |
If the webapp has a scan scheduled | ❌ |
isScheduled_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScheduled filter | ❌ |
isScanned |
bool |
If the webapp has been scanned | ❌ |
isScanned_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isScanned filter | ❌ |
lastScan_status |
Literal["SUBMITTED", "RUNNING", "FINISHED", "TIME_LIMIT_EXCEEDED", "SCAN_NOT_LAUNCHED", "SCANNER_NOT_AVAILABLE", "ERROR", "CANCELLED"] |
Status of the last scan | ❌ |
lastScan_status_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the lastScan_status filter | ❌ |
lastScan_date |
str |
Date of the last scan in UTC date/time format | ❌ |
lastScan_date_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the lastScan_date filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import purge_webapp
auth = BasicAuth(<username>, <password>)
# Purge scan data for a webapp by ID:
purge_webapp(auth, id=12345678)
# Purge scan data for multiple webapps by ID:
purge_webapp(auth, id="12345678,98765432", id_operator="IN")
# Purge scan data for all webapps that have the "deprecated" tag:
purge_webapp(auth, tags_name="deprecated", tags_name_operator="EQUALS")
>>>[{"id": 12345678}, {"id": 98765432}, ...]
Download a Web App's Associated Selenium Script API
get_selenium_script
returns the Selenium script associated with a web app.
Head's Up! Currently, code to create a dataclass object out of the response to this API has not been written. This is a stub. If you have written the code yourself, please submit a pull request! This method will still return data, but it will be the raw data underneath the API response's
data
XML tag.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
id |
Union[str, int] |
Web app ID | ✅ |
crawlingScripts_id |
Union[str, int] |
Crawling script ID | ✅ |
from qualysdk import BasicAuth
from qualysdk.was import get_selenium_script
auth = BasicAuth(<username>, <password>)
# STUB!
Count Authentication Records API
count_authentication_records
returns the number of authentication records in the subscription that match the given kwargs.
Head's Up! This method is useful for quickly getting a count of authentication records that match certain criteria. It does NOT return the authentication records themselves, or any attributes of the authentication records.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
id |
Union[str, int] |
Auth record ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
name |
str |
Auth record name | ❌ |
name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the name filter | ❌ |
tags |
Union[str, int] |
Tag ID | ❌ |
tags_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tags filter | ❌ |
tags_name |
str |
Tag name | ❌ |
tags_name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the tag name filter | ❌ |
tags_id |
Union[str, int] |
Tag ID | ❌ |
tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tag ID filter | ❌ |
createdDate |
str |
Date created | ❌ |
createdDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the created date filter | ❌ |
updatedDate |
str |
Date updated | ❌ |
updatedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the updated date filter | ❌ |
isUsed |
bool |
If the auth record is in use | ❌ |
isUsed_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isUsed filter | ❌ |
lastScan_authStatus |
Literal["NONE", "NOT_USED", "PARTIAL", "FAILED", "SUCCESSFUL"] |
Status of the last scan | ❌ |
lastScan_authStatus_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the lastScan_authStatus filter | ❌ |
lastScan_date |
str |
Date of the last scan in UTC date/time format | ❌ |
lastScan_date_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the lastScan_date filter | ❌ |
contents |
Literal["FORM_STANDARD", "FORM_CUSTOM", "FORM_SELENIUM", "SERVER_BASIC", "SERVER_DIGEST", "SERVER_NTLM", "CERTIFICATE", "OAUTH2_AUTH_CODE", "OAUTH2_IMPLICIT", "OAUTH2_PASSWORD", "OAUTH2_CLIENT_CREDS"] |
Auth record contents | ❌ |
contents_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the contents filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import count_authentication_records
auth = BasicAuth(<username>, <password>)
# Get the number of Selenium auth records that have a lastScan.authStatus of "FAILED":
failed_selenium = count_authentication_records(
auth,
lastScan_authStatus="FAILED",
contents="FORM_SELENIUM"
)
>>>5
# Get all OAuth2 auth records:
oauth2 = count_authentication_records(
auth,
contents="OAUTH2_AUTH_CODE,OAUTH2_IMPLICIT,OAUTH2_PASSWORD,OAUTH2_CLIENT_CREDS",
contents_operator="IN"
)
>>>50
List Authentication Records API
get_authentication_records
returns a list of authentication records in the subscription that match the given kwargs.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
page_count |
Union[int, 'all'] = 'all' |
Number of pages to return. If 'all', returns all pages | ❌ |
id |
Union[str, int] |
Auth record ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
name |
str |
Auth record name | ❌ |
name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the name filter | ❌ |
tags |
Union[str, int] |
Tag ID | ❌ |
tags_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tags filter | ❌ |
tags_name |
str |
Tag name | ❌ |
tags_name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the tag name filter | ❌ |
tags_id |
Union[str, int] |
Tag ID | ❌ |
tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tag ID filter | ❌ |
createdDate |
str |
Date created | ❌ |
createdDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the created date filter | ❌ |
updatedDate |
str |
Date updated | ❌ |
updatedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the updated date filter | ❌ |
isUsed |
bool |
If the auth record is in use | ❌ |
isUsed_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isUsed filter | ❌ |
lastScan_authStatus |
Literal["NONE", "NOT_USED", "PARTIAL", "FAILED", "SUCCESSFUL"] |
Status of the last scan | ❌ |
lastScan_authStatus_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the lastScan_authStatus filter | ❌ |
lastScan_date |
str |
Date of the last scan in UTC date/time format | ❌ |
lastScan_date_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the lastScan_date filter | ❌ |
contents |
Literal["FORM_STANDARD", "FORM_CUSTOM", "FORM_SELENIUM", "SERVER_BASIC", "SERVER_DIGEST", "SERVER_NTLM", "CERTIFICATE", "OAUTH2_AUTH_CODE", "OAUTH2_IMPLICIT", "OAUTH2_PASSWORD", "OAUTH2_CLIENT_CREDS"] |
Auth record type | ❌ |
contents_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the contents filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import get_authentication_records
auth = BasicAuth(<username>, <password>)
# Get all authentication records:
auth_records = get_authentication_records(auth)
>>>[
WebAppAuthRecord(
id=12345678,
name="My Auth Record",
owner_id=98765432,
owner_firstName="John",
owner_lastName="Doe",
createdDate=datetime.datetime(2022, 1, 1, 0, 0, tzinfo=datetime.timezone.utc),
updatedDate=datetime.datetime(2022, 2, 1, 0, 0, tzinfo=datetime.timezone.utc),
),
...
]
# Get all authentication records that have a lastScan.authStatus of "FAILED":
failed_auth_records = get_authentication_records(auth, lastScan_authStatus="FAILED")
>>>[
WebAppAuthRecord(
id=12345678,
name="My Failed Auth Record",
owner_id=98765432,
owner_firstName="John",
owner_lastName="Doe",
createdDate=datetime.datetime(2022, 1, 1, 0, 0, tzinfo=datetime.timezone.utc),
updatedDate=datetime.datetime(2022, 2, 1, 0, 0, tzinfo=datetime.timezone.utc),
),
...
]
Get Authentication Record Details API
get_authentication_record_details
returns all attributes of a single auth record.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
recordId |
Union[str, int] |
Auth record ID | ✅ |
Head's Up!: Server, Form, and OAuth2 passwords are automatically redacted when calling
sql.upload_was_authentication_records
and the record'ssecured
attribute is set toTrue
or the record'sname
attribute equals"password"
.
from qualysdk import BasicAuth
from qualysdk.was import get_authentication_record_details, get_authentication_records
# First, get some IDs of the auth records you want to get details for:
auth = BasicAuth(<username>, <password>)
authrecords = get_authentication_records(auth)
authrecord_id = webapps[0].id
# Get the details for the webapp. Some fields have been removed for space:
webapp = get_authentication_record_details(auth, authrecord_id)
>>>WebAppAuthRecord(
id=12345678,
name='My site',
owner_id=987654321,
owner_username='username',
owner_firstName='Eddie',
owner_lastName='Van Halen',
formRecord_type='STANDARD',
formRecord_sslOnly=False,
formRecord_authVault=False,
formRecord_seleniumCreds=False,
formRecord_fields_count=2,
formRecord_fields_list=[
WebAppAuthFormRecord(id=12345678, name='username', secured=False, value='username'),
WebAppAuthFormRecord(id=12345678, name='password', secured=False, value='Some Password')
],
tags_count=1,
tags_list=[WASTag(id=12345678, name='Main websites')],
comments_count=0,
comments_list=[],
createdDate=datetime.datetime(2024, 1, 1, 1, 10, 0, tzinfo=datetime.timezone.utc),
updatedDate=datetime.datetime(2024, 1, 1, 1, 30, 0, tzinfo=datetime.timezone.utc),
createdBy_id=12345678,
createdBy_username='username',
createdBy_firstName='Layne',
createdBy_lastName='Staley',
updatedBy_id=88888888,
updatedBy_username='username',
updatedBy_firstName='James',
updatedBy_lastName='Hetfield'
)
Get Authentication Records Verbose API
get_authentication_records_verbose
combines the functionality of get_authentication_records
and get_authentication_record_details
to return a list of auth records with all attributes.
This method uses threading to speed up the process. Number of threads can be set with the thread_count
parameter.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
thread_count |
int |
Number of threads to use for the request | ❌ |
page_count |
Union[int, 'all'] = 'all' |
Number of pages to return. If 'all', returns all pages | ❌ |
id |
Union[str, int] |
Auth record ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
name |
str |
Auth record name | ❌ |
name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the name filter | ❌ |
tags |
Union[str, int] |
Tag ID | ❌ |
tags_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tags filter | ❌ |
tags_name |
str |
Tag name | ❌ |
tags_name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the tag name filter | ❌ |
tags_id |
Union[str, int] |
Tag ID | ❌ |
tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tag ID filter | ❌ |
createdDate |
str |
Date created | ❌ |
createdDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the created date filter | ❌ |
updatedDate |
str |
Date updated | ❌ |
updatedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the updated date filter | ❌ |
isUsed |
bool |
If the auth record is in use | ❌ |
isUsed_operator |
Literal["EQUALS", "NOT EQUALS"] |
Operator for the isUsed filter | ❌ |
lastScan_authStatus |
Literal["NONE", "NOT_USED", "PARTIAL", "FAILED", "SUCCESSFUL"] |
Status of the last scan | ❌ |
lastScan_authStatus_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the lastScan_authStatus filter | ❌ |
lastScan_date |
str |
Date of the last scan in UTC date/time format | ❌ |
lastScan_date_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the lastScan_date filter | ❌ |
contents |
Literal["FORM_STANDARD", "FORM_CUSTOM", "FORM_SELENIUM", "SERVER_BASIC", "SERVER_DIGEST", "SERVER_NTLM", "CERTIFICATE", "OAUTH2_AUTH_CODE", "OAUTH2_IMPLICIT", "OAUTH2_PASSWORD", "OAUTH2_CLIENT_CREDS"] |
Auth record type | ❌ |
contents_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the contents filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import get_authentication_records_verbose
auth = BasicAuth(<username>, <password>)
# Get all auth records with all attributes:
authrecords = get_authentication_records_verbose(auth)
>>>[
WebAppAuthRecord(
id=12345678,
name="some auth record",
formRecord_type="SELENIUM",
...
),
WebAppAuthRecord(
id=98765432,
...
),
...
]
# Get all auth records with all attributes
# that have "prod" in the name, using 10 threads:
authrecords = get_authentication_records_verbose(
auth,
name="prod",
name_operator="CONTAINS",
thread_count=10
)
>>>[
WebAppAuthRecord(
id=12345678,
name="some prod auth record",
...
),
...
]
Create Authentication Record API
create_authentication_record
creates a new authentication record in the subscription. You can create formRecord
, serverRecord
, and oauth2Record
types. Each type requires different attributes, which are detailed below.
Head's Up!: The options for this API endpoint are quite complex. When in doubt, refer to the error messages the SDK raises. It may take a few tries to get the right combination of arguments.
Form Record
Below are the possible arguments for creating a form record:
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
name |
str |
Auth record name | ✅ |
recordType |
str = formRecord |
Record type | ✅ |
subType |
Literal["STANDARD", "CUSTOM", "SELENIUM"] |
Record sub-type | ✅ |
fields |
list[dict["name": str, "value": str]] |
List of fields | ✅ |
sslOnly |
bool |
If the authentication record should only be sent on a secure connection | ❌ |
authVault |
bool |
If the authentication record should be stored in the auth vault | ❌ |
seleniumCreds |
bool |
If the authentication record is for a Selenium script | ❌ |
seleniumScript |
dict[str, str] , like: {"name": "my_script", "data": <script_as_XML_string>} |
Selenium script data | ❌ |
tags |
list[Union[str, int]] |
List of tag IDs | ❌ |
comments |
list[str] |
List of comments | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import create_authentication_record
auth = BasicAuth(<username>, <password>)
# EXAMPLE formRecord with basic username/password fields:
new_auth_record = create_authentication_record(
auth,
name="My New Auth Record",
recordType="formRecord",
subType="STANDARD",
fields=[
{"name": "username", "value": "my_username"},
{"name": "password", "value": "my_password"},
],
tags=[12345, 54321],
comments=["This is my new auth record"],
sslOnly=True,
)
# SELENIUM EXAMPLE:
new_auth_record = create_authentication_record(
auth,
name="My Selenium Auth Record",
recordType="formRecord",
subType="SELENIUM",
fields=[
{"name": "username", "value": "my_username"},
{"name": "password", "value": "my_password"},
],
seleniumCreds=True,
seleniumScript={"name": "my_script", "data": """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head profile="http://selenium-ide.openqa.org/profiles/test-case">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="selenium.base" href="https://community.qualys.com/" />
<title>seleniumScriptOK</title>
</head>
<body>
<table cellpadding="1" cellspacing="1" border="1">..."""},
)
Server Record
Below are the possible arguments for creating a server record:
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
name |
str |
Auth record name | ✅ |
recordType |
str = serverRecord |
Record type | ✅ |
sslOnly |
bool |
If the authentication record should only be sent on a secure connection | ❌ |
certificate |
dict["name": str, "contents": str, "passphrase": str] |
Certificate data | ❌ |
tags |
list[Union[str, int]] |
List of tag IDs | ❌ |
comments |
list[str] |
List of comments | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import create_authentication_record
auth = BasicAuth(<username>, <password>)
# EXAMPLE serverRecord with a certificate:
new_auth_record = create_authentication_record(
auth,
name="My New Server Auth Record",
recordType="serverRecord",
certificate={"name": "my_cert", "contents": "-----BEGIN CERTIFICATE-----\nMIID...-----END CERTIFICATE-----", "passphrase": "my_passphrase"},
tags=[12345, 54321],
comments=["This is my new server auth record"],
sslOnly=True,
)
OAuth2 Record
Below are the possible arguments for creating an OAuth2 record:
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
name |
str |
Auth record name | ✅ |
recordType |
str = oauth2Record |
Record type | ✅ |
subType |
Literal["AUTH_CODE", "IMPLICIT", "PASSWORD", "CLIENT_CREDS"] |
Record sub-type | ✅ |
clientId |
str |
OAuth2 client ID | ✅ |
clientSecret |
str |
OAuth2 client secret | ✅ |
accessTokenUrl |
str |
OAuth2 access token URL | ✅ |
scope |
str |
OAuth2 scope | ❌ |
accessTokenExpiredMsgPattern |
str |
OAuth2 access token expired message pattern | ❌ |
seleniumCreds |
bool |
If the authentication record is for a Selenium script | ❌ |
seleniumScript |
dict[str, str] , like: {"name": "my_script", "data": <script_as_XML_string>} |
Selenium script data | ❌ |
tags |
list[Union[str, int]] |
List of tag IDs | ❌ |
comments |
list[str] |
List of comments | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import create_authentication_record
auth = BasicAuth(<username>, <password>)
# EXAMPLE OAuth2 record:
new_auth_record = create_authentication_record(
auth,
name="My New OAuth2 Auth Record",
recordType="oauth2Record",
subType="CLIENT_CREDS",
clientId="my_client_id",
clientSecret="my_client_secret",
accessTokenUrl="https://example.com/token",
scope="scope",
tags=[12345, 54321],
comments=["This is my new OAuth2 auth record"],
)
Delete Authentication Record API
delete_authentication_record
deletes an authentication record in the subscription.
Returns a list of auth record IDs that were deleted as a dictionary: {"id": <id>}
Head's Up!: Using this API may only remove the WAS-specific asset in the subscription. It may still be active in other Qualys modules, such as Global AssetView's web application view.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
id |
Union[str, int] |
Auth record ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
name |
str |
Auth record name | ❌ |
name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the name filter | ❌ |
tags |
Union[str, int] |
Tag ID | ❌ |
tags_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tags filter | ❌ |
tags_name |
str |
Tag name | ❌ |
tags_name_operator |
Literal["CONTAINS", "EQUALS", "NOT EQUALS"] |
Operator for the tag name filter | ❌ |
tags_id |
Union[str, int] |
Tag ID | ❌ |
tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the tag ID filter | ❌ |
createdDate |
str |
Date created | ❌ |
createdDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the created date filter | ❌ |
updatedDate |
str |
Date updated | ❌ |
updatedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the updated date filter | ❌ |
lastScan_date |
str |
Date of the last scan in UTC date/time format | ❌ |
lastScan_date_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER"] |
Operator for the lastScan_date filter | ❌ |
lastScan_authStatus |
Literal["NONE", "NOT_USED", "PARTIAL", "FAILED", "SUCCESSFUL"] |
Status of the last scan | ❌ |
lastScan_authStatus_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the lastScan_authStatus filter | ❌ |
isUsed |
bool |
If the auth record is in use | ❌ |
contents |
Literal["FORM_STANDARD", "FORM_CUSTOM", "FORM_SELENIUM", "SERVER_BASIC", "SERVER_DIGEST", "SERVER_NTLM", "CERTIFICATE", "OAUTH2_AUTH_CODE", "OAUTH2_IMPLICIT", "OAUTH2_PASSWORD", "OAUTH2_CLIENT_CREDS"] |
Auth record type | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import delete_authentication_record
auth = BasicAuth(<username>, <password>)
# Delete an auth record by ID:
delete_authentication_record(auth, id=12345678)
# Delete all auth record with the PURGE tag:
delete_authentication_record(auth, tags_name="PURGE", tags_name_operator="EQUALS")
>>>[{"id": 12345678}, {"id": 98765432}, ...]
Count Findings API
count_findings
returns the number of findings in the subscription that match the given kwargs.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
id |
Union[str, int] |
Finding ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
uniqueId |
str |
Unique ID of the finding | ❌ |
qid |
int |
Qualys ID of the finding | ❌ |
qid_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the QID filter | ❌ |
name |
str |
Name of the finding | ❌ |
name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the name filter | ❌ |
type |
Literal["VULNERABILITY", "SENSITIVE_CONTENT", "INFORMATION_GATHERED"] |
Type of the finding | ❌ |
type_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the type filter | ❌ |
url |
str |
URL of the finding's webapp | ❌ |
url_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the URL filter | ❌ |
webApp_tags_id |
int |
A tag ID on the webapp | ❌ |
webApp_tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the webApp_tags_id filter | ❌ |
webApp_tags_name |
str |
A tag name on the webapp | ❌ |
webApp_tags_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the webApp_tags_name filter | ❌ |
status |
Literal["NEW", "ACTIVE", "REOPENED", "PROTECTED", "FIXED"] |
Status of the finding | ❌ |
status_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the status filter | ❌ |
patch |
int |
Patch ID for WAF module | ❌ |
patch_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the patch filter | ❌ |
webApp_id |
int |
Webapp ID | ❌ |
webApp_id_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the webApp_id filter | ❌ |
webApp_name |
str |
Webapp name | ❌ |
webApp_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the webApp_name filter | ❌ |
severity |
Literal[1, 2, 3, 4, 5] |
Severity of the finding | ❌ |
severity_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the severity filter | ❌ |
externalRef |
str |
External reference of the finding | ❌ |
externalRef_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the externalRef filter | ❌ |
ignoredDate |
str |
Date the finding was ignored | ❌ |
ignoredDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ignoredDate filter | ❌ |
ignoredReason |
Literal["FALSE_POSITIVE", "RISK_ACCEPTED", "NOT_APPLICABLE"] |
Reason the finding was ignored | ❌ |
ignoredReason_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the ignoredReason filter | ❌ |
group |
Literal["XSS", "SQL", "INFO", "PATH", "CC", "SSN_US", "CUSTOM"] |
Group of the finding | ❌ |
group_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the group filter | ❌ |
owasp_name |
str |
OWASP name of the finding | ❌ |
owasp_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the owasp_name filter | ❌ |
owasp_code |
int |
OWASP code of the finding | ❌ |
owasp_code_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the owasp_code filter | ❌ |
wasc_name |
str |
WASC name of the finding | ❌ |
wasc_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the wasc_name filter | ❌ |
wasc_code |
int |
WASC code of the finding | ❌ |
wasc_code_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the wasc_code filter | ❌ |
cwe_id |
int |
CWE ID of the finding | ❌ |
cwe_id_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the cwe_id filter | ❌ |
firstDetectedDate |
str |
Date the finding was first detected | ❌ |
firstDetectedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the firstDetectedDate filter | ❌ |
lastDetectedDate |
str |
Date the finding was last detected | ❌ |
lastDetectedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the lastDetectedDate filter | ❌ |
lastTestedDate |
str |
Date the finding was last tested | ❌ |
lastTestedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the lastTestedDate filter | ❌ |
timesDetected |
int |
Number of times the finding was detected | ❌ |
timesDetected_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the timesDetected filter | ❌ |
fixedDate |
str |
Date the finding was fixed | ❌ |
fixedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the fixedDate filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import count_findings
auth = BasicAuth(<username>, <password>)
# Get the number of findings with a severity of 5:
count = count_findings(auth, severity=5)
# Get XSS findings that are severity 4 or 5,
# and have been detected 5+ times
# on assets with the PROD tag:
count = count_findings(
auth,
group="XSS",
severity="4,5",
severity_operator="IN",
timesDetected=4,
timesDetected_operator="GREATER",
webApp_tags_name="PROD",
)
>>> 5
List Findings API
get_findings
returns a list of findings in the subscription that match the given kwargs.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
page_count |
Union[int, 'all'] = 'all' |
Number of pages to return. If 'all', returns all pages | ❌ |
verbose |
bool |
Whether to return verbose output | ❌ |
id |
Union[str, int] |
Finding ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
uniqueId |
str |
Unique ID of the finding | ❌ |
qid |
int |
Qualys ID of the finding | ❌ |
qid_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the QID filter | ❌ |
name |
str |
Name of the finding | ❌ |
name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the name filter | ❌ |
type |
Literal["VULNERABILITY", "SENSITIVE_CONTENT", "INFORMATION_GATHERED"] |
Type of the finding | ❌ |
type_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the type filter | ❌ |
url |
str |
URL of the finding's webapp | ❌ |
url_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the URL filter | ❌ |
webApp_tags_id |
int |
A tag ID on the webapp | ❌ |
webApp_tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the webApp_tags_id filter | ❌ |
webApp_tags_name |
str |
A tag name on the webapp | ❌ |
webApp_tags_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the webApp_tags_name filter | ❌ |
status |
Literal["NEW", "ACTIVE", "REOPENED", "PROTECTED", "FIXED"] |
Status of the finding | ❌ |
status_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the status filter | ❌ |
patch |
int |
Patch ID for WAF module | ❌ |
patch_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the patch filter | ❌ |
webApp_id |
int |
Webapp ID | ❌ |
webApp_id_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the webApp_id filter | ❌ |
webApp_name |
str |
Webapp name | ❌ |
webApp_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the webApp_name filter | ❌ |
severity |
Literal[1, 2, 3, 4, 5] |
Severity of the finding | ❌ |
severity_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the severity filter | ❌ |
externalRef |
str |
External reference of the finding | ❌ |
externalRef_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the externalRef filter | ❌ |
ignoredDate |
str |
Date the finding was ignored | ❌ |
ignoredDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ignoredDate filter | ❌ |
ignoredReason |
Literal["FALSE_POSITIVE", "RISK_ACCEPTED", "NOT_APPLICABLE"] |
Reason the finding was ignored | ❌ |
ignoredReason_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the ignoredReason filter | ❌ |
group |
Literal["XSS", "SQL", "INFO", "PATH", "CC", "SSN_US", "CUSTOM"] |
Group of the finding | ❌ |
group_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the group filter | ❌ |
owasp_name |
str |
OWASP name of the finding | ❌ |
owasp_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the owasp_name filter | ❌ |
owasp_code |
int |
OWASP code of the finding | ❌ |
owasp_code_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the owasp_code filter | ❌ |
wasc_name |
str |
WASC name of the finding | ❌ |
wasc_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the wasc_name filter | ❌ |
wasc_code |
int |
WASC code of the finding | ❌ |
wasc_code_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the wasc_code filter | ❌ |
cwe_id |
int |
CWE ID of the finding | ❌ |
cwe_id_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the cwe_id filter | ❌ |
firstDetectedDate |
str |
Date the finding was first detected | ❌ |
firstDetectedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the firstDetectedDate filter | ❌ |
lastDetectedDate |
str |
Date the finding was last detected | ❌ |
lastDetectedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the lastDetectedDate filter | ❌ |
lastTestedDate |
str |
Date the finding was last tested | ❌ |
lastTestedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the lastTestedDate filter | ❌ |
timesDetected |
int |
Number of times the finding was detected | ❌ |
timesDetected_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the timesDetected filter | ❌ |
fixedDate |
str |
Date the finding was fixed | ❌ |
fixedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the fixedDate filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import get_findings
auth = BasicAuth(<username>, <password>)
# Get all findings, with all details:
findings = get_findings(auth, verbose=True)
>>>[
WASFinding(
id=123456789,
uniqueId='aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee',
qid=86002,
detectionScore=0,
name='SSL Certificate - Information',
type='INFORMATION_GATHERED',
potential=True,
findingType='QUALYS',
severity=1,
...
),
...
]
# Get all XSS & SQL findings
# with a severity of 4 or 5
# that have been detected
# 5+ times on assets with the PROD tag:
findings = get_findings(
auth,
group="XSS,SQL",
group_operator="IN",
severity="4,5",
severity_operator="IN",
timesDetected=4,
timesDetected_operator="GREATER",
webApp_tags_name="PROD",
)
Get Finding Details API
get_finding_details
returns the details of a single finding in the subscription.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
findingId |
Union[str, int] |
Finding # or unique ID | ✅ |
from qualysdk import BasicAuth
from qualysdk.was import get_finding_details
auth = BasicAuth(<username>, <password>)
finding = get_finding_details(auth, findingId=123456789)
finding2 = get_finding_details(auth, findingId="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")
Get Findings Verbose API
get_findings_verbose
returns a list of findings in the subscription with all attributes. This method uses threading to speed up the process. Number of threads can be set with the thread_count
parameter.
Head's Up!: Unlike the other
get_<thing>_verbose
methods, this method is not always faster than the non-verbose version. It is recommended to use the non-verbose version unless you need data specifically related to SSL/TLS certificates.
Parameter | Possible Values | Description | Required |
---|---|---|---|
auth |
qualysdk.auth.BasicAuth |
Authentication object | ✅ |
thread_count |
int |
Number of threads to use for the request | ❌ |
page_count |
Union[int, 'all'] = 'all' |
Number of pages to return. If 'all', returns all pages | ❌ |
verbose |
bool |
Whether to return verbose output | ❌ |
id |
Union[str, int] |
Finding ID | ❌ |
id_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ID filter | ❌ |
uniqueId |
str |
Unique ID of the finding | ❌ |
qid |
int |
Qualys ID of the finding | ❌ |
qid_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the QID filter | ❌ |
name |
str |
Name of the finding | ❌ |
name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the name filter | ❌ |
type |
Literal["VULNERABILITY", "SENSITIVE_CONTENT", "INFORMATION_GATHERED"] |
Type of the finding | ❌ |
type_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the type filter | ❌ |
url |
str |
URL of the finding's webapp | ❌ |
url_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the URL filter | ❌ |
webApp_tags_id |
int |
A tag ID on the webapp | ❌ |
webApp_tags_id_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the webApp_tags_id filter | ❌ |
webApp_tags_name |
str |
A tag name on the webapp | ❌ |
webApp_tags_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the webApp_tags_name filter | ❌ |
status |
Literal["NEW", "ACTIVE", "REOPENED", "PROTECTED", "FIXED"] |
Status of the finding | ❌ |
status_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the status filter | ❌ |
patch |
int |
Patch ID for WAF module | ❌ |
patch_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the patch filter | ❌ |
webApp_id |
int |
Webapp ID | ❌ |
webApp_id_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the webApp_id filter | ❌ |
webApp_name |
str |
Webapp name | ❌ |
webApp_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the webApp_name filter | ❌ |
severity |
Literal[1, 2, 3, 4, 5] |
Severity of the finding | ❌ |
severity_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the severity filter | ❌ |
externalRef |
str |
External reference of the finding | ❌ |
externalRef_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the externalRef filter | ❌ |
ignoredDate |
str |
Date the finding was ignored | ❌ |
ignoredDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the ignoredDate filter | ❌ |
ignoredReason |
Literal["FALSE_POSITIVE", "RISK_ACCEPTED", "NOT_APPLICABLE"] |
Reason the finding was ignored | ❌ |
ignoredReason_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the ignoredReason filter | ❌ |
group |
Literal["XSS", "SQL", "INFO", "PATH", "CC", "SSN_US", "CUSTOM"] |
Group of the finding | ❌ |
group_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the group filter | ❌ |
owasp_name |
str |
OWASP name of the finding | ❌ |
owasp_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the owasp_name filter | ❌ |
owasp_code |
int |
OWASP code of the finding | ❌ |
owasp_code_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the owasp_code filter | ❌ |
wasc_name |
str |
WASC name of the finding | ❌ |
wasc_name_operator |
Literal["EQUALS", "NOT EQUALS", "CONTAINS"] |
Operator for the wasc_name filter | ❌ |
wasc_code |
int |
WASC code of the finding | ❌ |
wasc_code_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the wasc_code filter | ❌ |
cwe_id |
int |
CWE ID of the finding | ❌ |
cwe_id_operator |
Literal["EQUALS", "NOT EQUALS", "IN"] |
Operator for the cwe_id filter | ❌ |
firstDetectedDate |
str |
Date the finding was first detected | ❌ |
firstDetectedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the firstDetectedDate filter | ❌ |
lastDetectedDate |
str |
Date the finding was last detected | ❌ |
lastDetectedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the lastDetectedDate filter | ❌ |
lastTestedDate |
str |
Date the finding was last tested | ❌ |
lastTestedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the lastTestedDate filter | ❌ |
timesDetected |
int |
Number of times the finding was detected | ❌ |
timesDetected_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the timesDetected filter | ❌ |
fixedDate |
str |
Date the finding was fixed | ❌ |
fixedDate_operator |
Literal["EQUALS", "NOT EQUALS", "GREATER", "LESSER", "IN"] |
Operator for the fixedDate filter | ❌ |
from qualysdk import BasicAuth
from qualysdk.was import get_findings_verbose
auth = BasicAuth(<username>, <password>)
findings = get_findings_verbose(auth, severity=5)
qualysdk-was
CLI tool
The qualysdk-was
CLI tool is a command-line interface for the WAS portion of the SDK. It allows you to quickly pull down results from WAS APIs and save them to an XLSX file.
Usage
usage: qualysdk-was [-h] -u USERNAME -p PASSWORD [-P {qg1,qg2,qg3,qg4}] {get_findings} ...
CLI script to quickly perform Web Application Scanning (WAS) operations using qualysdk
positional arguments:
{get_findings} Action to perform
get_findings Get a list of WAS findings.
options:
-h, --help show this help message and exit
-u USERNAME, --username USERNAME
Qualys username
-p PASSWORD, --password PASSWORD
Qualys password
-P {qg1,qg2,qg3,qg4}, --platform {qg1,qg2,qg3,qg4}
Qualys platform
Get Findings
usage: qualysdk-was get_findings [-h] [-o OUTPUT] [--kwarg key value]
options:
-h, --help show this help message and exit
-o OUTPUT, --output OUTPUT
Output xlsx file to write results to
--kwarg key value Specify a keyword argument to pass to the get_findings function. Can be used multiple times
# Example with a few kwargs:
qualysdk-was -u <username> -p <password> -P qg1 get_findings --kwarg verbose true --kwarg group XSS --output xss_findings.xlsx
>>>Data written to xss_findings.xlsx.