from __future__ import unicode_literals
from __future__ import print_function

import json
import re
import unittest

from mock import Mock, ANY, patch

from tcell_agent.appsensor.meta import AppSensorMeta
from tcell_agent.appsensor.params import GET_PARAM
from tcell_agent.config import CONFIGURATION
from tcell_agent.policies.appsensor.payloads_policy import PayloadsPolicy


class PayloadsPolicyTest(unittest.TestCase):

    def false_log_payloads_log_test(self):
        policy_json = { "payloads": {"log_payloads": False} }
        policy = PayloadsPolicy()
        policy.from_json(policy_json)
        meta = AppSensorMeta(
            "remote_addr",
            "request_method",
            "abosolute_uri",
            "23947",
            session_id="session_id",
            user_id="user_id"
        )

        old_allow = CONFIGURATION.log_appfirewall_events
        CONFIGURATION.log_appfirewall_events = False

        with patch("tcell_agent.policies.appsensor.payloads_policy.get_payloads_logger") as patched_get_payloadds_logger:
            policy.log("xss", meta, GET_PARAM, "password", "123password123", {"l": "query"}, "pattern")

            CONFIGURATION.log_appfirewall_events = old_allow

            self.assertFalse(patched_get_payloadds_logger.called)

    def true_log_payloads_false_log_appfirewall_events_log_test(self):
        policy_json = { "payloads": {"log_payloads": True} }
        policy = PayloadsPolicy()
        policy.from_json(policy_json)
        meta = AppSensorMeta(
            "remote_addr",
            "request_method",
            "abosolute_uri",
            "23947",
            session_id="session_id",
            user_id="user_id"
        )

        old_allow = CONFIGURATION.log_appfirewall_events
        CONFIGURATION.log_appfirewall_events = False

        with patch("tcell_agent.policies.appsensor.payloads_policy.get_payloads_logger") as patched_get_payloadds_logger:
            policy.log("xss", meta, GET_PARAM, "password", "123password123", {"l": "query"}, "pattern")

            CONFIGURATION.log_appfirewall_events = old_allow

            self.assertFalse(patched_get_payloadds_logger.called)

    def true_log_payloads_true_log_appfirewall_events_no_blacklist_no_whitelist_log_test(self):
        policy_json = { "payloads": {"log_payloads": True} }
        policy = PayloadsPolicy()
        policy.from_json(policy_json)
        meta = AppSensorMeta(
            "remote_addr",
            "request_method",
            "abosolute_uri",
            "23947",
            session_id="session_id",
            user_id="user_id"
        )

        old_allow = CONFIGURATION.log_appfirewall_events
        CONFIGURATION.log_appfirewall_events = True

        with patch("tcell_agent.policies.appsensor.payloads_policy.get_payloads_logger") as patched_get_payloadds_logger:
            policy.log("xss", meta, GET_PARAM, "password", "123password123", {"l": "query"}, "pattern")

            CONFIGURATION.log_appfirewall_events = old_allow

            self.assertFalse(patched_get_payloadds_logger.called)

    def true_log_payloads_true_log_appfirewall_events_no_blacklist_with_whitelist_missing_param_log_test(self):
        policy_json = { "payloads": {"log_payloads": True, "log_whitelist": {"username": ["*"]}} }
        policy = PayloadsPolicy()
        policy.from_json(policy_json)
        meta = AppSensorMeta(
            "remote_addr",
            "request_method",
            "abosolute_uri",
            "23947",
            session_id="session_id",
            user_id="user_id"
        )

        old_allow = CONFIGURATION.log_appfirewall_events
        CONFIGURATION.log_appfirewall_events = True

        with patch("tcell_agent.policies.appsensor.payloads_policy.get_payloads_logger") as patched_get_payloadds_logger:
            policy.log("xss", meta, GET_PARAM, "password", "123password123", {"l": "query"}, "pattern")

            CONFIGURATION.log_appfirewall_events = old_allow

            self.assertFalse(patched_get_payloadds_logger.called)

    def true_log_payloads_true_log_appfirewall_events_no_blacklist_param_in_whitelist_but_incorrect_location_log_test(self):
        policy_json = {
            "payloads": {
                "log_payloads": True,
                "log_whitelist": {
                    "username": ["*"],
                    "password": ["cookie"]
                }
            }
        }
        policy = PayloadsPolicy()
        policy.from_json(policy_json)
        meta = AppSensorMeta(
            "remote_addr",
            "request_method",
            "abosolute_uri",
            "23947",
            session_id="session_id",
            user_id="user_id"
        )

        old_allow = CONFIGURATION.log_appfirewall_events
        CONFIGURATION.log_appfirewall_events = True

        with patch("tcell_agent.policies.appsensor.payloads_policy.get_payloads_logger") as patched_get_payloadds_logger:
            policy.log("xss", meta, GET_PARAM, "password", "123password123", {"l": "query"}, "pattern")

            CONFIGURATION.log_appfirewall_events = old_allow

            self.assertFalse(patched_get_payloadds_logger.called)

    def true_log_payloads_true_log_appfirewall_events_no_blacklist_param_in_whitelist_log_test(self):
        policy_json = {
            "payloads": {
                "log_payloads": True,
                "log_whitelist": {
                    "username": ["*"],
                    "password": ["form"]
                }
            }
        }
        policy = PayloadsPolicy()
        policy.from_json(policy_json)
        meta = AppSensorMeta(
            "remote_addr",
            "request_method",
            "abosolute_uri",
            "23947",
            session_id="session_id",
            user_id="user_id"
        )

        old_allow = CONFIGURATION.log_appfirewall_events
        CONFIGURATION.log_appfirewall_events = True

        with patch("tcell_agent.policies.appsensor.payloads_policy.get_payloads_logger") as patched_get_payloadds_logger:
            policy.log("xss", meta, GET_PARAM, "password", "123password123", {"l": "query"}, "pattern")

            CONFIGURATION.log_appfirewall_events = old_allow

            self.assertFalse(patched_get_payloadds_logger.called)

    def true_log_payloads_true_log_appfirewall_events_no_whitelist_with_blacklist_missing_param_log_test(self):
        policy_json = { "payloads": {"log_payloads": True, "log_blacklist": {"username": ["*"]}} }
        policy = PayloadsPolicy()
        policy.from_json(policy_json)
        meta = AppSensorMeta(
            "remote_addr",
            "request_method",
            "abosolute_uri",
            "23947",
            session_id="session_id",
            user_id="user_id"
        )

        old_allow = CONFIGURATION.log_appfirewall_events
        CONFIGURATION.log_appfirewall_events = True

        mock_logger = Mock()
        with patch("tcell_agent.policies.appsensor.payloads_policy.get_payloads_logger", return_value=mock_logger) as patched_get_payloadds_logger:
            policy.log("xss", meta, GET_PARAM, "password", "123password123", {"l": "query"}, "pattern")

            CONFIGURATION.log_appfirewall_events = old_allow

            patched_get_payloadds_logger.assert_called_once_with()

            mock_logger.info.assert_called_once_with(ANY)
            call_args, call_kwargs = mock_logger.info.call_args
            self.assertEqual(json.loads(call_args[0]), {
                "event_type": "as",
                "remote_addr": "remote_addr",
                "pattern": "pattern",
                "m": "request_method",
                "param": "password",
                "meta": {"l": "query"},
                "sid": "session_id",
                "rid": "23947",
                "payload": "123password123",
                "dp": "xss",
                "uid": "user_id"
            })

    def true_log_payloads_true_log_appfirewall_events_no_whitelist_param_in_blacklist_but_incorrect_location_log_test(self):
        policy_json = {
            "payloads": {
                "log_payloads": True,
                "log_blacklist": {
                    "username": ["*"],
                    "password": ["cookie"]
                }
            }
        }
        policy = PayloadsPolicy()
        policy.from_json(policy_json)
        meta = AppSensorMeta(
            "remote_addr",
            "request_method",
            "abosolute_uri",
            "23947",
            session_id="session_id",
            user_id="user_id"
        )

        old_allow = CONFIGURATION.log_appfirewall_events
        CONFIGURATION.log_appfirewall_events = True

        mock_logger = Mock()
        with patch("tcell_agent.policies.appsensor.payloads_policy.get_payloads_logger", return_value=mock_logger) as patched_get_payloadds_logger:
            policy.log("xss", meta, GET_PARAM, "password", "123password123", {"l": "query"}, "pattern")

            CONFIGURATION.log_appfirewall_events = old_allow

            patched_get_payloadds_logger.assert_called_once_with()

            mock_logger.info.assert_called_once_with(ANY)
            call_args, call_kwargs = mock_logger.info.call_args
            self.assertEqual(json.loads(call_args[0]), {
                "event_type": "as",
                "remote_addr": "remote_addr",
                "pattern": "pattern",
                "m": "request_method",
                "param": "password",
                "meta": {"l": "query"},
                "sid": "session_id",
                "rid": "23947",
                "payload": "123password123",
                "dp": "xss",
                "uid": "user_id"
            })

    def true_log_payloads_true_log_appfirewall_events_no_whitelist_param_in_blacklist_log_test(self):
        policy_json = {
            "payloads": {
                "log_payloads": True,
                "log_blacklist": {
                    "username": ["*"],
                    "password": ["form"]
                }
            }
        }
        policy = PayloadsPolicy()
        policy.from_json(policy_json)
        meta = AppSensorMeta(
            "remote_addr",
            "request_method",
            "abosolute_uri",
            "23947",
            session_id="session_id",
            user_id="user_id"
        )

        old_allow = CONFIGURATION.log_appfirewall_events
        CONFIGURATION.log_appfirewall_events = True

        with patch("tcell_agent.policies.appsensor.payloads_policy.get_payloads_logger") as patched_get_payloadds_logger:
            policy.log("xss", meta, GET_PARAM, "password", "123password123", {"l": "query"}, "pattern")

            CONFIGURATION.log_appfirewall_events = old_allow

            self.assertFalse(patched_get_payloadds_logger.called)
