1#!/usr/bin/python 2# 3# Ansible module to manage configuration on fortios devices 4# (c) 2016, Benjamin Jolivot <bjolivot@gmail.com> 5# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) 6 7from __future__ import absolute_import, division, print_function 8__metaclass__ = type 9 10 11ANSIBLE_METADATA = {'metadata_version': '1.1', 12 'status': ['preview'], 13 'supported_by': 'community'} 14 15 16DOCUMENTATION = """ 17--- 18module: fortios_config 19version_added: "2.3" 20author: "Benjamin Jolivot (@bjolivot)" 21short_description: Manage config on Fortinet FortiOS firewall devices 22description: 23 - This module provides management of FortiOS Devices configuration. 24extends_documentation_fragment: fortios 25options: 26 src: 27 description: 28 - The I(src) argument provides a path to the configuration template 29 to load into the remote device. 30 filter: 31 description: 32 - Only for partial backup, you can restrict by giving expected configuration path (ex. firewall address). 33 default: "" 34requirements: 35 - pyFG 36""" 37 38EXAMPLES = """ 39- name: Backup current config 40 fortios_config: 41 host: 192.168.0.254 42 username: admin 43 password: password 44 backup: yes 45 46- name: Backup only address objects 47 fortios_config: 48 host: 192.168.0.254 49 username: admin 50 password: password 51 backup: yes 52 backup_path: /tmp/forti_backup/ 53 filter: "firewall address" 54 55- name: Update configuration from file 56 fortios_config: 57 host: 192.168.0.254 58 username: admin 59 password: password 60 src: new_configuration.conf.j2 61 62""" 63 64RETURN = """ 65running_config: 66 description: full config string 67 returned: always 68 type: str 69change_string: 70 description: The commands really executed by the module 71 returned: only if config changed 72 type: str 73""" 74 75from ansible.module_utils.basic import AnsibleModule 76from ansible.module_utils.network.fortios.fortios import fortios_argument_spec, fortios_required_if 77from ansible.module_utils.network.fortios.fortios import backup 78 79# check for pyFG lib 80try: 81 from pyFG import FortiOS, FortiConfig 82 from pyFG.fortios import logger 83 from pyFG.exceptions import CommandExecutionException, FailedCommit, ForcedCommit 84 HAS_PYFG = True 85except Exception: 86 HAS_PYFG = False 87 88 89# some blocks don't support update, so remove them 90NOT_UPDATABLE_CONFIG_OBJECTS = [ 91 "vpn certificate local", 92] 93 94 95def main(): 96 argument_spec = dict( 97 src=dict(type='str', default=None), 98 filter=dict(type='str', default=""), 99 ) 100 101 argument_spec.update(fortios_argument_spec) 102 103 required_if = fortios_required_if 104 105 module = AnsibleModule( 106 argument_spec=argument_spec, 107 supports_check_mode=True, 108 required_if=required_if, 109 ) 110 111 result = dict(changed=False) 112 113 # fail if pyFG not present 114 if not HAS_PYFG: 115 module.fail_json(msg='Could not import the python library pyFG required by this module') 116 117 # define device 118 f = FortiOS(module.params['host'], 119 username=module.params['username'], 120 password=module.params['password'], 121 timeout=module.params['timeout'], 122 vdom=module.params['vdom']) 123 124 # connect 125 try: 126 f.open() 127 except Exception: 128 module.fail_json(msg='Error connecting device') 129 130 # get config 131 try: 132 f.load_config(path=module.params['filter']) 133 result['running_config'] = f.running_config.to_text() 134 135 except Exception: 136 module.fail_json(msg='Error reading running config') 137 138 # backup config 139 if module.params['backup']: 140 backup(module, f.running_config.to_text()) 141 142 # update config 143 if module.params['src'] is not None: 144 # store config in str 145 try: 146 conf_str = module.params['src'] 147 f.load_config(in_candidate=True, config_text=conf_str) 148 except Exception: 149 module.fail_json(msg="Can't open configuration file, or configuration invalid") 150 151 # get updates lines 152 change_string = f.compare_config() 153 154 # remove not updatable parts 155 c = FortiConfig() 156 c.parse_config_output(change_string) 157 158 for o in NOT_UPDATABLE_CONFIG_OBJECTS: 159 c.del_block(o) 160 161 change_string = c.to_text() 162 163 if change_string != "": 164 result['change_string'] = change_string 165 result['changed'] = True 166 167 # Commit if not check mode 168 if module.check_mode is False and change_string != "": 169 try: 170 f.commit(change_string) 171 except CommandExecutionException as e: 172 module.fail_json(msg="Unable to execute command, check your args, the error was {0}".format(e.message)) 173 except FailedCommit as e: 174 module.fail_json(msg="Unable to commit, check your args, the error was {0}".format(e.message)) 175 except ForcedCommit as e: 176 module.fail_json(msg="Failed to force commit, check your args, the error was {0}".format(e.message)) 177 178 module.exit_json(**result) 179 180 181if __name__ == '__main__': 182 main() 183