scanners/zap-advanced/scanner/zapclient/context/zap_context_authentication.py
#!/usr/bin/env python
# SPDX-FileCopyrightText: the secureCodeBox authors
#
# SPDX-License-Identifier: Apache-2.0
# -*- coding: utf-8 -*-
import collections
import logging
from zapv2 import ZAPv2
from .. import ZapClient
from ..configuration import ZapConfiguration
# set up logging to file - see previous section for more details
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(name)-12s %(levelname)-8s: %(message)s",
datefmt="%Y-%m-%d %H:%M",
)
logging = logging.getLogger("ZapConfigureContextAuthentication")
class ZapConfigureContextAuthentication(ZapClient):
"""This class configures the context in running ZAP instance, based on a given ZAP Configuration."""
def __init__(self, zap: ZAPv2, config: ZapConfiguration):
"""Initial constructor used for this class
Parameters
----------
zap : ZAPv2
The running ZAP instance to configure.
config : ZapConfiguration
The configuration object containing all ZAP configs (based on the class ZapConfiguration).
"""
super().__init__(zap, config)
def configure_context_authentication(
self, context: collections.OrderedDict, context_id: int
):
"""Protected method to configure the ZAP 'Context / Authentication Settings' based on a given ZAP config.
Parameters
----------
context: collections.OrderedDict
The current configuration object containing the ZAP authentication configuration (based on the class ZapConfiguration).
context_id : int
The zap context id tot configure the ZAP authentication for (based on the class ZapConfiguration).
"""
authentication = context["authentication"]
auth_type = authentication["type"]
if auth_type == "script-based" and "script-based" in authentication:
self._configure_context_authentication_script(
authentication["script-based"], context_id
)
elif auth_type == "basic-auth" and "basic-auth" in authentication:
self._configure_context_authentication_basic_auth(
authentication["basic-auth"], context_id
)
elif auth_type == "form-based" and "form-based" in authentication:
self._configure_context_authentication_form_auth(
authentication["form-based"], context_id
)
elif auth_type == "json-based" and "json-based" in authentication:
self._configure_context_authentication_json_auth(
authentication["json-based"], context_id
)
if self._is_not_empty("verification", authentication):
self._configure_auth_validation(authentication["verification"], context_id)
def _configure_context_authentication_script(
self, script_config: collections.OrderedDict, context_id: int
):
"""Protected method to configure the ZAP 'Context / Authentication Settings with Script based Authentication' based on a given ZAP config.
Parameters
----------
script_config : collections.OrderedDict
The current 'script-based' authentication configuration object containing the ZAP authentication configuration (based on the class ZapConfiguration).
context_id : int
The zap context id tot configure the ZAP authentication for (based on the class ZapConfiguration).
"""
if (
not script_config == None
and "name" in script_config
and "filePath" in script_config
and "engine" in script_config
):
self._configure_load_script(
script_config=script_config, script_type="authentication"
)
auth_params = self.__get_script_auth_params(script_config)
# Add additional script parameters
logging.debug("Loading Authentication Script Parameters: %s", auth_params)
self.check_zap_result(
result=self.get_zap.authentication.set_authentication_method(
contextid=context_id,
authmethodname="scriptBasedAuthentication",
authmethodconfigparams=auth_params,
),
method_name="set_authentication_method",
exception_message="Missing ZAP Authentication Script Parameters! Please check your secureCodeBox YAML configuration!",
)
else:
logging.warning(
"Important script authentication configs (name, filePath, engine) are missing! Ignoring the authentication script configuration. Please check your YAML configuration."
)
def _configure_context_authentication_basic_auth(
self, basic_auth: collections.OrderedDict, context_id: int
):
"""Protected method to configure the ZAP 'Context / Authentication Settings with Basic Authentication' based on a given ZAP config.
Parameters
----------
basic_auth : collections.OrderedDict
The current 'basic-auth' authentication configuration object containing the ZAP authentication configuration (based on the class ZapConfiguration).
context_id : int
The zap context id tot configure the ZAP authentication for (based on the class ZapConfiguration).
"""
logging.debug("Enabling ZAP HTTP Basic Auth")
if "hostname" in basic_auth:
auth_method_config_params = "hostname=" + basic_auth["hostname"]
if "realm" in basic_auth:
auth_method_config_params += "&realm=" + basic_auth["realm"]
if "port" in basic_auth:
auth_method_config_params += "&port=" + str(basic_auth["port"])
logging.info("HTTP BasicAuth Params: '%s'", auth_method_config_params)
self.get_zap.authentication.set_authentication_method(
contextid=context_id,
authmethodname="httpAuthentication",
authmethodconfigparams=auth_method_config_params,
)
def _configure_context_authentication_form_auth(
self, form_auth: collections.OrderedDict, context_id: int
):
"""Protected method to configure the ZAP 'Context / Authentication Settings with Form Authentication' based on a given ZAP config.
Parameters
----------
form_auth : collections.OrderedDict
The current 'form-auth' authentication configuration object containing the ZAP authentication configuration (based on the class ZapConfiguration).
context_id : int
The zap context id tot configure the ZAP authentication for (based on the class ZapConfiguration).
"""
logging.debug("Enabling ZAP HTTP Form based Authentication")
if "loginUrl" in form_auth:
auth_method_config_params = "loginUrl=" + form_auth["loginUrl"]
if "loginRequestData" in form_auth:
auth_method_config_params += (
"&loginRequestData=" + form_auth["loginRequestData"]
)
logging.debug("HTTP ZAP HTTP Form Params: '%s'", auth_method_config_params)
self.get_zap.authentication.set_authentication_method(
contextid=context_id,
authmethodname="formBasedAuthentication",
authmethodconfigparams=auth_method_config_params,
)
def _configure_context_authentication_json_auth(
self, json_auth: collections.OrderedDict, context_id: int
):
"""Protected method to configure the ZAP 'Context / Authentication Settings with JSON Authentication' based on a given ZAP config.
Parameters
----------
json_auth : collections.OrderedDict
The current 'json-auth' authentication configuration object containing the ZAP authentication configuration (based on the class ZapConfiguration).
context_id : int
The zap context id tot configure the ZAP authentication for (based on the class ZapConfiguration).
"""
logging.debug("Enabling ZAP HTTP JSON based Authentication")
if "loginUrl" in json_auth:
auth_method_config_params = "loginUrl=" + json_auth["loginUrl"]
if "loginRequestData" in json_auth:
auth_method_config_params += (
"&loginRequestData=" + json_auth["loginRequestData"]
)
logging.debug("HTTP ZAP HTTP JSON Params: '%s'", auth_method_config_params)
self.get_zap.authentication.set_authentication_method(
contextid=context_id,
authmethodname="jsonBasedAuthentication",
authmethodconfigparams=auth_method_config_params,
)
def _configure_auth_validation(
self, validation: collections.OrderedDict, context_id: int
):
"""Protected method to configure the ZAP 'Context / Authentication Settings with Script based Authentication' based on a given ZAP config.
Parameters
----------
validation : collections.OrderedDict
The current 'script-based' authentication configuration object containing the ZAP authentication configuration (based on the class ZapConfiguration).
context_id : int
The zap context id tot configure the ZAP authentication for (based on the class ZapConfiguration).
"""
logging.debug("Configure Authentication Validation: %s", validation)
if "isLoggedInIndicator" in validation:
self.get_zap.authentication.set_logged_in_indicator(
contextid=context_id,
loggedinindicatorregex=validation["isLoggedInIndicator"],
)
if "isLoggedOutIndicator" in validation:
self.get_zap.authentication.set_logged_out_indicator(
contextid=context_id,
loggedoutindicatorregex=validation["isLoggedOutIndicator"],
)
def __get_script_auth_params(self, script_config: collections.OrderedDict) -> list:
"""Protected method to configure the ZAP 'Context / Authentication Settings with JSON Authentication' based on a given ZAP config.
Parameters
----------
json_auth : collections.OrderedDict
The current 'json-auth' authentication configuration object containing the ZAP authentication configuration (based on the class ZapConfiguration).
context_id : int
The zap context id tot configure the ZAP authentication for (based on the class ZapConfiguration).
"""
# Create ZAP Script parameters based on given configuration object
auth_params = [
"scriptName=" + script_config["name"],
]
# Creates a list of URL-Encoded params, based on the YAML config
for key, value in script_config["arguments"].items():
auth_params.append(key + "=" + value)
# Add a '&' to all elements except the last one
auth_params = "&".join(auth_params)
return auth_params