"""JSON-L parser plugin for Azure application gateway access log files."""

from dfdatetime import time_elements as dfdatetime_time_elements

from plaso.containers import events
from plaso.parsers import jsonl_parser
from plaso.parsers.jsonl_plugins import interface


class AzureApplicationGatewayAccessEventData(events.EventData):
    """Azure application gateway access log event data.

    Attributes:
      client_ip (str): Client IP address of the request.
      client_port (int): Client TCP/UDP port for the request.
      client_response_time (int): Duration, in seconds, from the first byte of
          a client request to be processed up to the first byte sent as response
          to the client.
      http_method (str): HTTP method used by the request.
      http_status (int): HTTP status code returned to the client from application
          gateway.
      http_version (str): HTTP version of the request.
      instance_identifier (str): Application gateway instance that served
          the request.
      original_request_host (str): Original IP address or name of the requested host.
      original_request_uri (str): Original request URL, including arguments.
      received_bytes (int): Size of packet received, in bytes.
      recorded_time (dfdatetime.DateTimeValues): date and time the log entry
          was recorded.
      request_query (str): Server-Routed: Back-end pool instance that was sent
          the request. X-AzureApplicationGateway-LOG-ID: Correlation ID used for
          the request. It can be used to troubleshoot traffic issues on
          the back-end servers. SERVER-STATUS: HTTP response code that application
          gateway received from the back-end.
      request_uri (str): URI of the received request.
      request_host (str): IP address or name fo the requested host as listed in the
          x-original-host header, which could have been changed by a reverse proxy.
      sent_bytes (int): Size of packet sent, in bytes.
      server_response_latency (str): Latency of the response (in seconds) from
          the back-end server.
      server_routed (str): The back-end server that application gateway routes
          the request to.
      server_status (str): HTTP status code of the back-end server.
      ssl_cipher (str): Cipher suite being used for TLS communication.
      ssl_client_certificate_fingerprint (str): Fingerprint of the SSL client
          certificate.
      ssl_client_certificate_issuer_name (str): Name of the issuer of the SSL
          client certificate.
      ssl_client_verify (str): TODO.
      ssl_enabled (str): Whether communication to the back-end pools used TLS.
          Valid values are on and off.
      ssl_protocol (str): The SSL/TLS protocol used.
      time_taken (double): Duration, in seconds, that it takes for the first byte
          of a client request to be processed and its last-byte sent in
          the response to the client. It's important to note that the Time-Taken
          field usually includes the time that the request and response packets
          are traveling over the network.
      transaction_id (str): Unique identifier to correlate the request received
          from the client
      user_agent (str): User agent from the HTTP request header.
      waf_evaluation_time (str): Duration, in seconds, that it takes for
          the request to be processed by the WAF.
      waf_mode (str): Value can be either Detection or Prevention.
    """

    DATA_TYPE = "azure:application_gateway_access:entry"

    def __init__(self):
        """Initializes event data."""
        super().__init__(data_type=self.DATA_TYPE)
        self.client_ip = None
        self.client_port = None
        self.client_response_time = None
        self.http_method = None
        self.http_status = None
        self.http_version = None
        self.instance_identifier = None
        self.original_request_host = None
        self.original_request_uri = None
        self.received_bytes = None
        self.recorded_time = None
        self.request_host = None
        self.request_query = None
        self.request_uri = None
        self.sent_bytes = None
        self.server_response_latency = None
        self.server_routed = None
        self.server_status = None
        self.ssl_cipher = None
        self.ssl_client_certificate_fingerprint = None
        self.ssl_client_certificate_issuer_name = None
        self.ssl_client_verify = None
        self.ssl_enabled = None
        self.ssl_protocol = None
        self.time_taken = None
        self.transaction_identifier = None
        self.user_agent = None
        self.waf_evaluation_time = None
        self.waf_mode = None


