From a6f0a279a94983c086142e857e2077d9e4f903cb Mon Sep 17 00:00:00 2001 From: Matthew Krupcale Date: Sun, 4 Dec 2016 05:44:43 -0500 Subject: [PATCH] FreeIPA module polymorphic restructuring and small fixes. (#3485) * Moved JSON-RPC client IPAClient class to ansible.module_utils.ipa, which is extended by all ipa modules * ipa_user: incorporate displayname and userpassword attributes in module_user * ipa_user: capitalized "I" in comment * ipa_user: updated get_ssh_key_fingerprint to include possibility of the uploaded SSH key including user@hostname comment, which also appears in the queried fingerprint. This fixes a mismatch in the calculated and queried SSH key fingerprint in the user_diff calculation when the user already exists. * ipa_hbacrule: ipaenabledflag must be 'TRUE' or 'FALSE', not 'NO' * ipa_sudorule: ipaenabledflag must be 'TRUE' or 'FALSE', not 'NO' * Add author to files missing it --- .../modules/extras/identity/ipa/ipa_group.py | 88 ++------------ .../extras/identity/ipa/ipa_hbacrule.py | 90 ++------------ .../modules/extras/identity/ipa/ipa_host.py | 89 ++------------ .../extras/identity/ipa/ipa_hostgroup.py | 89 ++------------ .../modules/extras/identity/ipa/ipa_role.py | 89 ++------------ .../extras/identity/ipa/ipa_sudocmd.py | 88 ++------------ .../extras/identity/ipa/ipa_sudocmdgroup.py | 88 ++------------ .../extras/identity/ipa/ipa_sudorule.py | 90 ++------------ .../modules/extras/identity/ipa/ipa_user.py | 115 ++++-------------- 9 files changed, 88 insertions(+), 738 deletions(-) diff --git a/lib/ansible/modules/extras/identity/ipa/ipa_group.py b/lib/ansible/modules/extras/identity/ipa/ipa_group.py index 0c45776a23f..246b769dd0d 100644 --- a/lib/ansible/modules/extras/identity/ipa/ipa_group.py +++ b/lib/ansible/modules/extras/identity/ipa/ipa_group.py @@ -87,8 +87,6 @@ options: required: false default: true version_added: "2.3" -requirements: -- json ''' EXAMPLES = ''' @@ -137,83 +135,12 @@ group: type: dict ''' -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.ipa import IPAClient +class GroupIPAClient(IPAClient): -class IPAClient: def __init__(self, module, host, port, protocol): - self.host = host - self.port = port - self.protocol = protocol - self.module = module - self.headers = None - - def get_base_url(self): - return '%s://%s/ipa' % (self.protocol, self.host) - - def get_json_url(self): - return '%s/session/json' % self.get_base_url() - - def login(self, username, password): - url = '%s/session/login_password' % self.get_base_url() - data = 'user=%s&password=%s' % (username, password) - headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'text/plain'} - try: - resp, info = fetch_url(module=self.module, url=url, data=data, headers=headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail('login', info['body']) - - self.headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Cookie': resp.info().getheader('Set-Cookie')} - except Exception: - e = get_exception() - self._fail('login', str(e)) - - def _fail(self, msg, e): - if 'message' in e: - err_string = e.get('message') - else: - err_string = e - self.module.fail_json(msg='%s: %s' % (msg, err_string)) - - def _post_json(self, method, name, item=None): - if item is None: - item = {} - url = '%s/session/json' % self.get_base_url() - data = {'method': method, 'params': [[name], item]} - try: - resp, info = fetch_url(module=self.module, url=url, data=json.dumps(data), headers=self.headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail(method, info['body']) - except Exception: - e = get_exception() - self._fail('post %s' % method, str(e)) - - resp = json.loads(resp.read()) - err = resp.get('error') - if err is not None: - self._fail('repsonse %s' % method, err) - - if 'result' in resp: - result = resp.get('result') - if 'result' in result: - result = result.get('result') - if isinstance(result, list): - if len(result) > 0: - return result[0] - else: - return {} - return result - return None + super(GroupIPAClient, self).__init__(module, host, port, protocol) def group_find(self, name): return self._post_json(method='group_find', name=None, item={'all': True, 'cn': name}) @@ -364,10 +291,10 @@ def main(): supports_check_mode=True, ) - client = IPAClient(module=module, - host=module.params['ipa_host'], - port=module.params['ipa_port'], - protocol=module.params['ipa_prot']) + client = GroupIPAClient(module=module, + host=module.params['ipa_host'], + port=module.params['ipa_port'], + protocol=module.params['ipa_prot']) try: client.login(username=module.params['ipa_user'], password=module.params['ipa_pass']) @@ -380,7 +307,6 @@ def main(): from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception -from ansible.module_utils.urls import fetch_url if __name__ == '__main__': main() diff --git a/lib/ansible/modules/extras/identity/ipa/ipa_hbacrule.py b/lib/ansible/modules/extras/identity/ipa/ipa_hbacrule.py index 54619c5ec33..29661fe77bf 100644 --- a/lib/ansible/modules/extras/identity/ipa/ipa_hbacrule.py +++ b/lib/ansible/modules/extras/identity/ipa/ipa_hbacrule.py @@ -122,8 +122,6 @@ options: required: false default: true version_added: "2.3" -requirements: -- json ''' EXAMPLES = ''' @@ -168,83 +166,12 @@ hbacrule: type: dict ''' -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.ipa import IPAClient +class HBACRuleIPAClient(IPAClient): -class IPAClient: def __init__(self, module, host, port, protocol): - self.host = host - self.port = port - self.protocol = protocol - self.module = module - self.headers = None - - def get_base_url(self): - return '%s://%s/ipa' % (self.protocol, self.host) - - def get_json_url(self): - return '%s/session/json' % self.get_base_url() - - def login(self, username, password): - url = '%s/session/login_password' % self.get_base_url() - data = 'user=%s&password=%s' % (username, password) - headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'text/plain'} - try: - resp, info = fetch_url(module=self.module, url=url, data=data, headers=headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail('login', info['body']) - - self.headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Cookie': resp.info().getheader('Set-Cookie')} - except Exception: - e = get_exception() - self._fail('login', str(e)) - - def _fail(self, msg, e): - if 'message' in e: - err_string = e.get('message') - else: - err_string = e - self.module.fail_json(msg='%s: %s' % (msg, err_string)) - - def _post_json(self, method, name, item=None): - if item is None: - item = {} - url = '%s/session/json' % self.get_base_url() - data = {'method': method, 'params': [[name], item]} - try: - resp, info = fetch_url(module=self.module, url=url, data=json.dumps(data), headers=self.headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail(method, info['body']) - except Exception: - e = get_exception() - self._fail('post %s' % method, str(e)) - - resp = json.loads(resp.read()) - err = resp.get('error') - if err is not None: - self._fail('repsonse %s' % method, err) - - if 'result' in resp: - result = resp.get('result') - if 'result' in result: - result = result.get('result') - if isinstance(result, list): - if len(result) > 0: - return result[0] - else: - return {} - return result - return None + super(HBACRuleIPAClient, self).__init__(module, host, port, protocol) def hbacrule_find(self, name): return self._post_json(method='hbacrule_find', name=None, item={'all': True, 'cn': name}) @@ -341,7 +268,7 @@ def ensure(module, client): if state in ['present', 'enabled']: ipaenabledflag = 'TRUE' else: - ipaenabledflag = 'NO' + ipaenabledflag = 'FALSE' host = module.params['host'] hostcategory = module.params['hostcategory'] @@ -458,10 +385,10 @@ def main(): supports_check_mode=True, ) - client = IPAClient(module=module, - host=module.params['ipa_host'], - port=module.params['ipa_port'], - protocol=module.params['ipa_prot']) + client = HBACRuleIPAClient(module=module, + host=module.params['ipa_host'], + port=module.params['ipa_port'], + protocol=module.params['ipa_prot']) try: client.login(username=module.params['ipa_user'], @@ -475,7 +402,6 @@ def main(): from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception -from ansible.module_utils.urls import fetch_url if __name__ == '__main__': main() diff --git a/lib/ansible/modules/extras/identity/ipa/ipa_host.py b/lib/ansible/modules/extras/identity/ipa/ipa_host.py index a7cc4d361e2..59c6772673d 100644 --- a/lib/ansible/modules/extras/identity/ipa/ipa_host.py +++ b/lib/ansible/modules/extras/identity/ipa/ipa_host.py @@ -18,6 +18,7 @@ DOCUMENTATION = ''' --- module: ipa_host +author: Thomas Krahn (@Nosmoht) short_description: Manage FreeIPA host description: - Add, modify and delete an IPA host using IPA API @@ -104,8 +105,6 @@ options: required: false default: true version_added: "2.3" -requirements: -- json ''' EXAMPLES = ''' @@ -161,83 +160,12 @@ host_diff: type: list ''' -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.ipa import IPAClient +class HostIPAClient(IPAClient): -class IPAClient: def __init__(self, module, host, port, protocol): - self.host = host - self.port = port - self.protocol = protocol - self.module = module - self.headers = None - - def get_base_url(self): - return '%s://%s/ipa' % (self.protocol, self.host) - - def get_json_url(self): - return '%s/session/json' % self.get_base_url() - - def login(self, username, password): - url = '%s/session/login_password' % self.get_base_url() - data = 'user=%s&password=%s' % (username, password) - headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'text/plain'} - try: - resp, info = fetch_url(module=self.module, url=url, data=data, headers=headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail('login', info['body']) - - self.headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Cookie': resp.info().getheader('Set-Cookie')} - except Exception: - e = get_exception() - self._fail('login', str(e)) - - def _fail(self, msg, e): - if 'message' in e: - err_string = e.get('message') - else: - err_string = e - self.module.fail_json(msg='%s: %s' % (msg, err_string)) - - def _post_json(self, method, name, item=None): - if item is None: - item = {} - url = '%s/session/json' % self.get_base_url() - data = {'method': method, 'params': [[name], item]} - try: - resp, info = fetch_url(module=self.module, url=url, data=json.dumps(data), headers=self.headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail(method, info['body']) - except Exception: - e = get_exception() - self._fail('post %s' % method, str(e)) - - resp = json.loads(resp.read()) - err = resp.get('error') - if err is not None: - self._fail('repsonse %s' % method, err) - - if 'result' in resp: - result = resp.get('result') - if 'result' in result: - result = result.get('result') - if isinstance(result, list): - if len(result) > 0: - return result[0] - else: - return {} - return result - return None + super(HostIPAClient, self).__init__(module, host, port, protocol) def host_find(self, name): return self._post_json(method='host_find', name=None, item={'all': True, 'fqdn': name}) @@ -357,10 +285,10 @@ def main(): supports_check_mode=True, ) - client = IPAClient(module=module, - host=module.params['ipa_host'], - port=module.params['ipa_port'], - protocol=module.params['ipa_prot']) + client = HostIPAClient(module=module, + host=module.params['ipa_host'], + port=module.params['ipa_port'], + protocol=module.params['ipa_prot']) try: client.login(username=module.params['ipa_user'], @@ -374,7 +302,6 @@ def main(): from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception -from ansible.module_utils.urls import fetch_url if __name__ == '__main__': main() diff --git a/lib/ansible/modules/extras/identity/ipa/ipa_hostgroup.py b/lib/ansible/modules/extras/identity/ipa/ipa_hostgroup.py index f0350277313..ba1ee33b8ac 100644 --- a/lib/ansible/modules/extras/identity/ipa/ipa_hostgroup.py +++ b/lib/ansible/modules/extras/identity/ipa/ipa_hostgroup.py @@ -18,6 +18,7 @@ DOCUMENTATION = ''' --- module: ipa_hostgroup +author: Thomas Krahn (@Nosmoht) short_description: Manage FreeIPA host-group description: - Add, modify and delete an IPA host-group using IPA API @@ -80,8 +81,6 @@ options: required: false default: true version_added: "2.3" -requirements: -- json ''' EXAMPLES = ''' @@ -114,83 +113,12 @@ hostgroup: type: dict ''' -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.ipa import IPAClient +class HostGroupIPAClient(IPAClient): -class IPAClient: def __init__(self, module, host, port, protocol): - self.host = host - self.port = port - self.protocol = protocol - self.module = module - self.headers = None - - def get_base_url(self): - return '%s://%s/ipa' % (self.protocol, self.host) - - def get_json_url(self): - return '%s/session/json' % self.get_base_url() - - def login(self, username, password): - url = '%s/session/login_password' % self.get_base_url() - data = 'user=%s&password=%s' % (username, password) - headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'text/plain'} - try: - resp, info = fetch_url(module=self.module, url=url, data=data, headers=headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail('login', info['body']) - - self.headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Cookie': resp.info().getheader('Set-Cookie')} - except Exception: - e = get_exception() - self._fail('login', str(e)) - - def _fail(self, msg, e): - if 'message' in e: - err_string = e.get('message') - else: - err_string = e - self.module.fail_json(msg='%s: %s' % (msg, err_string)) - - def _post_json(self, method, name, item=None): - if item is None: - item = {} - url = '%s/session/json' % self.get_base_url() - data = {'method': method, 'params': [[name], item]} - try: - resp, info = fetch_url(module=self.module, url=url, data=json.dumps(data), headers=self.headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail(method, info['body']) - except Exception: - e = get_exception() - self._fail('post %s' % method, str(e)) - - resp = json.loads(resp.read()) - err = resp.get('error') - if err is not None: - self._fail('repsonse %s' % method, err) - - if 'result' in resp: - result = resp.get('result') - if 'result' in result: - result = result.get('result') - if isinstance(result, list): - if len(result) > 0: - return result[0] - else: - return {} - return result - return None + super(HostGroupIPAClient, self).__init__(module, host, port, protocol) def hostgroup_find(self, name): return self._post_json(method='hostgroup_find', name=None, item={'all': True, 'cn': name}) @@ -324,10 +252,10 @@ def main(): supports_check_mode=True, ) - client = IPAClient(module=module, - host=module.params['ipa_host'], - port=module.params['ipa_port'], - protocol=module.params['ipa_prot']) + client = HostGroupIPAClient(module=module, + host=module.params['ipa_host'], + port=module.params['ipa_port'], + protocol=module.params['ipa_prot']) try: client.login(username=module.params['ipa_user'], @@ -341,7 +269,6 @@ def main(): from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception -from ansible.module_utils.urls import fetch_url if __name__ == '__main__': main() diff --git a/lib/ansible/modules/extras/identity/ipa/ipa_role.py b/lib/ansible/modules/extras/identity/ipa/ipa_role.py index 9d3ac043f3a..9740a4d4a4d 100644 --- a/lib/ansible/modules/extras/identity/ipa/ipa_role.py +++ b/lib/ansible/modules/extras/identity/ipa/ipa_role.py @@ -18,6 +18,7 @@ DOCUMENTATION = ''' --- module: ipa_role +author: Thomas Krahn (@Nosmoht) short_description: Manage FreeIPA role description: - Add, modify and delete a role within FreeIPA server using FreeIPA API @@ -98,8 +99,6 @@ options: required: false default: true version_added: "2.3" -requirements: -- json ''' EXAMPLES = ''' @@ -144,83 +143,12 @@ role: type: dict ''' -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.ipa import IPAClient +class RoleIPAClient(IPAClient): -class IPAClient: def __init__(self, module, host, port, protocol): - self.host = host - self.port = port - self.protocol = protocol - self.module = module - self.headers = None - - def get_base_url(self): - return '%s://%s/ipa' % (self.protocol, self.host) - - def get_json_url(self): - return '%s/session/json' % self.get_base_url() - - def login(self, username, password): - url = '%s/session/login_password' % self.get_base_url() - data = 'user=%s&password=%s' % (username, password) - headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'text/plain'} - try: - resp, info = fetch_url(module=self.module, url=url, data=data, headers=headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail('login', info['body']) - - self.headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Cookie': resp.info().getheader('Set-Cookie')} - except Exception: - e = get_exception() - self._fail('login', str(e)) - - def _fail(self, msg, e): - if 'message' in e: - err_string = e.get('message') - else: - err_string = e - self.module.fail_json(msg='%s: %s' % (msg, err_string)) - - def _post_json(self, method, name, item=None): - if item is None: - item = {} - url = '%s/session/json' % self.get_base_url() - data = {'method': method, 'params': [[name], item]} - try: - resp, info = fetch_url(module=self.module, url=url, data=json.dumps(data), headers=self.headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail(method, info['body']) - except Exception: - e = get_exception() - self._fail('post %s' % method, str(e)) - - resp = json.loads(resp.read()) - err = resp.get('error') - if err is not None: - self._fail('repsonse %s' % method, err) - - if 'result' in resp: - result = resp.get('result') - if 'result' in result: - result = result.get('result') - if isinstance(result, list): - if len(result) > 0: - return result[0] - else: - return {} - return result - return None + super(RoleIPAClient, self).__init__(module, host, port, protocol) def role_find(self, name): return self._post_json(method='role_find', name=None, item={'all': True, 'cn': name}) @@ -390,10 +318,10 @@ def main(): supports_check_mode=True, ) - client = IPAClient(module=module, - host=module.params['ipa_host'], - port=module.params['ipa_port'], - protocol=module.params['ipa_prot']) + client = RoleIPAClient(module=module, + host=module.params['ipa_host'], + port=module.params['ipa_port'], + protocol=module.params['ipa_prot']) try: client.login(username=module.params['ipa_user'], @@ -407,7 +335,6 @@ def main(): from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception -from ansible.module_utils.urls import fetch_url if __name__ == '__main__': main() diff --git a/lib/ansible/modules/extras/identity/ipa/ipa_sudocmd.py b/lib/ansible/modules/extras/identity/ipa/ipa_sudocmd.py index f759f2d726f..0a86bf68821 100644 --- a/lib/ansible/modules/extras/identity/ipa/ipa_sudocmd.py +++ b/lib/ansible/modules/extras/identity/ipa/ipa_sudocmd.py @@ -65,8 +65,6 @@ options: required: false default: true version_added: "2.3" -requirements: -- json ''' EXAMPLES = ''' @@ -94,83 +92,12 @@ sudocmd: type: dict ''' -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.ipa import IPAClient +class SudoCmdIPAClient(IPAClient): -class IPAClient: def __init__(self, module, host, port, protocol): - self.host = host - self.port = port - self.protocol = protocol - self.module = module - self.headers = None - - def get_base_url(self): - return '%s://%s/ipa' % (self.protocol, self.host) - - def get_json_url(self): - return '%s/session/json' % self.get_base_url() - - def login(self, username, password): - url = '%s/session/login_password' % self.get_base_url() - data = 'user=%s&password=%s' % (username, password) - headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'text/plain'} - try: - resp, info = fetch_url(module=self.module, url=url, data=data, headers=headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail('login', info['body']) - - self.headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Cookie': resp.info().getheader('Set-Cookie')} - except Exception: - e = get_exception() - self._fail('login', str(e)) - - def _fail(self, msg, e): - if 'message' in e: - err_string = e.get('message') - else: - err_string = e - self.module.fail_json(msg='%s: %s' % (msg, err_string)) - - def _post_json(self, method, name, item=None): - if item is None: - item = {} - url = '%s/session/json' % self.get_base_url() - data = {'method': method, 'params': [[name], item]} - try: - resp, info = fetch_url(module=self.module, url=url, data=json.dumps(data), headers=self.headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail(method, info['body']) - except Exception: - e = get_exception() - self._fail('post %s' % method, str(e)) - - resp = json.loads(resp.read()) - err = resp.get('error') - if err is not None: - self._fail('repsonse %s' % method, err) - - if 'result' in resp: - result = resp.get('result') - if 'result' in result: - result = result.get('result') - if isinstance(result, list): - if len(result) > 0: - return result[0] - else: - return {} - return result - return None + super(SudoCmdIPAClient, self).__init__(module, host, port, protocol) def sudocmd_find(self, name): return self._post_json(method='sudocmd_find', name=None, item={'all': True, 'sudocmd': name}) @@ -255,10 +182,10 @@ def main(): supports_check_mode=True, ) - client = IPAClient(module=module, - host=module.params['ipa_host'], - port=module.params['ipa_port'], - protocol=module.params['ipa_prot']) + client = SudoCmdIPAClient(module=module, + host=module.params['ipa_host'], + port=module.params['ipa_port'], + protocol=module.params['ipa_prot']) try: client.login(username=module.params['ipa_user'], password=module.params['ipa_pass']) @@ -271,7 +198,6 @@ def main(): from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception -from ansible.module_utils.urls import fetch_url if __name__ == '__main__': main() diff --git a/lib/ansible/modules/extras/identity/ipa/ipa_sudocmdgroup.py b/lib/ansible/modules/extras/identity/ipa/ipa_sudocmdgroup.py index b29216f70cd..b6730bccefe 100644 --- a/lib/ansible/modules/extras/identity/ipa/ipa_sudocmdgroup.py +++ b/lib/ansible/modules/extras/identity/ipa/ipa_sudocmdgroup.py @@ -70,8 +70,6 @@ options: required: false default: true version_added: "2.3" -requirements: -- json ''' EXAMPLES = ''' @@ -101,83 +99,12 @@ sudocmdgroup: type: dict ''' -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.ipa import IPAClient +class SudoCmdGroupIPAClient(IPAClient): -class IPAClient: def __init__(self, module, host, port, protocol): - self.host = host - self.port = port - self.protocol = protocol - self.module = module - self.headers = None - - def get_base_url(self): - return '%s://%s/ipa' % (self.protocol, self.host) - - def get_json_url(self): - return '%s/session/json' % self.get_base_url() - - def login(self, username, password): - url = '%s/session/login_password' % self.get_base_url() - data = 'user=%s&password=%s' % (username, password) - headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'text/plain'} - try: - resp, info = fetch_url(module=self.module, url=url, data=data, headers=headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail('login', info['body']) - - self.headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Cookie': resp.info().getheader('Set-Cookie')} - except Exception: - e = get_exception() - self._fail('login', str(e)) - - def _fail(self, msg, e): - if 'message' in e: - err_string = e.get('message') - else: - err_string = e - self.module.fail_json(msg='%s: %s' % (msg, err_string)) - - def _post_json(self, method, name, item=None): - if item is None: - item = {} - url = '%s/session/json' % self.get_base_url() - data = {'method': method, 'params': [[name], item]} - try: - resp, info = fetch_url(module=self.module, url=url, data=json.dumps(data), headers=self.headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail(method, info['body']) - except Exception: - e = get_exception() - self._fail('post %s' % method, str(e)) - - resp = json.loads(resp.read()) - err = resp.get('error') - if err is not None: - self._fail('repsonse %s' % method, err) - - if 'result' in resp: - result = resp.get('result') - if 'result' in result: - result = result.get('result') - if isinstance(result, list): - if len(result) > 0: - return result[0] - else: - return {} - return result - return None + super(SudoCmdGroupIPAClient, self).__init__(module, host, port, protocol) def sudocmdgroup_find(self, name): return self._post_json(method='sudocmdgroup_find', name=None, item={'all': True, 'cn': name}) @@ -297,10 +224,10 @@ def main(): supports_check_mode=True, ) - client = IPAClient(module=module, - host=module.params['ipa_host'], - port=module.params['ipa_port'], - protocol=module.params['ipa_prot']) + client = SudoCmdGroupIPAClient(module=module, + host=module.params['ipa_host'], + port=module.params['ipa_port'], + protocol=module.params['ipa_prot']) try: client.login(username=module.params['ipa_user'], password=module.params['ipa_pass']) @@ -313,7 +240,6 @@ def main(): from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception -from ansible.module_utils.urls import fetch_url if __name__ == '__main__': main() diff --git a/lib/ansible/modules/extras/identity/ipa/ipa_sudorule.py b/lib/ansible/modules/extras/identity/ipa/ipa_sudorule.py index 426a4444ecc..b8a4c062777 100644 --- a/lib/ansible/modules/extras/identity/ipa/ipa_sudorule.py +++ b/lib/ansible/modules/extras/identity/ipa/ipa_sudorule.py @@ -111,8 +111,6 @@ options: required: false default: true version_added: "2.3" -requirements: -- json ''' EXAMPLES = ''' @@ -153,83 +151,12 @@ sudorule: type: dict ''' -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.ipa import IPAClient +class SudoRuleIPAClient(IPAClient): -class IPAClient: def __init__(self, module, host, port, protocol): - self.host = host - self.port = port - self.protocol = protocol - self.module = module - self.headers = None - - def get_base_url(self): - return '%s://%s/ipa' % (self.protocol, self.host) - - def get_json_url(self): - return '%s/session/json' % self.get_base_url() - - def login(self, username, password): - url = '%s/session/login_password' % self.get_base_url() - data = 'user=%s&password=%s' % (username, password) - headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'text/plain'} - try: - resp, info = fetch_url(module=self.module, url=url, data=data, headers=headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail('login', info['body']) - - self.headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Cookie': resp.info().getheader('Set-Cookie')} - except Exception: - e = get_exception() - self._fail('login', str(e)) - - def _fail(self, msg, e): - if 'message' in e: - err_string = e.get('message') - else: - err_string = e - self.module.fail_json(msg='%s: %s' % (msg, err_string)) - - def _post_json(self, method, name, item=None): - if item is None: - item = {} - url = '%s/session/json' % self.get_base_url() - data = {'method': method, 'params': [[name], item]} - try: - resp, info = fetch_url(module=self.module, url=url, data=json.dumps(data), headers=self.headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail(method, info['body']) - except Exception: - e = get_exception() - self._fail('post %s' % method, str(e)) - - resp = json.loads(resp.read()) - err = resp.get('error') - if err is not None: - self._fail('repsonse %s' % method, err) - - if 'result' in resp: - result = resp.get('result') - if 'result' in result: - result = result.get('result') - if isinstance(result, list): - if len(result) > 0: - return result[0] - else: - return {} - return result - return None + super(SudoRuleIPAClient, self).__init__(module, host, port, protocol) def sudorule_find(self, name): return self._post_json(method='sudorule_find', name=None, item={'all': True, 'cn': name}) @@ -368,7 +295,7 @@ def ensure(module, client): if state in ['present', 'enabled']: ipaenabledflag = 'TRUE' else: - ipaenabledflag = 'NO' + ipaenabledflag = 'FALSE' sudoopt = module.params['sudoopt'] user = module.params['user'] @@ -472,10 +399,10 @@ def main(): supports_check_mode=True, ) - client = IPAClient(module=module, - host=module.params['ipa_host'], - port=module.params['ipa_port'], - protocol=module.params['ipa_prot']) + client = SudoRuleIPAClient(module=module, + host=module.params['ipa_host'], + port=module.params['ipa_port'], + protocol=module.params['ipa_prot']) try: client.login(username=module.params['ipa_user'], password=module.params['ipa_pass']) @@ -488,7 +415,6 @@ def main(): from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception -from ansible.module_utils.urls import fetch_url if __name__ == '__main__': main() diff --git a/lib/ansible/modules/extras/identity/ipa/ipa_user.py b/lib/ansible/modules/extras/identity/ipa/ipa_user.py index 464348ee9bc..9ee677b6653 100644 --- a/lib/ansible/modules/extras/identity/ipa/ipa_user.py +++ b/lib/ansible/modules/extras/identity/ipa/ipa_user.py @@ -18,6 +18,7 @@ DOCUMENTATION = ''' --- module: ipa_user +author: Thomas Krahn (@Nosmoht) short_description: Manage FreeIPA users description: - Add, modify and delete user within IPA server @@ -99,7 +100,6 @@ version_added: "2.3" requirements: - base64 - hashlib -- json ''' EXAMPLES = ''' @@ -139,83 +139,12 @@ user: import base64 import hashlib -try: - import json -except ImportError: - import simplejson as json +from ansible.module_utils.ipa import IPAClient +class UserIPAClient(IPAClient): -class IPAClient: def __init__(self, module, host, port, protocol): - self.host = host - self.port = port - self.protocol = protocol - self.module = module - self.headers = None - - def get_base_url(self): - return '%s://%s/ipa' % (self.protocol, self.host) - - def get_json_url(self): - return '%s/session/json' % self.get_base_url() - - def login(self, username, password): - url = '%s/session/login_password' % self.get_base_url() - data = 'user=%s&password=%s' % (username, password) - headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/x-www-form-urlencoded', - 'Accept': 'text/plain'} - try: - resp, info = fetch_url(module=self.module, url=url, data=data, headers=headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail('login', info['body']) - - self.headers = {'referer': self.get_base_url(), - 'Content-Type': 'application/json', - 'Accept': 'application/json', - 'Cookie': resp.info().getheader('Set-Cookie')} - except Exception: - e = get_exception() - self._fail('login', str(e)) - - def _fail(self, msg, e): - if 'message' in e: - err_string = e.get('message') - else: - err_string = e - self.module.fail_json(msg='%s: %s' % (msg, err_string)) - - def _post_json(self, method, name, item=None): - if item is None: - item = {} - url = '%s/session/json' % self.get_base_url() - data = {'method': method, 'params': [[name], item]} - try: - resp, info = fetch_url(module=self.module, url=url, data=json.dumps(data), headers=self.headers) - status_code = info['status'] - if status_code not in [200, 201, 204]: - self._fail(method, info['body']) - except Exception: - e = get_exception() - self._fail('post %s' % method, str(e)) - - resp = json.loads(resp.read()) - err = resp.get('error') - if err is not None: - self._fail('repsonse %s' % method, err) - - if 'result' in resp: - result = resp.get('result') - if 'result' in result: - result = result.get('result') - if isinstance(result, list): - if len(result) > 0: - return result[0] - else: - return {} - return result - return None + super(UserIPAClient, self).__init__(module, host, port, protocol) def user_find(self, name): return self._post_json(method='user_find', name=None, item={'all': True, 'uid': name}) @@ -236,10 +165,11 @@ class IPAClient: return self._post_json(method='user_enable', name=name) -def get_user_dict(givenname=None, loginshell=None, mail=None, nsaccountlock=False, sn=None, sshpubkey=None, - telephonenumber=None, - title=None): +def get_user_dict(displayname=None, givenname=None, loginshell=None, mail=None, nsaccountlock=False, sn=None, + sshpubkey=None, telephonenumber=None, title=None, userpassword=None): user = {} + if displayname is not None: + user['displayname'] = displayname if givenname is not None: user['givenname'] = givenname if loginshell is not None: @@ -255,6 +185,8 @@ def get_user_dict(givenname=None, loginshell=None, mail=None, nsaccountlock=Fals user['telephonenumber'] = telephonenumber if title is not None: user['title'] = title + if userpassword is not None: + user['userpassword'] = userpassword return user @@ -265,7 +197,7 @@ def get_user_diff(ipa_user, module_user): API returns everything as a list even if only a single value is possible. Therefore some more complexity is needed. The method will check if the value type of module_user.attr is not a list and - create a list with that element if the same attribute in ipa_user is list. In this way i hope that the method + create a list with that element if the same attribute in ipa_user is list. In this way I hope that the method must not be changed if the returned API dict is changed. :param ipa_user: :param module_user: @@ -301,7 +233,7 @@ def get_user_diff(ipa_user, module_user): def get_ssh_key_fingerprint(ssh_key): """ Return the public key fingerprint of a given public SSH key - in format "FB:0C:AC:0A:07:94:5B:CE:75:6E:63:32:13:AD:AD:D7 (ssh-rsa)" + in format "FB:0C:AC:0A:07:94:5B:CE:75:6E:63:32:13:AD:AD:D7 [user@host] (ssh-rsa)" :param ssh_key: :return: """ @@ -312,7 +244,12 @@ def get_ssh_key_fingerprint(ssh_key): key = base64.b64decode(parts[1].encode('ascii')) fp_plain = hashlib.md5(key).hexdigest() - return ':'.join(a + b for a, b in zip(fp_plain[::2], fp_plain[1::2])).upper() + ' (%s)' % key_type + key_fp = ':'.join(a + b for a, b in zip(fp_plain[::2], fp_plain[1::2])).upper() + if len(parts) < 3: + return "%s (%s)" % (key_fp, key_type) + else: + user_host = parts[2] + return "%s %s (%s)" % (key_fp, user_host, key_type) def ensure(module, client): @@ -320,10 +257,13 @@ def ensure(module, client): name = module.params['name'] nsaccountlock = state == 'disabled' - module_user = get_user_dict(givenname=module.params.get('givenname'), loginshell=module.params['loginshell'], + module_user = get_user_dict(displayname=module.params.get('displayname'), + givenname=module.params.get('givenname'), + loginshell=module.params['loginshell'], mail=module.params['mail'], sn=module.params['sn'], sshpubkey=module.params['sshpubkey'], nsaccountlock=nsaccountlock, - telephonenumber=module.params['telephonenumber'], title=module.params['title']) + telephonenumber=module.params['telephonenumber'], title=module.params['title'], + userpassword=module.params['password']) ipa_user = client.user_find(name=name) @@ -373,10 +313,10 @@ def main(): supports_check_mode=True, ) - client = IPAClient(module=module, - host=module.params['ipa_host'], - port=module.params['ipa_port'], - protocol=module.params['ipa_prot']) + client = UserIPAClient(module=module, + host=module.params['ipa_host'], + port=module.params['ipa_port'], + protocol=module.params['ipa_prot']) # If sshpubkey is defined as None than module.params['sshpubkey'] is [None]. IPA itself returns None (not a list). # Therefore a small check here to replace list(None) by None. Otherwise get_user_diff() would return sshpubkey @@ -397,7 +337,6 @@ def main(): from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.pycompat24 import get_exception -from ansible.module_utils.urls import fetch_url if __name__ == '__main__': main()