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_firewall_ipv6_eh_filter 27short_description: Configure IPv6 extension header filter 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 firewall feature and ipv6_eh_filter 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 firewall_ipv6_eh_filter: 77 description: 78 - Configure IPv6 extension header filter. 79 default: null 80 type: dict 81 suboptions: 82 auth: 83 description: 84 - Enable/disable blocking packets with the Authentication header . 85 type: str 86 choices: 87 - enable 88 - disable 89 dest_opt: 90 description: 91 - Enable/disable blocking packets with Destination Options headers . 92 type: str 93 choices: 94 - enable 95 - disable 96 fragment: 97 description: 98 - Enable/disable blocking packets with the Fragment header . 99 type: str 100 choices: 101 - enable 102 - disable 103 hdopt_type: 104 description: 105 - Block specific Hop-by-Hop and/or Destination Option types (max. 7 types, each between 0 and 255). 106 type: int 107 hop_opt: 108 description: 109 - Enable/disable blocking packets with the Hop-by-Hop Options header . 110 type: str 111 choices: 112 - enable 113 - disable 114 no_next: 115 description: 116 - Enable/disable blocking packets with the No Next header 117 type: str 118 choices: 119 - enable 120 - disable 121 routing: 122 description: 123 - Enable/disable blocking packets with Routing headers . 124 type: str 125 choices: 126 - enable 127 - disable 128 routing_type: 129 description: 130 - Block specific Routing header types (max. 7 types, each between 0 and 255). 131 type: int 132''' 133 134EXAMPLES = ''' 135- hosts: localhost 136 vars: 137 host: "192.168.122.40" 138 username: "admin" 139 password: "" 140 vdom: "root" 141 ssl_verify: "False" 142 tasks: 143 - name: Configure IPv6 extension header filter. 144 fortios_firewall_ipv6_eh_filter: 145 host: "{{ host }}" 146 username: "{{ username }}" 147 password: "{{ password }}" 148 vdom: "{{ vdom }}" 149 https: "False" 150 firewall_ipv6_eh_filter: 151 auth: "enable" 152 dest_opt: "enable" 153 fragment: "enable" 154 hdopt_type: "6" 155 hop_opt: "enable" 156 no_next: "enable" 157 routing: "enable" 158 routing_type: "10" 159''' 160 161RETURN = ''' 162build: 163 description: Build number of the fortigate image 164 returned: always 165 type: str 166 sample: '1547' 167http_method: 168 description: Last method used to provision the content into FortiGate 169 returned: always 170 type: str 171 sample: 'PUT' 172http_status: 173 description: Last result given by FortiGate on last operation applied 174 returned: always 175 type: str 176 sample: "200" 177mkey: 178 description: Master key (id) used in the last call to FortiGate 179 returned: success 180 type: str 181 sample: "id" 182name: 183 description: Name of the table used to fulfill the request 184 returned: always 185 type: str 186 sample: "urlfilter" 187path: 188 description: Path of the table used to fulfill the request 189 returned: always 190 type: str 191 sample: "webfilter" 192revision: 193 description: Internal revision number 194 returned: always 195 type: str 196 sample: "17.0.2.10658" 197serial: 198 description: Serial number of the unit 199 returned: always 200 type: str 201 sample: "FGVMEVYYQT3AB5352" 202status: 203 description: Indication of the operation's result 204 returned: always 205 type: str 206 sample: "success" 207vdom: 208 description: Virtual domain used 209 returned: always 210 type: str 211 sample: "root" 212version: 213 description: Version of the FortiGate 214 returned: always 215 type: str 216 sample: "v5.6.3" 217 218''' 219 220from ansible.module_utils.basic import AnsibleModule 221from ansible.module_utils.connection import Connection 222from ansible.module_utils.network.fortios.fortios import FortiOSHandler 223from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG 224 225 226def login(data, fos): 227 host = data['host'] 228 username = data['username'] 229 password = data['password'] 230 ssl_verify = data['ssl_verify'] 231 232 fos.debug('on') 233 if 'https' in data and not data['https']: 234 fos.https('off') 235 else: 236 fos.https('on') 237 238 fos.login(host, username, password, verify=ssl_verify) 239 240 241def filter_firewall_ipv6_eh_filter_data(json): 242 option_list = ['auth', 'dest_opt', 'fragment', 243 'hdopt_type', 'hop_opt', 'no_next', 244 'routing', 'routing_type'] 245 dictionary = {} 246 247 for attribute in option_list: 248 if attribute in json and json[attribute] is not None: 249 dictionary[attribute] = json[attribute] 250 251 return dictionary 252 253 254def underscore_to_hyphen(data): 255 if isinstance(data, list): 256 for elem in data: 257 elem = underscore_to_hyphen(elem) 258 elif isinstance(data, dict): 259 new_data = {} 260 for k, v in data.items(): 261 new_data[k.replace('_', '-')] = underscore_to_hyphen(v) 262 data = new_data 263 264 return data 265 266 267def firewall_ipv6_eh_filter(data, fos): 268 vdom = data['vdom'] 269 firewall_ipv6_eh_filter_data = data['firewall_ipv6_eh_filter'] 270 filtered_data = underscore_to_hyphen(filter_firewall_ipv6_eh_filter_data(firewall_ipv6_eh_filter_data)) 271 272 return fos.set('firewall', 273 'ipv6-eh-filter', 274 data=filtered_data, 275 vdom=vdom) 276 277 278def is_successful_status(status): 279 return status['status'] == "success" or \ 280 status['http_method'] == "DELETE" and status['http_status'] == 404 281 282 283def fortios_firewall(data, fos): 284 285 if data['firewall_ipv6_eh_filter']: 286 resp = firewall_ipv6_eh_filter(data, fos) 287 288 return not is_successful_status(resp), \ 289 resp['status'] == "success", \ 290 resp 291 292 293def main(): 294 fields = { 295 "host": {"required": False, "type": "str"}, 296 "username": {"required": False, "type": "str"}, 297 "password": {"required": False, "type": "str", "default": "", "no_log": True}, 298 "vdom": {"required": False, "type": "str", "default": "root"}, 299 "https": {"required": False, "type": "bool", "default": True}, 300 "ssl_verify": {"required": False, "type": "bool", "default": True}, 301 "firewall_ipv6_eh_filter": { 302 "required": False, "type": "dict", "default": None, 303 "options": { 304 "auth": {"required": False, "type": "str", 305 "choices": ["enable", "disable"]}, 306 "dest_opt": {"required": False, "type": "str", 307 "choices": ["enable", "disable"]}, 308 "fragment": {"required": False, "type": "str", 309 "choices": ["enable", "disable"]}, 310 "hdopt_type": {"required": False, "type": "int"}, 311 "hop_opt": {"required": False, "type": "str", 312 "choices": ["enable", "disable"]}, 313 "no_next": {"required": False, "type": "str", 314 "choices": ["enable", "disable"]}, 315 "routing": {"required": False, "type": "str", 316 "choices": ["enable", "disable"]}, 317 "routing_type": {"required": False, "type": "int"} 318 319 } 320 } 321 } 322 323 module = AnsibleModule(argument_spec=fields, 324 supports_check_mode=False) 325 326 # legacy_mode refers to using fortiosapi instead of HTTPAPI 327 legacy_mode = 'host' in module.params and module.params['host'] is not None and \ 328 'username' in module.params and module.params['username'] is not None and \ 329 'password' in module.params and module.params['password'] is not None 330 331 if not legacy_mode: 332 if module._socket_path: 333 connection = Connection(module._socket_path) 334 fos = FortiOSHandler(connection) 335 336 is_error, has_changed, result = fortios_firewall(module.params, fos) 337 else: 338 module.fail_json(**FAIL_SOCKET_MSG) 339 else: 340 try: 341 from fortiosapi import FortiOSAPI 342 except ImportError: 343 module.fail_json(msg="fortiosapi module is required") 344 345 fos = FortiOSAPI() 346 347 login(module.params, fos) 348 is_error, has_changed, result = fortios_firewall(module.params, fos) 349 fos.logout() 350 351 if not is_error: 352 module.exit_json(changed=has_changed, meta=result) 353 else: 354 module.fail_json(msg="Error in repo", meta=result) 355 356 357if __name__ == '__main__': 358 main() 359