class AzureApplicationGatewayAccessLogJSONLPlugin(interface.JSONLPlugin):
    """JSON-L parser plugin for Azure application gateway access log files."""

    NAME = "azure_application_gateway_access_log"
    DATA_FORMAT = "Azure Application Gateway access log"

    def _ParseRecord(self, parser_mediator, json_dict):
        """Parses an Azure application gateway access log record.

        Args:
          parser_mediator (ParserMediator): mediates interactions between parsers and
              other components, such as storage and dfVFS.
          json_dict (dict): JSON dictionary of the log record.
        """
        properties_json_dict = self._GetJSONValue(
            json_dict, "properties", default_value={}
        )
        date_time, corrupted = self._ParseISO8601DateTimeString(
            parser_mediator, json_dict, "timeStamp"
        )
        event_data = AzureApplicationGatewayAccessEventData()
        event_data.client_ip = self._GetJSONValue(properties_json_dict, "clientIP")
        event_data.client_port = self._GetJSONValue(properties_json_dict, "clientPort")
        event_data.client_response_time = self._GetJSONValue(
            properties_json_dict, "clientResponseTime"
        )
        event_data.request_host = self._GetJSONValue(properties_json_dict, "host")
        event_data.http_method = self._GetJSONValue(properties_json_dict, "httpMethod")
        event_data.http_status = self._GetJSONValue(properties_json_dict, "httpStatus")
        event_data.http_version = self._GetJSONValue(
            properties_json_dict, "httpVersion"
        )
        event_data.instance_identifier = self._GetJSONValue(
            properties_json_dict, "instanceId"
        )
        event_data.original_request_host = self._GetJSONValue(
            properties_json_dict, "originalHost"
        )
        event_data.original_request_uri = self._GetJSONValue(
            properties_json_dict, "originalRequestUriWithArgs"
        )
        event_data.received_bytes = self._GetJSONValue(
            properties_json_dict, "receivedBytes"
        )
        event_data.recorded_time = date_time
        event_data.request_query = self._GetJSONValue(
            properties_json_dict, "requestQuery"
        )
        event_data.request_uri = self._GetJSONValue(properties_json_dict, "requestUri")
        event_data.sent_bytes = self._GetJSONValue(properties_json_dict, "sentBytes")
        event_data.server_response_latency = self._GetJSONValue(
            properties_json_dict, "serverResponseLatency"
        )
        event_data.server_routed = self._GetJSONValue(
            properties_json_dict, "serverRouted"
        )
        event_data.server_status = self._GetJSONValue(
            properties_json_dict, "serverStatus"
        )
        event_data.ssl_cipher = self._GetJSONValue(properties_json_dict, "sslCipher")
        event_data.ssl_client_certificate_fingerprint = self._GetJSONValue(
            properties_json_dict, "sslClientCertificateFingerprint"
        )
        event_data.ssl_client_certificate_issuer_name = self._GetJSONValue(
            properties_json_dict, "sslClientCertificateIssuerName"
        )
        event_data.ssl_client_verify = self._GetJSONValue(
            properties_json_dict, "sslClientVerify"
        )
        event_data.ssl_enabled = self._GetJSONValue(properties_json_dict, "sslEnabled")
        event_data.ssl_protocol = self._GetJSONValue(
            properties_json_dict, "sslProtocol"
        )
        event_data.time_taken = self._GetJSONValue(properties_json_dict, "timeTaken")
        event_data.transaction_identifier = self._GetJSONValue(
            properties_json_dict, "transactionId"
        )
        event_data.user_agent = self._GetJSONValue(properties_json_dict, "userAgent")
        event_data.waf_evaluation_time = self._GetJSONValue(
            properties_json_dict, "WAFEvaluationTime"
        )
        event_data.waf_mode = self._GetJSONValue(properties_json_dict, "WAFMode")

        parser_mediator.ProduceEventData(event_data, corrupted=corrupted)

    def CheckRequiredFormat(self, json_dict):
        """Check if the log record has the minimal structure required by the plugin.

        Args:
          json_dict (dict): JSON dictionary of the log record.

        Returns:
          bool: True if this is the correct parser, False otherwise.
        """
        operation_name = self._GetJSONValue(json_dict, "operationName")
        properties = self._GetJSONValue(json_dict, "properties")
        iso8601_string = self._GetJSONValue(json_dict, "timeStamp")

        if (
            None in (operation_name, properties, iso8601_string)
            or operation_name != "ApplicationGatewayAccess"
        ):
            return False

        date_time = dfdatetime_time_elements.TimeElementsInMicroseconds()

        try:
            date_time.CopyFromStringISO8601(iso8601_string)
        except ValueError:
            return False

        return True


jsonl_parser.JSONLParser.RegisterPlugin(AzureApplicationGatewayAccessLogJSONLPlugin)
