1# Copyright 2019 Fortinet, Inc. 2# 3# This program is free software: you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation, either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with Ansible. If not, see <https://www.gnu.org/licenses/>. 15 16# Make coding more python3-ish 17from __future__ import (absolute_import, division, print_function) 18__metaclass__ = type 19 20import os 21import json 22import pytest 23from mock import ANY 24from ansible.module_utils.network.fortios.fortios import FortiOSHandler 25 26try: 27 from ansible.modules.network.fortios import fortios_user_tacacsplus 28except ImportError: 29 pytest.skip("Could not load required modules for testing", allow_module_level=True) 30 31 32@pytest.fixture(autouse=True) 33def connection_mock(mocker): 34 connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_user_tacacsplus.Connection') 35 return connection_class_mock 36 37 38fos_instance = FortiOSHandler(connection_mock) 39 40 41def test_user_tacacsplus_creation(mocker): 42 schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema') 43 44 set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200} 45 set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result) 46 47 input_data = { 48 'username': 'admin', 49 'state': 'present', 50 'user_tacacsplus': { 51 'authen_type': 'mschap', 52 'authorization': 'enable', 53 'key': 'test_value_5', 54 'name': 'default_name_6', 55 'port': '7', 56 'secondary_key': 'test_value_8', 57 'secondary_server': 'test_value_9', 58 'server': '192.168.100.10', 59 'source_ip': '84.230.14.11', 60 'tertiary_key': 'test_value_12', 61 'tertiary_server': 'test_value_13' 62 }, 63 'vdom': 'root'} 64 65 is_error, changed, response = fortios_user_tacacsplus.fortios_user(input_data, fos_instance) 66 67 expected_data = { 68 'authen-type': 'mschap', 69 'authorization': 'enable', 70 'key': 'test_value_5', 71 'name': 'default_name_6', 72 'port': '7', 73 'secondary-key': 'test_value_8', 74 'secondary-server': 'test_value_9', 75 'server': '192.168.100.10', 76 'source-ip': '84.230.14.11', 77 'tertiary-key': 'test_value_12', 78 'tertiary-server': 'test_value_13' 79 } 80 81 set_method_mock.assert_called_with('user', 'tacacs+', data=expected_data, vdom='root') 82 schema_method_mock.assert_not_called() 83 assert not is_error 84 assert changed 85 assert response['status'] == 'success' 86 assert response['http_status'] == 200 87 88 89def test_user_tacacsplus_creation_fails(mocker): 90 schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema') 91 92 set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500} 93 set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result) 94 95 input_data = { 96 'username': 'admin', 97 'state': 'present', 98 'user_tacacsplus': { 99 'authen_type': 'mschap', 100 'authorization': 'enable', 101 'key': 'test_value_5', 102 'name': 'default_name_6', 103 'port': '7', 104 'secondary_key': 'test_value_8', 105 'secondary_server': 'test_value_9', 106 'server': '192.168.100.10', 107 'source_ip': '84.230.14.11', 108 'tertiary_key': 'test_value_12', 109 'tertiary_server': 'test_value_13' 110 }, 111 'vdom': 'root'} 112 113 is_error, changed, response = fortios_user_tacacsplus.fortios_user(input_data, fos_instance) 114 115 expected_data = { 116 'authen-type': 'mschap', 117 'authorization': 'enable', 118 'key': 'test_value_5', 119 'name': 'default_name_6', 120 'port': '7', 121 'secondary-key': 'test_value_8', 122 'secondary-server': 'test_value_9', 123 'server': '192.168.100.10', 124 'source-ip': '84.230.14.11', 125 'tertiary-key': 'test_value_12', 126 'tertiary-server': 'test_value_13' 127 } 128 129 set_method_mock.assert_called_with('user', 'tacacs+', data=expected_data, vdom='root') 130 schema_method_mock.assert_not_called() 131 assert is_error 132 assert not changed 133 assert response['status'] == 'error' 134 assert response['http_status'] == 500 135 136 137def test_user_tacacsplus_removal(mocker): 138 schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema') 139 140 delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200} 141 delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result) 142 143 input_data = { 144 'username': 'admin', 145 'state': 'absent', 146 'user_tacacsplus': { 147 'authen_type': 'mschap', 148 'authorization': 'enable', 149 'key': 'test_value_5', 150 'name': 'default_name_6', 151 'port': '7', 152 'secondary_key': 'test_value_8', 153 'secondary_server': 'test_value_9', 154 'server': '192.168.100.10', 155 'source_ip': '84.230.14.11', 156 'tertiary_key': 'test_value_12', 157 'tertiary_server': 'test_value_13' 158 }, 159 'vdom': 'root'} 160 161 is_error, changed, response = fortios_user_tacacsplus.fortios_user(input_data, fos_instance) 162 163 delete_method_mock.assert_called_with('user', 'tacacs+', mkey=ANY, vdom='root') 164 schema_method_mock.assert_not_called() 165 assert not is_error 166 assert changed 167 assert response['status'] == 'success' 168 assert response['http_status'] == 200 169 170 171def test_user_tacacsplus_deletion_fails(mocker): 172 schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema') 173 174 delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500} 175 delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result) 176 177 input_data = { 178 'username': 'admin', 179 'state': 'absent', 180 'user_tacacsplus': { 181 'authen_type': 'mschap', 182 'authorization': 'enable', 183 'key': 'test_value_5', 184 'name': 'default_name_6', 185 'port': '7', 186 'secondary_key': 'test_value_8', 187 'secondary_server': 'test_value_9', 188 'server': '192.168.100.10', 189 'source_ip': '84.230.14.11', 190 'tertiary_key': 'test_value_12', 191 'tertiary_server': 'test_value_13' 192 }, 193 'vdom': 'root'} 194 195 is_error, changed, response = fortios_user_tacacsplus.fortios_user(input_data, fos_instance) 196 197 delete_method_mock.assert_called_with('user', 'tacacs+', mkey=ANY, vdom='root') 198 schema_method_mock.assert_not_called() 199 assert is_error 200 assert not changed 201 assert response['status'] == 'error' 202 assert response['http_status'] == 500 203 204 205def test_user_tacacsplus_idempotent(mocker): 206 schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema') 207 208 set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404} 209 set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result) 210 211 input_data = { 212 'username': 'admin', 213 'state': 'present', 214 'user_tacacsplus': { 215 'authen_type': 'mschap', 216 'authorization': 'enable', 217 'key': 'test_value_5', 218 'name': 'default_name_6', 219 'port': '7', 220 'secondary_key': 'test_value_8', 221 'secondary_server': 'test_value_9', 222 'server': '192.168.100.10', 223 'source_ip': '84.230.14.11', 224 'tertiary_key': 'test_value_12', 225 'tertiary_server': 'test_value_13' 226 }, 227 'vdom': 'root'} 228 229 is_error, changed, response = fortios_user_tacacsplus.fortios_user(input_data, fos_instance) 230 231 expected_data = { 232 'authen-type': 'mschap', 233 'authorization': 'enable', 234 'key': 'test_value_5', 235 'name': 'default_name_6', 236 'port': '7', 237 'secondary-key': 'test_value_8', 238 'secondary-server': 'test_value_9', 239 'server': '192.168.100.10', 240 'source-ip': '84.230.14.11', 241 'tertiary-key': 'test_value_12', 242 'tertiary-server': 'test_value_13' 243 } 244 245 set_method_mock.assert_called_with('user', 'tacacs+', data=expected_data, vdom='root') 246 schema_method_mock.assert_not_called() 247 assert not is_error 248 assert not changed 249 assert response['status'] == 'error' 250 assert response['http_status'] == 404 251 252 253def test_user_tacacsplus_filter_foreign_attributes(mocker): 254 schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema') 255 256 set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200} 257 set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result) 258 259 input_data = { 260 'username': 'admin', 261 'state': 'present', 262 'user_tacacsplus': { 263 'random_attribute_not_valid': 'tag', 264 'authen_type': 'mschap', 265 'authorization': 'enable', 266 'key': 'test_value_5', 267 'name': 'default_name_6', 268 'port': '7', 269 'secondary_key': 'test_value_8', 270 'secondary_server': 'test_value_9', 271 'server': '192.168.100.10', 272 'source_ip': '84.230.14.11', 273 'tertiary_key': 'test_value_12', 274 'tertiary_server': 'test_value_13' 275 }, 276 'vdom': 'root'} 277 278 is_error, changed, response = fortios_user_tacacsplus.fortios_user(input_data, fos_instance) 279 280 expected_data = { 281 'authen-type': 'mschap', 282 'authorization': 'enable', 283 'key': 'test_value_5', 284 'name': 'default_name_6', 285 'port': '7', 286 'secondary-key': 'test_value_8', 287 'secondary-server': 'test_value_9', 288 'server': '192.168.100.10', 289 'source-ip': '84.230.14.11', 290 'tertiary-key': 'test_value_12', 291 'tertiary-server': 'test_value_13' 292 } 293 294 set_method_mock.assert_called_with('user', 'tacacs+', data=expected_data, vdom='root') 295 schema_method_mock.assert_not_called() 296 assert not is_error 297 assert changed 298 assert response['status'] == 'success' 299 assert response['http_status'] == 200 300