1#!/usr/bin/python 2from __future__ import (absolute_import, division, print_function) 3# Copyright 2019 Fortinet, Inc. 4# 5# This program is free software: you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation, either version 3 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see <https://www.gnu.org/licenses/>. 17 18__metaclass__ = type 19 20ANSIBLE_METADATA = {'status': ['preview'], 21 'supported_by': 'community', 22 'metadata_version': '1.1'} 23 24DOCUMENTATION = ''' 25--- 26module: fortios_log_null_device_setting 27short_description: Settings for null device logging in Fortinet's FortiOS and FortiGate. 28description: 29 - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the 30 user to set and modify log_null_device feature and setting category. 31 Examples include all parameters and values need to be adjusted to datasources before usage. 32 Tested with FOS v6.0.5 33version_added: "2.8" 34author: 35 - Miguel Angel Munoz (@mamunozgonzalez) 36 - Nicolas Thomas (@thomnico) 37notes: 38 - Requires fortiosapi library developed by Fortinet 39 - Run as a local_action in your playbook 40requirements: 41 - fortiosapi>=0.9.8 42options: 43 host: 44 description: 45 - FortiOS or FortiGate IP address. 46 type: str 47 required: false 48 username: 49 description: 50 - FortiOS or FortiGate username. 51 type: str 52 required: false 53 password: 54 description: 55 - FortiOS or FortiGate password. 56 type: str 57 default: "" 58 vdom: 59 description: 60 - Virtual domain, among those defined previously. A vdom is a 61 virtual instance of the FortiGate that can be configured and 62 used as a different unit. 63 type: str 64 default: root 65 https: 66 description: 67 - Indicates if the requests towards FortiGate must use HTTPS protocol. 68 type: bool 69 default: true 70 ssl_verify: 71 description: 72 - Ensures FortiGate certificate must be verified by a proper CA. 73 type: bool 74 default: true 75 version_added: 2.9 76 log_null_device_setting: 77 description: 78 - Settings for null device logging. 79 default: null 80 type: dict 81 suboptions: 82 status: 83 description: 84 - Enable/disable statistics collection for when no external logging destination, such as FortiAnalyzer, is present (data is not saved). 85 type: str 86 choices: 87 - enable 88 - disable 89''' 90 91EXAMPLES = ''' 92- hosts: localhost 93 vars: 94 host: "192.168.122.40" 95 username: "admin" 96 password: "" 97 vdom: "root" 98 ssl_verify: "False" 99 tasks: 100 - name: Settings for null device logging. 101 fortios_log_null_device_setting: 102 host: "{{ host }}" 103 username: "{{ username }}" 104 password: "{{ password }}" 105 vdom: "{{ vdom }}" 106 https: "False" 107 log_null_device_setting: 108 status: "enable" 109''' 110 111RETURN = ''' 112build: 113 description: Build number of the fortigate image 114 returned: always 115 type: str 116 sample: '1547' 117http_method: 118 description: Last method used to provision the content into FortiGate 119 returned: always 120 type: str 121 sample: 'PUT' 122http_status: 123 description: Last result given by FortiGate on last operation applied 124 returned: always 125 type: str 126 sample: "200" 127mkey: 128 description: Master key (id) used in the last call to FortiGate 129 returned: success 130 type: str 131 sample: "id" 132name: 133 description: Name of the table used to fulfill the request 134 returned: always 135 type: str 136 sample: "urlfilter" 137path: 138 description: Path of the table used to fulfill the request 139 returned: always 140 type: str 141 sample: "webfilter" 142revision: 143 description: Internal revision number 144 returned: always 145 type: str 146 sample: "17.0.2.10658" 147serial: 148 description: Serial number of the unit 149 returned: always 150 type: str 151 sample: "FGVMEVYYQT3AB5352" 152status: 153 description: Indication of the operation's result 154 returned: always 155 type: str 156 sample: "success" 157vdom: 158 description: Virtual domain used 159 returned: always 160 type: str 161 sample: "root" 162version: 163 description: Version of the FortiGate 164 returned: always 165 type: str 166 sample: "v5.6.3" 167 168''' 169 170from ansible.module_utils.basic import AnsibleModule 171from ansible.module_utils.connection import Connection 172from ansible.module_utils.network.fortios.fortios import FortiOSHandler 173from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG 174 175 176def login(data, fos): 177 host = data['host'] 178 username = data['username'] 179 password = data['password'] 180 ssl_verify = data['ssl_verify'] 181 182 fos.debug('on') 183 if 'https' in data and not data['https']: 184 fos.https('off') 185 else: 186 fos.https('on') 187 188 fos.login(host, username, password, verify=ssl_verify) 189 190 191def filter_log_null_device_setting_data(json): 192 option_list = ['status'] 193 dictionary = {} 194 195 for attribute in option_list: 196 if attribute in json and json[attribute] is not None: 197 dictionary[attribute] = json[attribute] 198 199 return dictionary 200 201 202def underscore_to_hyphen(data): 203 if isinstance(data, list): 204 for elem in data: 205 elem = underscore_to_hyphen(elem) 206 elif isinstance(data, dict): 207 new_data = {} 208 for k, v in data.items(): 209 new_data[k.replace('_', '-')] = underscore_to_hyphen(v) 210 data = new_data 211 212 return data 213 214 215def log_null_device_setting(data, fos): 216 vdom = data['vdom'] 217 log_null_device_setting_data = data['log_null_device_setting'] 218 filtered_data = underscore_to_hyphen(filter_log_null_device_setting_data(log_null_device_setting_data)) 219 220 return fos.set('log.null-device', 221 'setting', 222 data=filtered_data, 223 vdom=vdom) 224 225 226def is_successful_status(status): 227 return status['status'] == "success" or \ 228 status['http_method'] == "DELETE" and status['http_status'] == 404 229 230 231def fortios_log_null_device(data, fos): 232 233 if data['log_null_device_setting']: 234 resp = log_null_device_setting(data, fos) 235 236 return not is_successful_status(resp), \ 237 resp['status'] == "success", \ 238 resp 239 240 241def main(): 242 fields = { 243 "host": {"required": False, "type": "str"}, 244 "username": {"required": False, "type": "str"}, 245 "password": {"required": False, "type": "str", "default": "", "no_log": True}, 246 "vdom": {"required": False, "type": "str", "default": "root"}, 247 "https": {"required": False, "type": "bool", "default": True}, 248 "ssl_verify": {"required": False, "type": "bool", "default": True}, 249 "log_null_device_setting": { 250 "required": False, "type": "dict", "default": None, 251 "options": { 252 "status": {"required": False, "type": "str", 253 "choices": ["enable", "disable"]} 254 255 } 256 } 257 } 258 259 module = AnsibleModule(argument_spec=fields, 260 supports_check_mode=False) 261 262 # legacy_mode refers to using fortiosapi instead of HTTPAPI 263 legacy_mode = 'host' in module.params and module.params['host'] is not None and \ 264 'username' in module.params and module.params['username'] is not None and \ 265 'password' in module.params and module.params['password'] is not None 266 267 if not legacy_mode: 268 if module._socket_path: 269 connection = Connection(module._socket_path) 270 fos = FortiOSHandler(connection) 271 272 is_error, has_changed, result = fortios_log_null_device(module.params, fos) 273 else: 274 module.fail_json(**FAIL_SOCKET_MSG) 275 else: 276 try: 277 from fortiosapi import FortiOSAPI 278 except ImportError: 279 module.fail_json(msg="fortiosapi module is required") 280 281 fos = FortiOSAPI() 282 283 login(module.params, fos) 284 is_error, has_changed, result = fortios_log_null_device(module.params, fos) 285 fos.logout() 286 287 if not is_error: 288 module.exit_json(changed=has_changed, meta=result) 289 else: 290 module.fail_json(msg="Error in repo", meta=result) 291 292 293if __name__ == '__main__': 294 main() 295