diff --git a/CHANGELOG.md b/CHANGELOG.md index dd36fa2..16ab8a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Minimum Python 3 version is now 3.4. ### Changed +- Update core APIs for ZAP 2.8.0. - Allow to validate the status code returned by the ZAP API, to fail sooner if the API request was not successful. This can be enabled when instantiating the `ZAPv2` class with the argument `validate_status_code` diff --git a/src/zapv2/__init__.py b/src/zapv2/__init__.py index e421e14..5be58bf 100644 --- a/src/zapv2/__init__.py +++ b/src/zapv2/__init__.py @@ -26,6 +26,7 @@ from requests.packages.urllib3.exceptions import InsecureRequestWarning from .acsrf import acsrf +from .alert import alert from .ascan import ascan from .ajaxSpider import ajaxSpider from .authentication import authentication @@ -80,6 +81,7 @@ def __init__(self, proxies=None, apikey=None, validate_status_code=False): self.__validate_status_code=validate_status_code self.acsrf = acsrf(self) + self.alert = alert(self) self.ajaxSpider = ajaxSpider(self) self.ascan = ascan(self) self.authentication = authentication(self) diff --git a/src/zapv2/alert.py b/src/zapv2/alert.py new file mode 100644 index 0000000..e17b9ac --- /dev/null +++ b/src/zapv2/alert.py @@ -0,0 +1,103 @@ +# Zed Attack Proxy (ZAP) and its related class files. +# +# ZAP is an HTTP/HTTPS proxy for assessing web application security. +# +# Copyright 2019 the ZAP development team +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +This file was automatically generated. +""" + +import six + + +class alert(object): + + def __init__(self, zap): + self.zap = zap + + def alert(self, id): + """ + Gets the alert with the given ID, the corresponding HTTP message can be obtained with the 'messageId' field and 'message' API method + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'alert/view/alert/', {'id': id}))) + + def alerts(self, baseurl=None, start=None, count=None, riskid=None): + """ + Gets the alerts raised by ZAP, optionally filtering by URL or riskId, and paginating with 'start' position and 'count' of alerts + """ + params = {} + if baseurl is not None: + params['baseurl'] = baseurl + if start is not None: + params['start'] = start + if count is not None: + params['count'] = count + if riskid is not None: + params['riskId'] = riskid + return six.next(six.itervalues(self.zap._request(self.zap.base + 'alert/view/alerts/', params))) + + def alerts_summary(self, baseurl=None): + """ + Gets number of alerts grouped by each risk level, optionally filtering by URL + """ + params = {} + if baseurl is not None: + params['baseurl'] = baseurl + return six.next(six.itervalues(self.zap._request(self.zap.base + 'alert/view/alertsSummary/', params))) + + def number_of_alerts(self, baseurl=None, riskid=None): + """ + Gets the number of alerts, optionally filtering by URL or riskId + """ + params = {} + if baseurl is not None: + params['baseurl'] = baseurl + if riskid is not None: + params['riskId'] = riskid + return six.next(six.itervalues(self.zap._request(self.zap.base + 'alert/view/numberOfAlerts/', params))) + + def alerts_by_risk(self, url=None, recurse=None): + """ + Gets a summary of the alerts, optionally filtered by a 'url'. If 'recurse' is true then all alerts that apply to urls that start with the specified 'url' will be returned, otherwise only those on exactly the same 'url' (ignoring url parameters) + """ + params = {} + if url is not None: + params['url'] = url + if recurse is not None: + params['recurse'] = recurse + return six.next(six.itervalues(self.zap._request(self.zap.base + 'alert/view/alertsByRisk/', params))) + + def alert_counts_by_risk(self, url=None, recurse=None): + """ + Gets a count of the alerts, optionally filtered as per alertsPerRisk + """ + params = {} + if url is not None: + params['url'] = url + if recurse is not None: + params['recurse'] = recurse + return six.next(six.itervalues(self.zap._request(self.zap.base + 'alert/view/alertCountsByRisk/', params))) + + def delete_all_alerts(self, apikey=''): + """ + Deletes all alerts of the current session. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'alert/action/deleteAllAlerts/', {'apikey': apikey}))) + + def delete_alert(self, id, apikey=''): + """ + Deletes the alert with the given ID. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'alert/action/deleteAlert/', {'id': id, 'apikey': apikey}))) diff --git a/src/zapv2/ascan.py b/src/zapv2/ascan.py index 93f748c..0c21b36 100644 --- a/src/zapv2/ascan.py +++ b/src/zapv2/ascan.py @@ -67,6 +67,9 @@ def excluded_from_scan(self): return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/view/excludedFromScan/'))) def scanners(self, scanpolicyname=None, policyid=None): + """ + Gets the scanners, optionally, of the given scan policy and/or scanner policy/category ID. + """ params = {} if scanpolicyname is not None: params['scanPolicyName'] = scanpolicyname @@ -159,6 +162,13 @@ def option_target_params_injectable(self): def option_thread_per_host(self): return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/view/optionThreadPerHost/'))) + @property + def option_add_query_param(self): + """ + Tells whether or not the active scanner should add a query parameter to GET request that don't have parameters to start with. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/view/optionAddQueryParam/'))) + @property def option_allow_attack_on_start(self): return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/view/optionAllowAttackOnStart/'))) @@ -272,24 +282,36 @@ def exclude_from_scan(self, regex, apikey=''): return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/action/excludeFromScan/', {'regex': regex, 'apikey': apikey}))) def enable_all_scanners(self, scanpolicyname=None, apikey=''): + """ + Enables all scanners of the scan policy with the given name, or the default if none given. + """ params = {'apikey': apikey} if scanpolicyname is not None: params['scanPolicyName'] = scanpolicyname return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/action/enableAllScanners/', params))) def disable_all_scanners(self, scanpolicyname=None, apikey=''): + """ + Disables all scanners of the scan policy with the given name, or the default if none given. + """ params = {'apikey': apikey} if scanpolicyname is not None: params['scanPolicyName'] = scanpolicyname return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/action/disableAllScanners/', params))) def enable_scanners(self, ids, scanpolicyname=None, apikey=''): + """ + Enables the scanners with the given IDs (comma separated list of IDs) of the scan policy with the given name, or the default if none given. + """ params = {'ids': ids, 'apikey': apikey} if scanpolicyname is not None: params['scanPolicyName'] = scanpolicyname return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/action/enableScanners/', params))) def disable_scanners(self, ids, scanpolicyname=None, apikey=''): + """ + Disables the scanners with the given IDs (comma separated list of IDs) of the scan policy with the given name, or the default if none given. + """ params = {'ids': ids, 'apikey': apikey} if scanpolicyname is not None: params['scanPolicyName'] = scanpolicyname @@ -392,6 +414,12 @@ def set_option_attack_policy(self, string, apikey=''): def set_option_default_policy(self, string, apikey=''): return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/action/setOptionDefaultPolicy/', {'String': string, 'apikey': apikey}))) + def set_option_add_query_param(self, boolean, apikey=''): + """ + Sets whether or not the active scanner should add a query param to GET requests which do not have parameters to start with. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/action/setOptionAddQueryParam/', {'Boolean': boolean, 'apikey': apikey}))) + def set_option_allow_attack_on_start(self, boolean, apikey=''): return six.next(six.itervalues(self.zap._request(self.zap.base + 'ascan/action/setOptionAllowAttackOnStart/', {'Boolean': boolean, 'apikey': apikey}))) diff --git a/src/zapv2/authentication.py b/src/zapv2/authentication.py index 2cad640..8f134fc 100644 --- a/src/zapv2/authentication.py +++ b/src/zapv2/authentication.py @@ -29,28 +29,52 @@ def __init__(self, zap): @property def get_supported_authentication_methods(self): + """ + Gets the name of the authentication methods. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'authentication/view/getSupportedAuthenticationMethods/'))) def get_authentication_method_config_params(self, authmethodname): + """ + Gets the configuration parameters for the authentication method with the given name. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'authentication/view/getAuthenticationMethodConfigParams/', {'authMethodName': authmethodname}))) def get_authentication_method(self, contextid): + """ + Gets the name of the authentication method for the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'authentication/view/getAuthenticationMethod/', {'contextId': contextid}))) def get_logged_in_indicator(self, contextid): + """ + Gets the logged in indicator for the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'authentication/view/getLoggedInIndicator/', {'contextId': contextid}))) def get_logged_out_indicator(self, contextid): + """ + Gets the logged out indicator for the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'authentication/view/getLoggedOutIndicator/', {'contextId': contextid}))) def set_authentication_method(self, contextid, authmethodname, authmethodconfigparams=None, apikey=''): + """ + Sets the authentication method for the context with the given ID. + """ params = {'contextId': contextid, 'authMethodName': authmethodname, 'apikey': apikey} if authmethodconfigparams is not None: params['authMethodConfigParams'] = authmethodconfigparams return six.next(six.itervalues(self.zap._request(self.zap.base + 'authentication/action/setAuthenticationMethod/', params))) def set_logged_in_indicator(self, contextid, loggedinindicatorregex, apikey=''): + """ + Sets the logged in indicator for the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'authentication/action/setLoggedInIndicator/', {'contextId': contextid, 'loggedInIndicatorRegex': loggedinindicatorregex, 'apikey': apikey}))) def set_logged_out_indicator(self, contextid, loggedoutindicatorregex, apikey=''): + """ + Sets the logged out indicator for the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'authentication/action/setLoggedOutIndicator/', {'contextId': contextid, 'loggedOutIndicatorRegex': loggedoutindicatorregex, 'apikey': apikey}))) diff --git a/src/zapv2/autoupdate.py b/src/zapv2/autoupdate.py index a400739..306bfae 100644 --- a/src/zapv2/autoupdate.py +++ b/src/zapv2/autoupdate.py @@ -48,6 +48,13 @@ def installed_addons(self): """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'autoupdate/view/installedAddons/'))) + @property + def local_addons(self): + """ + Returns a list with all local add-ons, installed or not. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'autoupdate/view/localAddons/'))) + @property def new_addons(self): """ @@ -133,6 +140,9 @@ def install_addon(self, id, apikey=''): """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'autoupdate/action/installAddon/', {'id': id, 'apikey': apikey}))) + def install_local_addon(self, file, apikey=''): + return six.next(six.itervalues(self.zap._request(self.zap.base + 'autoupdate/action/installLocalAddon/', {'file': file, 'apikey': apikey}))) + def uninstall_addon(self, id, apikey=''): """ Uninstalls the specified add-on diff --git a/src/zapv2/context.py b/src/zapv2/context.py index 77d9611..3b3a9f6 100644 --- a/src/zapv2/context.py +++ b/src/zapv2/context.py @@ -71,6 +71,12 @@ def excluded_technology_list(self, contextname): """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'context/view/excludedTechnologyList/', {'contextName': contextname}))) + def urls(self, contextname): + """ + Lists the URLs accessed through/by ZAP, that belong to the context with the given name. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'context/view/urls/', {'contextName': contextname}))) + def exclude_from_context(self, contextname, regex, apikey=''): """ Add exclude regex to context @@ -83,6 +89,12 @@ def include_in_context(self, contextname, regex, apikey=''): """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'context/action/includeInContext/', {'contextName': contextname, 'regex': regex, 'apikey': apikey}))) + def set_context_regexs(self, contextname, incregexs, excregexs, apikey=''): + """ + Set the regexs to include and exclude for a context, both supplied as JSON string arrays + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'context/action/setContextRegexs/', {'contextName': contextname, 'incRegexs': incregexs, 'excRegexs': excregexs, 'apikey': apikey}))) + def new_context(self, contextname, apikey=''): """ Creates a new context with the given name in the current session diff --git a/src/zapv2/core.py b/src/zapv2/core.py index 514ee8e..161edd1 100644 --- a/src/zapv2/core.py +++ b/src/zapv2/core.py @@ -27,47 +27,6 @@ class core(object): def __init__(self, zap): self.zap = zap - def alert(self, id): - """ - Gets the alert with the given ID, the corresponding HTTP message can be obtained with the 'messageId' field and 'message' API method - """ - return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/alert/', {'id': id}))) - - def alerts(self, baseurl=None, start=None, count=None, riskid=None): - """ - Gets the alerts raised by ZAP, optionally filtering by URL or riskId, and paginating with 'start' position and 'count' of alerts - """ - params = {} - if baseurl is not None: - params['baseurl'] = baseurl - if start is not None: - params['start'] = start - if count is not None: - params['count'] = count - if riskid is not None: - params['riskId'] = riskid - return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/alerts/', params))) - - def alerts_summary(self, baseurl=None): - """ - Gets number of alerts grouped by each risk level, optionally filtering by URL - """ - params = {} - if baseurl is not None: - params['baseurl'] = baseurl - return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/alertsSummary/', params))) - - def number_of_alerts(self, baseurl=None, riskid=None): - """ - Gets the number of alerts, optionally filtering by URL or riskId - """ - params = {} - if baseurl is not None: - params['baseurl'] = baseurl - if riskid is not None: - params['riskId'] = riskid - return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/numberOfAlerts/', params))) - @property def hosts(self): """ @@ -91,6 +50,15 @@ def urls(self, baseurl=None): params['baseurl'] = baseurl return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/urls/', params))) + def child_nodes(self, url=None): + """ + Gets the child nodes underneath the specified URL in the Sites tree + """ + params = {} + if url is not None: + params['url'] = url + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/childNodes/', params))) + def message(self, id): """ Gets the HTTP message with the given ID. Returns the ID, request/response headers and bodies, cookies, note, type, RTT, and timestamp. @@ -213,6 +181,47 @@ def option_alert_overrides_file_path(self): """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/optionAlertOverridesFilePath/'))) + def alert(self, id): + """ + Gets the alert with the given ID, the corresponding HTTP message can be obtained with the 'messageId' field and 'message' API method + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/alert/', {'id': id}))) + + def alerts(self, baseurl=None, start=None, count=None, riskid=None): + """ + Gets the alerts raised by ZAP, optionally filtering by URL or riskId, and paginating with 'start' position and 'count' of alerts + """ + params = {} + if baseurl is not None: + params['baseurl'] = baseurl + if start is not None: + params['start'] = start + if count is not None: + params['count'] = count + if riskid is not None: + params['riskId'] = riskid + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/alerts/', params))) + + def alerts_summary(self, baseurl=None): + """ + Gets number of alerts grouped by each risk level, optionally filtering by URL + """ + params = {} + if baseurl is not None: + params['baseurl'] = baseurl + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/alertsSummary/', params))) + + def number_of_alerts(self, baseurl=None, riskid=None): + """ + Gets the number of alerts, optionally filtering by URL or riskId + """ + params = {} + if baseurl is not None: + params['baseurl'] = baseurl + if riskid is not None: + params['riskId'] = riskid + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/numberOfAlerts/', params))) + @property def option_default_user_agent(self): """ @@ -253,6 +262,9 @@ def option_proxy_chain_user_name(self): @property def option_timeout_in_secs(self): + """ + Gets the connection time out, in seconds. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/view/optionTimeoutInSecs/'))) @property @@ -316,8 +328,16 @@ def save_session(self, name, overwrite=None, apikey=''): params['overwrite'] = overwrite return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/saveSession/', params))) - def snapshot_session(self, apikey=''): - return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/snapshotSession/', {'apikey': apikey}))) + def snapshot_session(self, name=None, overwrite=None, apikey=''): + """ + Snapshots the session, optionally with the given name, and overwriting existing files. If no name is specified the name of the current session with a timestamp appended is used. If a relative path is specified it will be resolved against the "session" directory in ZAP "home" dir. + """ + params = {'apikey': apikey} + if name is not None: + params['name'] = name + if overwrite is not None: + params['overwrite'] = overwrite + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/snapshotSession/', params))) def clear_excluded_from_proxy(self, apikey=''): """ @@ -355,18 +375,6 @@ def send_request(self, request, followredirects=None, apikey=''): params['followRedirects'] = followredirects return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/sendRequest/', params))) - def delete_all_alerts(self, apikey=''): - """ - Deletes all alerts of the current session. - """ - return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/deleteAllAlerts/', {'apikey': apikey}))) - - def delete_alert(self, id, apikey=''): - """ - Deletes the alert with the given ID. - """ - return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/deleteAlert/', {'id': id, 'apikey': apikey}))) - def run_garbage_collection(self, apikey=''): return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/runGarbageCollection/', {'apikey': apikey}))) @@ -444,6 +452,33 @@ def set_option_alert_overrides_file_path(self, filepath=None, apikey=''): params['filePath'] = filepath return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/setOptionAlertOverridesFilePath/', params))) + def enable_pkcs_12_client_certificate(self, filepath, password, index=None, apikey=''): + """ + Enables use of a PKCS12 client certificate for the certificate with the given file system path, password, and optional index. + """ + params = {'filePath': filepath, 'password': password, 'apikey': apikey} + if index is not None: + params['index'] = index + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/enablePKCS12ClientCertificate/', params))) + + def disable_client_certificate(self, apikey=''): + """ + Disables the option for use of client certificates. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/disableClientCertificate/', {'apikey': apikey}))) + + def delete_all_alerts(self, apikey=''): + """ + Deletes all alerts of the current session. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/deleteAllAlerts/', {'apikey': apikey}))) + + def delete_alert(self, id, apikey=''): + """ + Deletes the alert with the given ID. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/deleteAlert/', {'id': id, 'apikey': apikey}))) + def set_option_default_user_agent(self, string, apikey=''): """ Sets the user agent that ZAP should use when creating HTTP messages (for example, spider messages or CONNECT requests to outgoing proxy). @@ -487,6 +522,9 @@ def set_option_single_cookie_request_header(self, boolean, apikey=''): return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/setOptionSingleCookieRequestHeader/', {'Boolean': boolean, 'apikey': apikey}))) def set_option_timeout_in_secs(self, integer, apikey=''): + """ + Sets the connection time out, in seconds. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'core/action/setOptionTimeoutInSecs/', {'Integer': integer, 'apikey': apikey}))) def set_option_use_proxy_chain(self, boolean, apikey=''): diff --git a/src/zapv2/httpSessions.py b/src/zapv2/httpSessions.py index 10e3033..226c4fa 100644 --- a/src/zapv2/httpSessions.py +++ b/src/zapv2/httpSessions.py @@ -55,6 +55,13 @@ def session_tokens(self, site): """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'httpSessions/view/sessionTokens/', {'site': site}))) + @property + def default_session_tokens(self): + """ + Gets the default session tokens. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'httpSessions/view/defaultSessionTokens/'))) + def create_empty_session(self, site, session=None, apikey=''): """ Creates an empty session for the given site. Optionally with the given name. @@ -105,3 +112,24 @@ def rename_session(self, site, oldsessionname, newsessionname, apikey=''): Renames the session of the given site. """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'httpSessions/action/renameSession/', {'site': site, 'oldSessionName': oldsessionname, 'newSessionName': newsessionname, 'apikey': apikey}))) + + def add_default_session_token(self, sessiontoken, tokenenabled=None, apikey=''): + """ + Adds a default session token with the given name and enabled state. + """ + params = {'sessionToken': sessiontoken, 'apikey': apikey} + if tokenenabled is not None: + params['tokenEnabled'] = tokenenabled + return six.next(six.itervalues(self.zap._request(self.zap.base + 'httpSessions/action/addDefaultSessionToken/', params))) + + def set_default_session_token_enabled(self, sessiontoken, tokenenabled, apikey=''): + """ + Sets whether or not the default session token with the given name is enabled. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'httpSessions/action/setDefaultSessionTokenEnabled/', {'sessionToken': sessiontoken, 'tokenEnabled': tokenenabled, 'apikey': apikey}))) + + def remove_default_session_token(self, sessiontoken, apikey=''): + """ + Removes the default session token with the given name. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'httpSessions/action/removeDefaultSessionToken/', {'sessionToken': sessiontoken, 'apikey': apikey}))) diff --git a/src/zapv2/pscan.py b/src/zapv2/pscan.py index 5280e6c..cd8b158 100644 --- a/src/zapv2/pscan.py +++ b/src/zapv2/pscan.py @@ -48,6 +48,20 @@ def scanners(self): """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'pscan/view/scanners/'))) + @property + def current_rule(self): + """ + Show information about the passive scan rule currently being run (if any). + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'pscan/view/currentRule/'))) + + @property + def max_alerts_per_rule(self): + """ + Gets the maximum number of alerts a passive scan rule should raise. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'pscan/view/maxAlertsPerRule/'))) + def set_enabled(self, enabled, apikey=''): """ Sets whether or not the passive scanning is enabled (Note: the enabled state is not persisted). @@ -89,3 +103,9 @@ def set_scanner_alert_threshold(self, id, alertthreshold, apikey=''): Sets the alert threshold of the passive scanner with the given ID, accepted values for alert threshold: OFF, DEFAULT, LOW, MEDIUM and HIGH """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'pscan/action/setScannerAlertThreshold/', {'id': id, 'alertThreshold': alertthreshold, 'apikey': apikey}))) + + def set_max_alerts_per_rule(self, maxalerts, apikey=''): + """ + Sets the maximum number of alerts a passive scan rule should raise. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'pscan/action/setMaxAlertsPerRule/', {'maxAlerts': maxalerts, 'apikey': apikey}))) diff --git a/src/zapv2/script.py b/src/zapv2/script.py index 5a78725..c54d173 100644 --- a/src/zapv2/script.py +++ b/src/zapv2/script.py @@ -34,6 +34,13 @@ def list_engines(self): """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/view/listEngines/'))) + @property + def list_types(self): + """ + Lists the script types available. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/view/listTypes/'))) + @property def list_scripts(self): """ @@ -41,6 +48,31 @@ def list_scripts(self): """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/view/listScripts/'))) + def global_var(self, varkey): + """ + Gets the value of the global variable with the given key. Returns an API error (DOES_NOT_EXIST) if no value was previously set. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/view/globalVar/', {'varKey': varkey}))) + + @property + def global_vars(self): + """ + Gets all the global variables (key/value pairs). + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/view/globalVars/'))) + + def script_var(self, scriptname, varkey): + """ + Gets the value of the variable with the given key for the given script. Returns an API error (DOES_NOT_EXIST) if no script with the given name exists or if no value was previously set. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/view/scriptVar/', {'scriptName': scriptname, 'varKey': varkey}))) + + def script_vars(self, scriptname): + """ + Gets all the variables (key/value pairs) of the given script. Returns an API error (DOES_NOT_EXIST) if no script with the given name exists. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/view/scriptVars/', {'scriptName': scriptname}))) + def enable(self, scriptname, apikey=''): """ Enables the script with the given name @@ -72,6 +104,48 @@ def remove(self, scriptname, apikey=''): def run_stand_alone_script(self, scriptname, apikey=''): """ - Runs the stand alone script with the give name + Runs the stand alone script with the given name """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/action/runStandAloneScript/', {'scriptName': scriptname, 'apikey': apikey}))) + + def clear_global_var(self, varkey, apikey=''): + """ + Clears the global variable with the given key. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/action/clearGlobalVar/', {'varKey': varkey, 'apikey': apikey}))) + + def clear_global_vars(self, apikey=''): + """ + Clears the global variables. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/action/clearGlobalVars/', {'apikey': apikey}))) + + def clear_script_var(self, scriptname, varkey, apikey=''): + """ + Clears the variable with the given key of the given script. Returns an API error (DOES_NOT_EXIST) if no script with the given name exists. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/action/clearScriptVar/', {'scriptName': scriptname, 'varKey': varkey, 'apikey': apikey}))) + + def clear_script_vars(self, scriptname, apikey=''): + """ + Clears the variables of the given script. Returns an API error (DOES_NOT_EXIST) if no script with the given name exists. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/action/clearScriptVars/', {'scriptName': scriptname, 'apikey': apikey}))) + + def set_script_var(self, scriptname, varkey, varvalue=None, apikey=''): + """ + Sets the value of the variable with the given key of the given script. Returns an API error (DOES_NOT_EXIST) if no script with the given name exists. + """ + params = {'scriptName': scriptname, 'varKey': varkey, 'apikey': apikey} + if varvalue is not None: + params['varValue'] = varvalue + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/action/setScriptVar/', params))) + + def set_global_var(self, varkey, varvalue=None, apikey=''): + """ + Sets the value of the global variable with the given key. + """ + params = {'varKey': varkey, 'apikey': apikey} + if varvalue is not None: + params['varValue'] = varvalue + return six.next(six.itervalues(self.zap._request(self.zap.base + 'script/action/setGlobalVar/', params))) diff --git a/src/zapv2/search.py b/src/zapv2/search.py index b722dd1..ca0c92c 100644 --- a/src/zapv2/search.py +++ b/src/zapv2/search.py @@ -28,6 +28,9 @@ def __init__(self, zap): self.zap = zap def urls_by_url_regex(self, regex, baseurl=None, start=None, count=None): + """ + Returns the URLs of the HTTP messages that match the given regular expression in the URL optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex} if baseurl is not None: params['baseurl'] = baseurl @@ -38,6 +41,9 @@ def urls_by_url_regex(self, regex, baseurl=None, start=None, count=None): return six.next(six.itervalues(self.zap._request(self.zap.base + 'search/view/urlsByUrlRegex/', params))) def urls_by_request_regex(self, regex, baseurl=None, start=None, count=None): + """ + Returns the URLs of the HTTP messages that match the given regular expression in the request optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex} if baseurl is not None: params['baseurl'] = baseurl @@ -48,6 +54,9 @@ def urls_by_request_regex(self, regex, baseurl=None, start=None, count=None): return six.next(six.itervalues(self.zap._request(self.zap.base + 'search/view/urlsByRequestRegex/', params))) def urls_by_response_regex(self, regex, baseurl=None, start=None, count=None): + """ + Returns the URLs of the HTTP messages that match the given regular expression in the response optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex} if baseurl is not None: params['baseurl'] = baseurl @@ -58,6 +67,9 @@ def urls_by_response_regex(self, regex, baseurl=None, start=None, count=None): return six.next(six.itervalues(self.zap._request(self.zap.base + 'search/view/urlsByResponseRegex/', params))) def urls_by_header_regex(self, regex, baseurl=None, start=None, count=None): + """ + Returns the URLs of the HTTP messages that match the given regular expression in the header(s) optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex} if baseurl is not None: params['baseurl'] = baseurl @@ -68,6 +80,9 @@ def urls_by_header_regex(self, regex, baseurl=None, start=None, count=None): return six.next(six.itervalues(self.zap._request(self.zap.base + 'search/view/urlsByHeaderRegex/', params))) def messages_by_url_regex(self, regex, baseurl=None, start=None, count=None): + """ + Returns the HTTP messages that match the given regular expression in the URL optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex} if baseurl is not None: params['baseurl'] = baseurl @@ -78,6 +93,9 @@ def messages_by_url_regex(self, regex, baseurl=None, start=None, count=None): return six.next(six.itervalues(self.zap._request(self.zap.base + 'search/view/messagesByUrlRegex/', params))) def messages_by_request_regex(self, regex, baseurl=None, start=None, count=None): + """ + Returns the HTTP messages that match the given regular expression in the request optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex} if baseurl is not None: params['baseurl'] = baseurl @@ -88,6 +106,9 @@ def messages_by_request_regex(self, regex, baseurl=None, start=None, count=None) return six.next(six.itervalues(self.zap._request(self.zap.base + 'search/view/messagesByRequestRegex/', params))) def messages_by_response_regex(self, regex, baseurl=None, start=None, count=None): + """ + Returns the HTTP messages that match the given regular expression in the response optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex} if baseurl is not None: params['baseurl'] = baseurl @@ -98,6 +119,9 @@ def messages_by_response_regex(self, regex, baseurl=None, start=None, count=None return six.next(six.itervalues(self.zap._request(self.zap.base + 'search/view/messagesByResponseRegex/', params))) def messages_by_header_regex(self, regex, baseurl=None, start=None, count=None): + """ + Returns the HTTP messages that match the given regular expression in the header(s) optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex} if baseurl is not None: params['baseurl'] = baseurl @@ -108,6 +132,9 @@ def messages_by_header_regex(self, regex, baseurl=None, start=None, count=None): return six.next(six.itervalues(self.zap._request(self.zap.base + 'search/view/messagesByHeaderRegex/', params))) def har_by_url_regex(self, regex, baseurl=None, start=None, count=None, apikey=''): + """ + Returns the HTTP messages, in HAR format, that match the given regular expression in the URL optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex, 'apikey': apikey} if baseurl is not None: params['baseurl'] = baseurl @@ -118,6 +145,9 @@ def har_by_url_regex(self, regex, baseurl=None, start=None, count=None, apikey=' return (self.zap._request_other(self.zap.base_other + 'search/other/harByUrlRegex/', params)) def har_by_request_regex(self, regex, baseurl=None, start=None, count=None, apikey=''): + """ + Returns the HTTP messages, in HAR format, that match the given regular expression in the request optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex, 'apikey': apikey} if baseurl is not None: params['baseurl'] = baseurl @@ -128,6 +158,9 @@ def har_by_request_regex(self, regex, baseurl=None, start=None, count=None, apik return (self.zap._request_other(self.zap.base_other + 'search/other/harByRequestRegex/', params)) def har_by_response_regex(self, regex, baseurl=None, start=None, count=None, apikey=''): + """ + Returns the HTTP messages, in HAR format, that match the given regular expression in the response optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex, 'apikey': apikey} if baseurl is not None: params['baseurl'] = baseurl @@ -138,6 +171,9 @@ def har_by_response_regex(self, regex, baseurl=None, start=None, count=None, api return (self.zap._request_other(self.zap.base_other + 'search/other/harByResponseRegex/', params)) def har_by_header_regex(self, regex, baseurl=None, start=None, count=None, apikey=''): + """ + Returns the HTTP messages, in HAR format, that match the given regular expression in the header(s) optionally filtered by URL and paginated with 'start' position and 'count' of messages. + """ params = {'regex': regex, 'apikey': apikey} if baseurl is not None: params['baseurl'] = baseurl diff --git a/src/zapv2/sessionManagement.py b/src/zapv2/sessionManagement.py index 314e031..ba9f58b 100644 --- a/src/zapv2/sessionManagement.py +++ b/src/zapv2/sessionManagement.py @@ -29,15 +29,27 @@ def __init__(self, zap): @property def get_supported_session_management_methods(self): + """ + Gets the name of the session management methods. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'sessionManagement/view/getSupportedSessionManagementMethods/'))) def get_session_management_method_config_params(self, methodname): + """ + Gets the configuration parameters for the session management method with the given name. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'sessionManagement/view/getSessionManagementMethodConfigParams/', {'methodName': methodname}))) def get_session_management_method(self, contextid): + """ + Gets the name of the session management method for the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'sessionManagement/view/getSessionManagementMethod/', {'contextId': contextid}))) def set_session_management_method(self, contextid, methodname, methodconfigparams=None, apikey=''): + """ + Sets the session management method for the context with the given ID. + """ params = {'contextId': contextid, 'methodName': methodname, 'apikey': apikey} if methodconfigparams is not None: params['methodConfigParams'] = methodconfigparams diff --git a/src/zapv2/spider.py b/src/zapv2/spider.py index daacdd0..25d34d8 100644 --- a/src/zapv2/spider.py +++ b/src/zapv2/spider.py @@ -103,6 +103,9 @@ def option_max_children(self): @property def option_max_depth(self): + """ + Gets the maximum depth the spider can crawl, 0 if unlimited. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'spider/view/optionMaxDepth/'))) @property @@ -338,6 +341,9 @@ def set_option_max_children(self, integer, apikey=''): return six.next(six.itervalues(self.zap._request(self.zap.base + 'spider/action/setOptionMaxChildren/', {'Integer': integer, 'apikey': apikey}))) def set_option_max_depth(self, integer, apikey=''): + """ + Sets the maximum depth the spider can crawl, 0 for unlimited depth. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'spider/action/setOptionMaxDepth/', {'Integer': integer, 'apikey': apikey}))) def set_option_max_duration(self, integer, apikey=''): diff --git a/src/zapv2/users.py b/src/zapv2/users.py index b8bfcf6..b360ae3 100644 --- a/src/zapv2/users.py +++ b/src/zapv2/users.py @@ -28,38 +28,60 @@ def __init__(self, zap): self.zap = zap def users_list(self, contextid=None): + """ + Gets a list of users that belong to the context with the given ID, or all users if none provided. + """ params = {} if contextid is not None: params['contextId'] = contextid return six.next(six.itervalues(self.zap._request(self.zap.base + 'users/view/usersList/', params))) - def get_user_by_id(self, contextid=None, userid=None): - params = {} - if contextid is not None: - params['contextId'] = contextid - if userid is not None: - params['userId'] = userid - return six.next(six.itervalues(self.zap._request(self.zap.base + 'users/view/getUserById/', params))) + def get_user_by_id(self, contextid, userid): + """ + Gets the data of the user with the given ID that belongs to the context with the given ID. + """ + return six.next(six.itervalues(self.zap._request(self.zap.base + 'users/view/getUserById/', {'contextId': contextid, 'userId': userid}))) def get_authentication_credentials_config_params(self, contextid): + """ + Gets the configuration parameters for the credentials of the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'users/view/getAuthenticationCredentialsConfigParams/', {'contextId': contextid}))) def get_authentication_credentials(self, contextid, userid): + """ + Gets the authentication credentials of the user with given ID that belongs to the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'users/view/getAuthenticationCredentials/', {'contextId': contextid, 'userId': userid}))) def new_user(self, contextid, name, apikey=''): + """ + Creates a new user with the given name for the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'users/action/newUser/', {'contextId': contextid, 'name': name, 'apikey': apikey}))) def remove_user(self, contextid, userid, apikey=''): + """ + Removes the user with the given ID that belongs to the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'users/action/removeUser/', {'contextId': contextid, 'userId': userid, 'apikey': apikey}))) def set_user_enabled(self, contextid, userid, enabled, apikey=''): + """ + Sets whether or not the user, with the given ID that belongs to the context with the given ID, should be enabled. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'users/action/setUserEnabled/', {'contextId': contextid, 'userId': userid, 'enabled': enabled, 'apikey': apikey}))) def set_user_name(self, contextid, userid, name, apikey=''): + """ + Renames the user with the given ID that belongs to the context with the given ID. + """ return six.next(six.itervalues(self.zap._request(self.zap.base + 'users/action/setUserName/', {'contextId': contextid, 'userId': userid, 'name': name, 'apikey': apikey}))) def set_authentication_credentials(self, contextid, userid, authcredentialsconfigparams=None, apikey=''): + """ + Sets the authentication credentials for the user with the given ID that belongs to the context with the given ID. + """ params = {'contextId': contextid, 'userId': userid, 'apikey': apikey} if authcredentialsconfigparams is not None: params['authCredentialsConfigParams'] = authcredentialsconfigparams