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_dlp_fp_sensitivity
27short_description: Create self-explanatory DLP sensitivity levels to be used when setting sensitivity under config fp-doc-source in Fortinet's FortiOS and
28   FortiGate.
29description:
30    - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
31      user to set and modify dlp feature and fp_sensitivity category.
32      Examples include all parameters and values need to be adjusted to datasources before usage.
33      Tested with FOS v6.0.5
34version_added: "2.8"
35author:
36    - Miguel Angel Munoz (@mamunozgonzalez)
37    - Nicolas Thomas (@thomnico)
38notes:
39    - Requires fortiosapi library developed by Fortinet
40    - Run as a local_action in your playbook
41requirements:
42    - fortiosapi>=0.9.8
43options:
44    host:
45        description:
46            - FortiOS or FortiGate IP address.
47        type: str
48        required: false
49    username:
50        description:
51            - FortiOS or FortiGate username.
52        type: str
53        required: false
54    password:
55        description:
56            - FortiOS or FortiGate password.
57        type: str
58        default: ""
59    vdom:
60        description:
61            - Virtual domain, among those defined previously. A vdom is a
62              virtual instance of the FortiGate that can be configured and
63              used as a different unit.
64        type: str
65        default: root
66    https:
67        description:
68            - Indicates if the requests towards FortiGate must use HTTPS protocol.
69        type: bool
70        default: true
71    ssl_verify:
72        description:
73            - Ensures FortiGate certificate must be verified by a proper CA.
74        type: bool
75        default: true
76        version_added: 2.9
77    state:
78        description:
79            - Indicates whether to create or remove the object.
80              This attribute was present already in previous version in a deeper level.
81              It has been moved out to this outer level.
82        type: str
83        required: false
84        choices:
85            - present
86            - absent
87        version_added: 2.9
88    dlp_fp_sensitivity:
89        description:
90            - Create self-explanatory DLP sensitivity levels to be used when setting sensitivity under config fp-doc-source.
91        default: null
92        type: dict
93        suboptions:
94            state:
95                description:
96                    - B(Deprecated)
97                    - Starting with Ansible 2.9 we recommend using the top-level 'state' parameter.
98                    - HORIZONTALLINE
99                    - Indicates whether to create or remove the object.
100                type: str
101                required: false
102                choices:
103                    - present
104                    - absent
105            name:
106                description:
107                    - DLP Sensitivity Levels.
108                required: true
109                type: str
110'''
111
112EXAMPLES = '''
113- hosts: localhost
114  vars:
115   host: "192.168.122.40"
116   username: "admin"
117   password: ""
118   vdom: "root"
119   ssl_verify: "False"
120  tasks:
121  - name: Create self-explanatory DLP sensitivity levels to be used when setting sensitivity under config fp-doc-source.
122    fortios_dlp_fp_sensitivity:
123      host:  "{{ host }}"
124      username: "{{ username }}"
125      password: "{{ password }}"
126      vdom:  "{{ vdom }}"
127      https: "False"
128      state: "present"
129      dlp_fp_sensitivity:
130        name: "default_name_3"
131'''
132
133RETURN = '''
134build:
135  description: Build number of the fortigate image
136  returned: always
137  type: str
138  sample: '1547'
139http_method:
140  description: Last method used to provision the content into FortiGate
141  returned: always
142  type: str
143  sample: 'PUT'
144http_status:
145  description: Last result given by FortiGate on last operation applied
146  returned: always
147  type: str
148  sample: "200"
149mkey:
150  description: Master key (id) used in the last call to FortiGate
151  returned: success
152  type: str
153  sample: "id"
154name:
155  description: Name of the table used to fulfill the request
156  returned: always
157  type: str
158  sample: "urlfilter"
159path:
160  description: Path of the table used to fulfill the request
161  returned: always
162  type: str
163  sample: "webfilter"
164revision:
165  description: Internal revision number
166  returned: always
167  type: str
168  sample: "17.0.2.10658"
169serial:
170  description: Serial number of the unit
171  returned: always
172  type: str
173  sample: "FGVMEVYYQT3AB5352"
174status:
175  description: Indication of the operation's result
176  returned: always
177  type: str
178  sample: "success"
179vdom:
180  description: Virtual domain used
181  returned: always
182  type: str
183  sample: "root"
184version:
185  description: Version of the FortiGate
186  returned: always
187  type: str
188  sample: "v5.6.3"
189
190'''
191
192from ansible.module_utils.basic import AnsibleModule
193from ansible.module_utils.connection import Connection
194from ansible.module_utils.network.fortios.fortios import FortiOSHandler
195from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
196
197
198def login(data, fos):
199    host = data['host']
200    username = data['username']
201    password = data['password']
202    ssl_verify = data['ssl_verify']
203
204    fos.debug('on')
205    if 'https' in data and not data['https']:
206        fos.https('off')
207    else:
208        fos.https('on')
209
210    fos.login(host, username, password, verify=ssl_verify)
211
212
213def filter_dlp_fp_sensitivity_data(json):
214    option_list = ['name']
215    dictionary = {}
216
217    for attribute in option_list:
218        if attribute in json and json[attribute] is not None:
219            dictionary[attribute] = json[attribute]
220
221    return dictionary
222
223
224def underscore_to_hyphen(data):
225    if isinstance(data, list):
226        for elem in data:
227            elem = underscore_to_hyphen(elem)
228    elif isinstance(data, dict):
229        new_data = {}
230        for k, v in data.items():
231            new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
232        data = new_data
233
234    return data
235
236
237def dlp_fp_sensitivity(data, fos):
238    vdom = data['vdom']
239    if 'state' in data and data['state']:
240        state = data['state']
241    elif 'state' in data['dlp_fp_sensitivity'] and data['dlp_fp_sensitivity']:
242        state = data['dlp_fp_sensitivity']['state']
243    else:
244        state = True
245    dlp_fp_sensitivity_data = data['dlp_fp_sensitivity']
246    filtered_data = underscore_to_hyphen(filter_dlp_fp_sensitivity_data(dlp_fp_sensitivity_data))
247
248    if state == "present":
249        return fos.set('dlp',
250                       'fp-sensitivity',
251                       data=filtered_data,
252                       vdom=vdom)
253
254    elif state == "absent":
255        return fos.delete('dlp',
256                          'fp-sensitivity',
257                          mkey=filtered_data['name'],
258                          vdom=vdom)
259
260
261def is_successful_status(status):
262    return status['status'] == "success" or \
263        status['http_method'] == "DELETE" and status['http_status'] == 404
264
265
266def fortios_dlp(data, fos):
267
268    if data['dlp_fp_sensitivity']:
269        resp = dlp_fp_sensitivity(data, fos)
270
271    return not is_successful_status(resp), \
272        resp['status'] == "success", \
273        resp
274
275
276def main():
277    fields = {
278        "host": {"required": False, "type": "str"},
279        "username": {"required": False, "type": "str"},
280        "password": {"required": False, "type": "str", "default": "", "no_log": True},
281        "vdom": {"required": False, "type": "str", "default": "root"},
282        "https": {"required": False, "type": "bool", "default": True},
283        "ssl_verify": {"required": False, "type": "bool", "default": True},
284        "state": {"required": False, "type": "str",
285                  "choices": ["present", "absent"]},
286        "dlp_fp_sensitivity": {
287            "required": False, "type": "dict", "default": None,
288            "options": {
289                "state": {"required": False, "type": "str",
290                          "choices": ["present", "absent"]},
291                "name": {"required": True, "type": "str"}
292
293            }
294        }
295    }
296
297    module = AnsibleModule(argument_spec=fields,
298                           supports_check_mode=False)
299
300    # legacy_mode refers to using fortiosapi instead of HTTPAPI
301    legacy_mode = 'host' in module.params and module.params['host'] is not None and \
302                  'username' in module.params and module.params['username'] is not None and \
303                  'password' in module.params and module.params['password'] is not None
304
305    if not legacy_mode:
306        if module._socket_path:
307            connection = Connection(module._socket_path)
308            fos = FortiOSHandler(connection)
309
310            is_error, has_changed, result = fortios_dlp(module.params, fos)
311        else:
312            module.fail_json(**FAIL_SOCKET_MSG)
313    else:
314        try:
315            from fortiosapi import FortiOSAPI
316        except ImportError:
317            module.fail_json(msg="fortiosapi module is required")
318
319        fos = FortiOSAPI()
320
321        login(module.params, fos)
322        is_error, has_changed, result = fortios_dlp(module.params, fos)
323        fos.logout()
324
325    if not is_error:
326        module.exit_json(changed=has_changed, meta=result)
327    else:
328        module.fail_json(msg="Error in repo", meta=result)
329
330
331if __name__ == '__main__':
332    main()
333