1#!/usr/bin/python
2'''
3(c) 2019, Red Hat, Inc
4GNU General Public License v3.0+
5(see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
6'''
7
8from __future__ import absolute_import, division, print_function
9__metaclass__ = type
10
11ANSIBLE_METADATA = {'metadata_version': '1.1',
12                    'status': ['preview'],
13                    'supported_by': 'certified'}
14
15DOCUMENTATION = '''
16
17module: na_ontap_kerberos_realm
18
19short_description: NetApp ONTAP vserver nfs kerberos realm
20extends_documentation_fragment:
21    - netapp.na_ontap
22version_added: '2.9'
23author: Milan Zink (@zeten30) <zeten30@gmail.com>,<mzink@redhat.com>
24
25description:
26- Create, modify or delete vserver kerberos realm configuration
27
28options:
29
30  state:
31    description:
32    - Whether the Kerberos realm is present or absent.
33    choices: ['present', 'absent']
34    default: 'present'
35    type: str
36
37  vserver:
38    description:
39    - vserver/svm with kerberos realm configured
40    required: true
41    type: str
42
43  realm:
44    description:
45    - Kerberos realm name
46    required: true
47    type: str
48
49  kdc_vendor:
50    description:
51    - The vendor of the Key Distribution Centre (KDC) server
52    - Required if I(state=present)
53    choices: ['Other', 'Microsoft']
54    type: str
55
56  kdc_ip:
57    description:
58    - IP address of the Key Distribution Centre (KDC) server
59    - Required if I(state=present)
60    type: str
61
62  kdc_port:
63    description:
64    - TCP port on the KDC to be used for Kerberos communication.
65    - The default for this parameter is '88'.
66    type: str
67
68  clock_skew:
69    description:
70    - The clock skew in minutes is the tolerance for accepting tickets with time stamps that do not exactly match the host's system clock.
71    - The default for this parameter is '5' minutes.
72    type: str
73
74  comment:
75    description:
76    - Optional comment
77    type: str
78
79  admin_server_ip:
80    description:
81    - IP address of the host where the Kerberos administration daemon is running. This is usually the master KDC.
82    - If this parameter is omitted, the address specified in kdc_ip is used.
83    type: str
84
85  admin_server_port:
86    description:
87    - The TCP port on the Kerberos administration server where the Kerberos administration service is running.
88    - The default for this parameter is '749'
89    type: str
90
91  pw_server_ip:
92    description:
93    - IP address of the host where the Kerberos password-changing server is running.
94    - Typically, this is the same as the host indicated in the adminserver-ip.
95    - If this parameter is omitted, the IP address in kdc-ip is used.
96    type: str
97
98  pw_server_port:
99    description:
100    - The TCP port on the Kerberos password-changing server where the Kerberos password-changing service is running.
101    - The default for this parameter is '464'.
102    type: str
103'''
104
105EXAMPLES = '''
106
107    - name: Create kerberos realm
108      na_ontap_kerberos_realm:
109        state:         present
110        realm:         'EXAMPLE.COM'
111        vserver:       'vserver1'
112        kdc_ip:        '1.2.3.4'
113        kdc_vendor:    'Other'
114        hostname:      "{{ netapp_hostname }}"
115        username:      "{{ netapp_username }}"
116        password:      "{{ netapp_password }}"
117
118'''
119
120RETURN = '''
121'''
122
123import traceback
124import ansible.module_utils.netapp as netapp_utils
125from ansible.module_utils.netapp_module import NetAppModule
126from ansible.module_utils._text import to_native
127from ansible.module_utils.basic import AnsibleModule
128
129HAS_NETAPP_LIB = netapp_utils.has_netapp_lib()
130
131
132class NetAppOntapKerberosRealm(object):
133    '''
134    Kerberos Realm definition class
135    '''
136
137    def __init__(self):
138        self.argument_spec = netapp_utils.na_ontap_host_argument_spec()
139        self.argument_spec.update(dict(
140            admin_server_ip=dict(required=False, default=None, type='str'),
141            admin_server_port=dict(required=False, default=None, type='str'),
142            clock_skew=dict(required=False, default=None, type='str'),
143            comment=dict(required=False, default=None, type='str'),
144            kdc_ip=dict(required_if=[["state", "present"]], default=None, type='str'),
145            kdc_port=dict(required=False, default=None, type='str'),
146            kdc_vendor=dict(required_if=[["state", "present"]], default=None, type='str', choices=['Microsoft', 'Other']),
147            pw_server_ip=dict(required=False, default=None, type='str'),
148            pw_server_port=dict(required=False, default=None, type='str'),
149            realm=dict(required=True, type='str'),
150            state=dict(required=False, choices=['present', 'absent'], default='present'),
151            vserver=dict(required=True, type='str')
152        ))
153
154        self.module = AnsibleModule(
155            argument_spec=self.argument_spec,
156            supports_check_mode=True,
157            required_if=[('state', 'present', ['kdc_vendor', 'kdc_ip'])],
158        )
159        self.na_helper = NetAppModule()
160        self.parameters = self.na_helper.set_parameters(self.module.params)
161
162        if HAS_NETAPP_LIB is False:
163            self.module.fail_json(
164                msg="the python NetApp-Lib module is required")
165        else:
166            self.server = netapp_utils.setup_na_ontap_zapi(module=self.module, vserver=self.parameters['vserver'])
167
168        self.simple_attributes = [
169            'admin_server_ip',
170            'admin_server_port',
171            'clock_skew',
172            'kdc_ip',
173            'kdc_port',
174            'kdc_vendor',
175        ]
176
177    def get_krbrealm(self, realm_name=None, vserver_name=None):
178        '''
179        Checks if Kerberos Realm config exists.
180
181        :return:
182            kerberos realm object if found
183            None if not found
184        :rtype: object/None
185        '''
186        # Make query
187        krbrealm_info = netapp_utils.zapi.NaElement('kerberos-realm-get-iter')
188
189        if realm_name is None:
190            realm_name = self.parameters['realm']
191
192        if vserver_name is None:
193            vserver_name = self.parameters['vserver']
194
195        query_details = netapp_utils.zapi.NaElement.create_node_with_children('kerberos-realm', **{'realm': realm_name, 'vserver-name': vserver_name})
196
197        query = netapp_utils.zapi.NaElement('query')
198        query.add_child_elem(query_details)
199        krbrealm_info.add_child_elem(query)
200
201        result = self.server.invoke_successfully(krbrealm_info, enable_tunneling=True)
202
203        # Get Kerberos Realm details
204        krbrealm_details = None
205        if (result.get_child_by_name('num-records') and int(result.get_child_content('num-records')) >= 1):
206            attributes_list = result.get_child_by_name('attributes-list')
207            config_info = attributes_list.get_child_by_name('kerberos-realm')
208
209            krbrealm_details = {
210                'admin_server_ip': config_info.get_child_content('admin-server-ip'),
211                'admin_server_port': config_info.get_child_content('admin-server-port'),
212                'clock_skew': config_info.get_child_content('clock-skew'),
213                'kdc_ip': config_info.get_child_content('kdc-ip'),
214                'kdc_port': config_info.get_child_content('kdc-port'),
215                'kdc_vendor': config_info.get_child_content('kdc-vendor'),
216                'pw_server_ip': config_info.get_child_content('password-server-ip'),
217                'pw_server_port': config_info.get_child_content('password-server-port'),
218                'realm': config_info.get_child_content('realm'),
219                'vserver': config_info.get_child_content('vserver'),
220            }
221
222        return krbrealm_details
223
224    def create_krbrealm(self):
225        '''supported
226        Create Kerberos Realm configuration
227        '''
228        options = {
229            'realm': self.parameters['realm']
230        }
231
232        # Other options/attributes
233        for attribute in self.simple_attributes:
234            if self.parameters.get(attribute) is not None:
235                options[str(attribute).replace('_', '-')] = self.parameters[attribute]
236
237        if self.parameters.get('pw_server_ip') is not None:
238            options['password-server-ip'] = self.parameters['pw_server_ip']
239        if self.parameters.get('pw_server_port') is not None:
240            options['password-server-port'] = self.parameters['pw_server_port']
241
242        # Initialize NaElement
243        krbrealm_create = netapp_utils.zapi.NaElement.create_node_with_children('kerberos-realm-create', **options)
244
245        # Try to create Kerberos Realm configuration
246        try:
247            self.server.invoke_successfully(krbrealm_create, enable_tunneling=True)
248        except netapp_utils.zapi.NaApiError as errcatch:
249            self.module.fail_json(msg='Error creating Kerberos Realm configuration %s: %s' % (self.parameters['realm'], to_native(errcatch)),
250                                  exception=traceback.format_exc())
251
252    def delete_krbrealm(self):
253        '''
254        Delete Kerberos Realm configuration
255        '''
256        krbrealm_delete = netapp_utils.zapi.NaElement.create_node_with_children('kerberos-realm-delete', **{'realm': self.parameters['realm']})
257
258        try:
259            self.server.invoke_successfully(krbrealm_delete, enable_tunneling=True)
260        except netapp_utils.zapi.NaApiError as errcatch:
261            self.module.fail_json(msg='Error deleting Kerberos Realm configuration %s: %s' % (
262                self.parameters['realm'], to_native(errcatch)), exception=traceback.format_exc())
263
264    def modify_krbrealm(self, modify):
265        '''
266        Modify Kerberos Realm
267        :param modify: list of modify attributes
268        '''
269        krbrealm_modify = netapp_utils.zapi.NaElement('kerberos-realm-modify')
270        krbrealm_modify.add_new_child('realm', self.parameters['realm'])
271
272        for attribute in modify:
273            if attribute in self.simple_attributes:
274                krbrealm_modify.add_new_child(str(attribute).replace('_', '-'), self.parameters[attribute])
275            if attribute == 'pw_server_ip':
276                krbrealm_modify.add_new_child('password-server-ip', self.parameters['pw_server_ip'])
277            if attribute == 'pw_server_port':
278                krbrealm_modify.add_new_child('password-server-port', self.parameters['pw_server_port'])
279
280        # Try to modify Kerberos Realm
281        try:
282            self.server.invoke_successfully(krbrealm_modify, enable_tunneling=True)
283        except netapp_utils.zapi.NaApiError as errcatch:
284            self.module.fail_json(msg='Error modifying Kerberos Realm %s: %s' % (self.parameters['realm'], to_native(errcatch)),
285                                  exception=traceback.format_exc())
286
287    def apply(self):
288        '''Call create/modify/delete operations.'''
289        current = self.get_krbrealm()
290        cd_action = self.na_helper.get_cd_action(current, self.parameters)
291        modify = self.na_helper.get_modified_attributes(current, self.parameters)
292        #  create an ems log event for users with auto support turned on
293        netapp_utils.ems_log_event("na_ontap_kerberos_realm", self.server)
294
295        if self.na_helper.changed:
296            if self.module.check_mode:
297                pass
298            else:
299                if cd_action == 'create':
300                    self.create_krbrealm()
301                elif cd_action == 'delete':
302                    self.delete_krbrealm()
303                elif modify:
304                    self.modify_krbrealm(modify)
305        self.module.exit_json(changed=self.na_helper.changed)
306
307
308#
309# MAIN
310#
311def main():
312    '''ONTAP Kerberos Realm'''
313    krbrealm = NetAppOntapKerberosRealm()
314    krbrealm.apply()
315
316
317if __name__ == '__main__':
318    main()
319