1# -*- coding: utf-8 -*- 2# 3# Copyright: (c) 2019, F5 Networks Inc. 4# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 5 6from __future__ import (absolute_import, division, print_function) 7__metaclass__ = type 8 9import os 10import json 11import pytest 12import sys 13 14if sys.version_info < (2, 7): 15 pytestmark = pytest.mark.skip("F5 Ansible modules require Python >= 2.7") 16 17from ansible.module_utils.basic import AnsibleModule 18from ansible_collections.f5networks.f5_modules.plugins.modules.bigip_asm_dos_application import ( 19 ApiParameters, ModuleParameters, ModuleManager, ArgumentSpec 20) 21from ansible_collections.f5networks.f5_modules.tests.unit.modules.utils import set_module_args 22from ansible_collections.f5networks.f5_modules.tests.unit.compat import unittest 23from ansible_collections.f5networks.f5_modules.tests.unit.compat.mock import ( 24 Mock, patch 25) 26 27 28fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures') 29fixture_data = {} 30 31 32def load_fixture(name): 33 path = os.path.join(fixture_path, name) 34 35 if path in fixture_data: 36 return fixture_data[path] 37 38 with open(path) as f: 39 data = f.read() 40 41 try: 42 data = json.loads(data) 43 except Exception: 44 pass 45 46 fixture_data[path] = data 47 return data 48 49 50class TestParameters(unittest.TestCase): 51 def test_module_parameters(self): 52 args = dict( 53 profile='dos_foo', 54 geolocations=dict( 55 blacklist=['Argentina', 'Montenegro'], 56 whitelist=['France', 'Belgium'] 57 ), 58 heavy_urls=dict( 59 auto_detect=True, 60 latency_threshold=3000, 61 exclude=['/exclude1.html', '/exclude2.html'], 62 include=[dict(url='include1.html', threshold='auto'), 63 dict(url='include2.html', threshold='2000')], 64 ), 65 mobile_detection=dict( 66 enabled=True, 67 allow_android_rooted_device=True, 68 allow_any_android_package=True, 69 allow_any_ios_package=True, 70 allow_jailbroken_devices=True, 71 allow_emulators=True, 72 client_side_challenge_mode='cshui', 73 ios_allowed_package_names=['foo', 'bar'], 74 android_publishers=['cert1.crt', 'cert2.crt'] 75 ), 76 rtbh_duration=180, 77 rtbh_enable=True, 78 scrubbing_duration=360, 79 scrubbing_enable=True, 80 single_page_application=True, 81 trigger_irule=False, 82 partition='Common' 83 ) 84 85 p = ModuleParameters(params=args) 86 assert p.profile == 'dos_foo' 87 assert p.geo_whitelist == ['France', 'Belgium'] 88 assert p.geo_blacklist == ['Argentina', 'Montenegro'] 89 assert p.auto_detect == 'enabled' 90 assert p.latency_threshold == 3000 91 assert p.hw_url_exclude == ['/exclude1.html', '/exclude2.html'] 92 assert dict(name='URL/include1.html', threshold='auto', url='/include1.html') in p.hw_url_include 93 assert dict(name='URL/include2.html', threshold='2000', url='/include2.html') in p.hw_url_include 94 assert p.allow_android_rooted_device == 'true' 95 assert p.enable_mobile_detection == 'enabled' 96 assert p.allow_any_android_package == 'true' 97 assert p.allow_any_ios_package == 'true' 98 assert p.allow_jailbroken_devices == 'true' 99 assert p.allow_emulators == 'true' 100 assert p.client_side_challenge_mode == 'cshui' 101 assert p.ios_allowed_package_names == ['foo', 'bar'] 102 assert p.android_publishers == ['/Common/cert1.crt', '/Common/cert2.crt'] 103 assert p.rtbh_duration == 180 104 assert p.rtbh_enable == 'enabled' 105 assert p.scrubbing_duration == 360 106 assert p.scrubbing_enable == 'enabled' 107 assert p.single_page_application == 'enabled' 108 assert p.trigger_irule == 'disabled' 109 110 def test_api_parameters(self): 111 args = load_fixture('load_asm_dos.json') 112 113 p = ApiParameters(params=args) 114 assert p.geo_whitelist == ['Aland Islands'] 115 assert p.geo_blacklist == ['Afghanistan'] 116 assert p.auto_detect == 'enabled' 117 assert p.latency_threshold == 1000 118 assert p.hw_url_exclude == ['/exclude.html'] 119 assert dict(name='URL/test.htm', threshold='auto', url='/test.htm') in p.hw_url_include 120 assert dict(name='URL/testy.htm', threshold='auto', url='/testy.htm') in p.hw_url_include 121 assert p.allow_android_rooted_device == 'false' 122 assert p.enable_mobile_detection == 'disabled' 123 assert p.allow_any_android_package == 'false' 124 assert p.allow_any_ios_package == 'false' 125 assert p.allow_jailbroken_devices == 'true' 126 assert p.allow_emulators == 'true' 127 assert p.client_side_challenge_mode == 'pass' 128 assert p.ios_allowed_package_names == ['foobarapp'] 129 assert p.android_publishers == ['/Common/ca-bundle.crt'] 130 assert p.rtbh_duration == 300 131 assert p.rtbh_enable == 'enabled' 132 assert p.scrubbing_duration == 60 133 assert p.scrubbing_enable == 'enabled' 134 assert p.single_page_application == 'enabled' 135 assert p.trigger_irule == 'enabled' 136 137 138class TestManager(unittest.TestCase): 139 def setUp(self): 140 self.spec = ArgumentSpec() 141 self.p1 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_asm_dos_application.module_provisioned') 142 self.m1 = self.p1.start() 143 self.m1.return_value = True 144 self.p2 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_asm_dos_application.tmos_version') 145 self.p3 = patch('ansible_collections.f5networks.f5_modules.plugins.modules.bigip_asm_dos_application.send_teem') 146 self.m2 = self.p2.start() 147 self.m2.return_value = '14.1.0' 148 self.m3 = self.p3.start() 149 self.m3.return_value = True 150 151 def tearDown(self): 152 self.p1.stop() 153 self.p2.stop() 154 self.p3.stop() 155 156 def test_create_asm_dos_profile(self, *args): 157 set_module_args(dict( 158 profile='dos_foo', 159 geolocations=dict( 160 blacklist=['Argentina', 'Montenegro'], 161 whitelist=['France', 'Belgium'] 162 ), 163 heavy_urls=dict( 164 auto_detect=True, 165 latency_threshold=3000, 166 exclude=['/exclude1.html', '/exclude2.html'], 167 include=[dict(url='include1.html', threshold='auto'), 168 dict(url='include2.html', threshold='2000')] 169 ), 170 mobile_detection=dict( 171 enabled=True, 172 allow_android_rooted_device=True, 173 allow_any_android_package=True, 174 allow_any_ios_package=True, 175 allow_jailbroken_devices=True, 176 allow_emulators=True, 177 client_side_challenge_mode='cshui', 178 ios_allowed_package_names=['foo', 'bar'], 179 android_publishers=['cert1.crt', 'cert2.crt'] 180 ), 181 rtbh_duration=180, 182 rtbh_enable=True, 183 scrubbing_duration=360, 184 scrubbing_enable=True, 185 single_page_application=True, 186 trigger_irule=False, 187 partition='Common', 188 provider=dict( 189 server='localhost', 190 password='password', 191 user='admin' 192 ) 193 )) 194 195 module = AnsibleModule( 196 argument_spec=self.spec.argument_spec, 197 supports_check_mode=self.spec.supports_check_mode, 198 ) 199 200 # Override methods in the specific type of manager 201 mm = ModuleManager(module=module) 202 mm.exists = Mock(return_value=False) 203 mm.create_on_device = Mock(return_value=True) 204 mm.version_less_than_13_1 = Mock(return_value=False) 205 206 results = mm.exec_module() 207 208 assert results['changed'] is True 209 assert results['geolocations'] == dict(blacklist=['Argentina', 'Montenegro'], whitelist=['France', 'Belgium']) 210 assert results['heavy_urls'] == dict(auto_detect='yes', latency_threshold=3000, 211 exclude=['/exclude1.html', '/exclude2.html'], 212 include=[dict(url='/include1.html', threshold='auto'), 213 dict(url='/include2.html', threshold='2000')] 214 ) 215 assert results['mobile_detection'] == dict(enabled='yes', allow_android_rooted_device='yes', 216 allow_any_android_package='yes', allow_any_ios_package='yes', 217 allow_jailbroken_devices='yes', allow_emulators='yes', 218 client_side_challenge_mode='cshui', 219 ios_allowed_package_names=['foo', 'bar'], 220 android_publishers=['/Common/cert1.crt', '/Common/cert2.crt'] 221 ) 222 assert results['rtbh_duration'] == 180 223 assert results['rtbh_enable'] == 'yes' 224 assert results['scrubbing_duration'] == 360 225 assert results['scrubbing_enable'] == 'yes' 226 assert results['single_page_application'] == 'yes' 227 assert results['trigger_irule'] == 'no' 228 229 def test_update_asm_dos_profile(self, *args): 230 set_module_args(dict( 231 profile='test', 232 heavy_urls=dict( 233 latency_threshold=3000, 234 exclude=['/exclude1.html', '/exclude2.html'], 235 include=[dict(url='include1.html', threshold='auto'), 236 dict(url='include2.html', threshold='2000')] 237 ), 238 provider=dict( 239 server='localhost', 240 password='password', 241 user='admin' 242 ) 243 )) 244 245 current = ApiParameters(params=load_fixture('load_asm_dos.json')) 246 247 module = AnsibleModule( 248 argument_spec=self.spec.argument_spec, 249 supports_check_mode=self.spec.supports_check_mode, 250 ) 251 252 # Override methods in the specific type of manager 253 mm = ModuleManager(module=module) 254 mm.exists = Mock(return_value=True) 255 mm.update_on_device = Mock(return_value=True) 256 mm.read_current_from_device = Mock(return_value=current) 257 mm.version_less_than_13_1 = Mock(return_value=False) 258 259 results = mm.exec_module() 260 261 assert results['changed'] is True 262 assert results['heavy_urls'] == dict(latency_threshold=3000, exclude=['/exclude1.html', '/exclude2.html'], 263 include=[dict(url='/include1.html', threshold='auto'), 264 dict(url='/include2.html', threshold='2000')] 265 ) 266