From 56b1368441fce0f711ec12254aa0945450f122d6 Mon Sep 17 00:00:00 2001 From: chrisp Date: Thu, 19 Dec 2019 20:57:24 +0000 Subject: [PATCH 1/3] There is a new config management module placed in the plugins folder: plugins/modules/ipaconfig.py The config module allows the user change global config settings. The config module is as compatible as possible to the Ansible upstream ipa_config module, but adds many extra variables. Here is the documentation for the module: README-config.md --- README-config.md | 145 +++++++++++ plugins/modules/ipaconfig.py | 460 +++++++++++++++++++++++++++++++++++ tests/config/test_config.yml | 143 +++++++++++ 3 files changed, 748 insertions(+) create mode 100644 README-config.md create mode 100644 plugins/modules/ipaconfig.py create mode 100644 tests/config/test_config.yml diff --git a/README-config.md b/README-config.md new file mode 100644 index 00000000..608df548 --- /dev/null +++ b/README-config.md @@ -0,0 +1,145 @@ +Config module +=========== + +Description +----------- + +The config module allows the setting of global config parameters within IPA. If no parameters are specified it returns the list of all current parameters. + +The config module is as compatible as possible to the Ansible upstream `ipa_config` module, but adds many additional parameters + + +Features +-------- +* IPA server configuration management + + +Supported FreeIPA Versions +-------------------------- + +FreeIPA versions 4.4.0 and up are supported by the ipaconfig module. + + +Requirements +------------ + +**Controller** +* Ansible version: 2.8+ + +**Node** +* Supported FreeIPA version (see above) + + +Usage +===== + +Example inventory file + +```ini +[ipaserver] +ipaserver.test.local +``` + + +Example playbook to read config options: + +```yaml +--- +- name: Playbook to handle global config options + hosts: ipaserver + become: true + tasks: + - name: return current values of the global configuration options + ipaconfig: + ipaadmin_password: password + register: result + - name: display default login shell + debug: + msg: '{{result.config.defaultlogin }}' + + - name: ensure defaultloginshell and maxusernamelength are set as required + ipaconfig: + ipaadmin_password: password + defaultlogin: /bin/bash + maxusername: 64 +``` + +```yaml +--- +- name: Playbook to ensure some config options are set + hosts: ipaserver + become: true + tasks: + - name: set defaultlogin and maxusername + ipaconfig: + ipaadmin_password: password + defaultlogin: /bin/bash + maxusername: 64 +``` + + +Variables +========= + +ipauser +------- + +**General Variables:** + +Variable | Description | Required +-------- | ----------- | -------- +`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no +`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no +`maxusername` \| `ipamaxusernamelength` | Set the maximum username length (1 to 255) | false +`homedirectory` \| `ipahomesrootdir` | Set the default location of home directories | false +`defaultshell` \| `ipadefaultloginshell` | Set the default shell for new users | false +`defaultgroup` \| `ipadefaultprimarygroup` | Set the default group for new users | false +`emaildomain`\| `ipadefaultemaildomain` | Set the default e-mail domain | false +`searchtimelimit` \| `ipasearchtimelimit` | Set maximum amount of time (seconds) for a search -1 to 2147483647 (-1 or 0 is unlimited) | false +`searchrecordslimit` \| `ipasearchrecordslimit` | Set maximum number of records to search -1 to 2147483647 (-1 or 0 is unlimited) | false +`usersearch` \| `ipausersearchfields` | Set list of fields to search when searching for users | false +`groupsearch` \| `ipagroupsearchfields` | Set list of fields to search in when searching for groups | false +`enable_migration` \| `ipamigrationenabled` | Enable migration mode (choices: True, False ) | false +`groupobjectclasses` \| `ipagroupobjectclasses` | Set default group objectclasses (list) | false +`userobjectclasses` \| `ipauserobjectclasses` | Set default user objectclasses (list) | false +`pwdexpnotify` \| `ipapwdexpadvnotify` | Set number of days's notice of impending password expiration (0 to 2147483647) | false +`configstring` \| `ipaconfigstring` | Set extra hashes to generate in password plug-in (choices:`AllowNThash`, `KDC:Disable Last Success`, `KDC:Disable Lockout`, `KDC:Disable Default Preauth for SPNs`) | false +`selinuxusermaporder` \| `ipaselinuxusermaporder`| Set ordered list in increasing priority of SELinux users | false +`selinuxusermapdefault`\| `ipaselinuxusermapdefault` | Set default SELinux user when no match is found in SELinux map rule | false +`pac_type` \| `ipakrbauthzdata` | set default types of PAC supported for services (choices: `MS-PAC`, `PAD`, `nfs:NONE`) +`user_auth_type` \| `ipauserauthtype` | set default types of supported user authentication (choices: `password`, `radius`, `otp`, `disabled`) | false +`domain_resolution_order` \| `ipadomainresolutionorder` | Set list of domains used for short name qualification | false + + +Return Values +============= + +Variable | Description | Returned When +-------- | ----------- | ------------- +`config` | config dict
Fields: | No values to configure are specified +  | `homedirectory` |   +  | `defaultshell` |   +  | `defaultgroup` |   +  | `emaildomain` |   +  | `searchtimelimit` |   +  | `searchrecordslimit` |   +  | `usersearch` |   +  | `groupsearch` |   +  | `enable_migration` |   +  | `groupobjectclasses` |   +  | `userobjectclasses` |   +  | `pwdexpnotify` |   +  | `configstring` |   +  | `selinuxusermaporder` |   +  | `selinuxusermapdefault` |   +  | `pac_type` |   +  | `user_auth_type` |   +  | `domain_resolution_order` |   + + +All returned fields take the same form as their namesake input parameters + +Authors +======= + +Chris Procter diff --git a/plugins/modules/ipaconfig.py b/plugins/modules/ipaconfig.py new file mode 100644 index 00000000..d4383adc --- /dev/null +++ b/plugins/modules/ipaconfig.py @@ -0,0 +1,460 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Authors: +# Chris Procter +# +# Copyright (C) 2020 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +ANSIBLE_METADATA = { + "metadata_version": "1.0", + "supported_by": "community", + "status": ["preview"], +} + + +DOCUMENTATION = ''' +--- +module: ipa_config +author: chris procter +short_description: Modify IPA global config options +description: +- Modify IPA global config options +options: + ipaadmin_principal: + description: The admin principal + default: admin + ipaadmin_password: + description: The admin password + required: false + maxusername: + description: Set the maximum username length between 1-255 + required: false + aliases: ['ipamaxusernamelength'] + homedirectory: + description: Set the default location of home directories + required: false + aliases: ['ipahomesrootdir'] + defaultshell: + description: Set the default shell for new users + required: false + aliases: ['ipadefaultloginshell', 'loginshell'] + defaultgroup: + description: Set the default group for new users + required: false + aliases: ['ipadefaultprimarygroup'] + emaildomain: + description: Set the default e-mail domain + required: false + aliases: ['ipadefaultemaildomain'] + searchtimelimit: + description: + - Set maximum amount of time (seconds) for a search + - values -1 to 2147483647 (-1 or 0 is unlimited) + required: false + aliases: ['ipasearchtimelimit'] + searchrecordslimit: + description: + - Set maximum number of records to search + - values -1 to 2147483647 (-1 or 0 is unlimited) + required: false + aliases: ['ipasearchrecordslimit'] + usersearch: + description: + - Set comma-separated list of fields to search for user search + required: false + aliases: ['ipausersearchfields'] + groupsearch: + description: + - Set comma-separated list of fields to search for group search + required: false + aliases: ['ipagroupsearchfields'] + enable_migration: + description: Enable migration mode + type: bool + required: false + aliases: ['enable-migration','ipamigrationenabled'] + groupobjectclasses: + description: Set default group objectclasses (comma-separated list) + required: false + type: list + aliases: ['ipagroupobjectclasses'] + userobjectclasses: + description: Set default user objectclasses (comma-separated list) + required: false + type: list + aliases: ['ipauserobjectclasses'] + pwdexpnotify: + description: + - Set number of days's notice of impending password expiration + - values 0 to 2147483647 + required: false + aliases: ['ipapwdexpadvnotify'] + configstring: + description: Set extra hashes to generate in password plug-in + required: false + type: list + choices: + - "AllowNThash" + - "KDC:Disable Last Success" + - "KDC:Disable Lockout" + - "KDC:Disable Default Preauth for SPNs" + aliases: ['ipaconfigstring'] + selinuxusermaporder: + description: Set order in increasing priority of SELinux users + required: false + type: list + aliases: ['ipaselinuxusermaporder'] + selinuxusermapdefault: + description: Set default SELinux user when no match found in map rule + required: false + aliases: ['ipaselinuxusermapdefault'] + pac_type: + description: set default types of PAC supported for services + required: false + type: list + choices: ["MS-PAC", "PAD", "nfs:NONE"] + aliases: ["pac-type","ipakrbauthzdata"] + user_auth_type: + description: set default types of supported user authentication + required: false + type: list + choices: ["password", "radius", "otp", "disabled"] + aliases: ["user-auth_type","user-auth-type","ipauserauthtype"] + domain_resolution_order: + description: set list of domains used for short name qualification + required: false + type: list + aliases: ["domain-resolution_order", + "domain-resolution-order", + "ipadomainresolutionorder"] +''' + +EXAMPLES = ''' +--- +- name: Playbook to handle global configuration options + hosts: ipaserver + become: true + tasks: + - name: return current values of the global configuration options + ipaconfig: + ipaadmin_password: password + register: result + - name: display default login shell + debug: + msg: '{{result.config.defaultshell[0] }}' + + - name: set defaultshell and maxusername + ipaconfig: + ipaadmin_password: password + defaultshell: /bin/bash + maxusername: 64 +''' + +RETURN = ''' +config: + description: Dict of all global config options + returned: When no options are set + type: dict + options: + maxusername: + description: maximum username length + returned: always + homedirectory: + description: default location of home directories + returned: always + defaultshell: + description: default shell for new users + returned: always + defaultgroup: + description: default group for new users + returned: always + emaildomain: + description: default e-mail domain + returned: always + searchtimelimit: + description: maximum amount of time (seconds) for a search + returned: always + searchrecordslimit: + description: maximum number of records to search + returned: always + usersearch: + description: comma-separated list of fields to search in user search + type: list + returned: always + groupsearch: + description: comma-separated list of fields to search in group search + type: list + returned: always + enable_migration: + description: Enable migration mode + type: bool + returned: always + groupobjectclasses: + description: default group objectclasses (comma-separated list) + type: list + returned: always + userobjectclasses: + description: default user objectclasses (comma-separated list) + type: list + returned: always + pwdexpnotify: + description: number of days's notice of impending password expiration + returned: always + configstring: + description: extra hashes to generate in password plug-in + type: list + returned: always + selinuxusermaporder: + description: order in increasing priority of SELinux users + returned: always + selinuxusermapdefault: + description: default SELinux user when no match is found in map rule + returned: always + pac_type: + description: default types of PAC supported for services + type: list + returned: always + user_auth_type: + description: default types of supported user authentication + returned: always + domain_resolution_order: + description: list of domains used for short name qualification + returned: always +''' + + +from ansible.module_utils.basic import AnsibleModule +from ansible.module_utils.ansible_freeipa_module import temp_kinit, \ + temp_kdestroy, valid_creds, api_connect, api_command_no_name, \ + compare_args_ipa, module_params_get + + +def config_show(module): + _result = api_command_no_name(module, "config_show", {}) + + return _result["result"] + + +def gen_args(params): + _args = {} + for k, v in params.items(): + if v is not None: + _args[k] = v + + return _args + + +def main(): + ansible_module = AnsibleModule( + argument_spec=dict( + # general + ipaadmin_principal=dict(type="str", default="admin"), + ipaadmin_password=dict(type="str", required=False, no_log=True), + maxusername=dict(type="int", required=False, + aliases=['ipamaxusernamelength']), + homedirectory=dict(type="str", required=False, + aliases=['ipahomesrootdir']), + defaultshell=dict(type="str", required=False, + aliases=['ipadefaultloginshell', + 'loginshell']), + defaultgroup=dict(type="str", required=False, + aliases=['ipadefaultprimarygroup']), + emaildomain=dict(type="str", required=False, + aliases=['ipadefaultemaildomain']), + searchtimelimit=dict(type="int", required=False, + aliases=['ipasearchtimelimit']), + searchrecordslimit=dict(type="int", required=False, + aliases=['ipasearchrecordslimit']), + usersearch=dict(type="list", required=False, + aliases=['ipausersearchfields']), + groupsearch=dict(type="list", required=False, + aliases=['ipagroupsearchfields']), + enable_migration=dict(type="bool", required=False, + aliases=['ipamigrationenabled', + 'enable-migration']), + groupobjectclasses=dict(type="list", required=False, + aliases=['ipagroupobjectclasses']), + userobjectclasses=dict(type="list", required=False, + aliases=['ipauserobjectclasses']), + pwdexpnotify=dict(type="int", required=False, + aliases=['ipapwdexpadvnotify']), + configstring=dict(type="list", required=False, + aliases=['ipaconfigstring'], + choices=["AllowNThash", + "KDC:Disable Last Success", + "KDC:Disable Lockout", + "KDC:Disable Default Preauth for SPNs"]), # noqa E128 + selinuxusermaporder=dict(type="list", required=False, + aliases=['ipaselinuxusermaporder']), + selinuxusermapdefault=dict(type="str", required=False, + aliases=['ipaselinuxusermapdefault']), + pac_type=dict(type="list", required=False, + aliases=["ipakrbauthzdata", "pac-type"], + choices=["MS-PAC", "PAD", "nfs:NONE"]), + user_auth_type=dict(type="list", required=False, + aliases=["ipauserauthtype", + "user-auth_type", + "user-auth-type"]), + domain_resolution_order=dict(type="list", required=False, + aliases=["ipadomainresolutionorder", + "domain-resolution_order", + "domain-resolution-order"]) + ), + supports_check_mode=True, + ) + + ansible_module._ansible_debug = True + + # Get parameters + + # general + ipaadmin_principal = module_params_get(ansible_module, + "ipaadmin_principal") + ipaadmin_password = module_params_get(ansible_module, + "ipaadmin_password") + + field_map = { + "maxusername": "ipamaxusernamelength", + "homedirectory": "ipahomesrootdir", + "defaultshell": "ipadefaultloginshell", + "defaultgroup": "ipadefaultprimarygroup", + "emaildomain": "ipadefaultemaildomain", + "searchtimelimit": "ipasearchtimelimit", + "searchrecordslimit": "ipasearchrecordslimit", + "usersearch": "ipausersearchfields", + "groupsearch": "ipagroupsearchfields", + "enable_migration": "ipamigrationenabled", + "groupobjectclasses": "ipagroupobjectclasses", + "userobjectclasses": "ipauserobjectclasses", + "pwdexpnotify": "ipapwdexpadvnotify", + "configstring": "ipaconfigstring", + "selinuxusermaporder": "ipaselinuxusermaporder", + "selinuxusermapdefault": "ipaselinuxusermapdefault", + "pac_type": "ipakrbauthzdata", + "user_auth_type": "ipauserauthtype", + "domain_resolution_order": "ipadomainresolutionorder" + } + reverse_field_map = {v: k for k, v in field_map.items()} + + params = {} + for x in field_map.keys(): + val = module_params_get(ansible_module, x) + + if val is not None: + params[field_map.get(x, x)] = val + + if params.get("ipamigrationenabled") is not None: + params["ipamigrationenabled"] = \ + str(params["ipamigrationenabled"]).upper() + + if params.get("ipaselinuxusermaporder", None): + params["ipaselinuxusermaporder"] = \ + "$".join(params["ipaselinuxusermaporder"]) + + if params.get("ipadomainresolutionorder", None): + params["ipadomainresolutionorder"] = \ + ":".join(params["ipadomainresolutionorder"]) + + if params.get("ipausersearchfields", None): + params["ipausersearchfields"] = \ + ",".join(params["ipausersearchfields"]) + + if params.get("ipagroupsearchfields", None): + params["ipagroupsearchfields"] = \ + ",".join(params["ipagroupsearchfields"]) + + if params.get("ipamaxusernamelength", 0) > 255 \ + or params.get("ipamaxusernamelength", 2) < 1: + ansible_module.fail_json( + msg="Argument 'maxusername' mustn range 1 to 255") + + for x in ["ipasearchtimelimit", + "ipasearchrecordslimit", + "ipapwdexpadvnotify"]: + if params.get(x, 0) > 2147483647: + ansible_module.fail_json( + msg="Argument '%s' has a maximum value of 2147483647" % (x)) + + for x in ["ipasearchtimelimit", "ipasearchrecordslimit"]: + if params.get(x, 0) < -2147483648: + ansible_module.fail_json( + msg="Argument '%s' has minimum value of -2147483648" % (x)) + + changed = False + exit_args = {} + ccache_dir = None + ccache_name = None + res_show = None + try: + if not valid_creds(ansible_module, ipaadmin_principal): + ccache_dir, ccache_name = temp_kinit(ipaadmin_principal, + ipaadmin_password) + api_connect() + + if params.keys(): + res_show = config_show(ansible_module) + if not compare_args_ipa(ansible_module, params, res_show): + changed = True + api_command_no_name(ansible_module, "config_mod", params) + + else: + rawresult = api_command_no_name(ansible_module, "config_show", {}) + result = rawresult['result'] + del result['dn'] + for key, v in result.items(): + k = reverse_field_map.get(key, key) + if ansible_module.argument_spec.get(k): + if k == 'ipaselinuxusermaporder': + exit_args['ipaselinuxusermaporder'] = \ + result.get(key)[0].split('$') + elif k == 'domain_resolution_order': + exit_args['domain_resolution_order'] = \ + result.get(key)[0].split('$') + elif k == 'usersearch': + exit_args['usersearch'] = \ + result.get(key)[0].split(',') + elif k == 'groupsearch': + exit_args['groupsearch'] = \ + result.get(key)[0].split(',') + elif isinstance(v, str) and \ + ansible_module.argument_spec[k]['type'] == "list": + exit_args[k] = [v] + elif isinstance(v, list) and \ + ansible_module.argument_spec[k]['type'] == "str": + exit_args[k] = ",".join(v) + elif isinstance(v, list) and \ + ansible_module.argument_spec[k]['type'] == "int": + exit_args[k] = ",".join(v) + elif isinstance(v, list) and \ + ansible_module.argument_spec[k]['type'] == "bool": + exit_args[k] = (v[0] == "TRUE") + else: + exit_args[k] = v + + except Exception as e: + ansible_module.fail_json(msg="%s %s" % (params, str(e))) + + finally: + temp_kdestroy(ccache_dir, ccache_name) + + # Done + ansible_module.exit_json(changed=changed, config=exit_args) + + +if __name__ == "__main__": + main() diff --git a/tests/config/test_config.yml b/tests/config/test_config.yml new file mode 100644 index 00000000..81f2f4e0 --- /dev/null +++ b/tests/config/test_config.yml @@ -0,0 +1,143 @@ +--- +- name: Playbook to handle users + hosts: ipaserver + become: true + gather_facts: false + + tasks: + - name: return current values of the global configuration options + ipaconfig: + ipaadmin_password: SomeADMINpassword + register: previousconfig + + - debug: + msg: "{{previousconfig}}" + + - name: set default shell to default value + ipaconfig: + ipaadmin_password: SomeADMINpassword + defaultshell: /bin/sh + register: result + failed_when: result.changed + + - name: set default shell to new value + ipaconfig: + ipaadmin_password: SomeADMINpassword + defaultshell: /bin/bash + register: result + failed_when: not result.changed + + - name: check default shell is changed + ipaconfig: + ipaadmin_password: SomeADMINpassword + defaultshell: /bin/bash + register: result + failed_when: result.changed + + - name: reset default shell to old value + ipaconfig: + ipaadmin_password: SomeADMINpassword + defaultshell: '{{previousconfig.config.defaultshell }}' + register: result + failed_when: not result.changed + + - name: check default shell is reset + ipaconfig: + ipaadmin_password: SomeADMINpassword + defaultshell: '{{previousconfig.config.defaultshell }}' + register: result + failed_when: result.changed + + - name: Ensure the default e-mail domain is ansible.com. + ipaconfig: + ipaadmin_password: SomeADMINpassword + emaildomain: ansible.com + register: result + failed_when: not result.changed + + - name: Ensure the default e-mail domain is set + ipaconfig: + ipaadmin_password: SomeADMINpassword + emaildomain: ansible.com + register: result + failed_when: result.changed + + - name: reset default e-mail domain + ipaconfig: + ipaadmin_password: SomeADMINpassword + emaildomain: '{{previousconfig.config.emaildomain }}' + register: result + failed_when: not result.changed + + - name: set pac-type + ipaconfig: + ipaadmin_password: SomeADMINpassword + pac_type: + - nfs:NONE + register: result + failed_when: not result.changed + + - name: reset pac-type + ipaconfig: + ipaadmin_password: SomeADMINpassword + pac_type: '{{previousconfig.config.pac_type}}' + register: result + failed_when: not result.changed + + - name: set usersearch + ipaconfig: + ipaadmin_password: SomeADMINpassword + usersearch: + - uid + register: result + failed_when: not result.changed + + - name: check usersearch + ipaconfig: + ipaadmin_password: SomeADMINpassword + usersearch: + - uid + register: result + failed_when: result.changed + + - name: reset changed fields + ipaconfig: + ipaadmin_password: 'SomeADMINpassword' + configstring: '{{previousconfig.config.configstring}}' + emaildomain: '{{previousconfig.config.emaildomain}}' + defaultshell: '{{previousconfig.config.defaultshell}}' + defaultgroup: '{{previousconfig.config.defaultgroup}}' + groupsearch: '{{previousconfig.config.groupsearch}}' + homedirectory: '{{previousconfig.config.homedirectory}}' + pac_type: '{{previousconfig.config.pac_type}}' + maxusername: '{{previousconfig.config.maxusername}}' + enable_migration: '{{previousconfig.config.enable_migration}}' + pwdexpnotify: '{{previousconfig.config.pwdexpnotify}}' + searchrecordslimit: '{{previousconfig.config.searchrecordslimit}}' + searchtimelimit: '{{previousconfig.config.searchtimelimit}}' + selinuxusermapdefault: '{{previousconfig.config.selinuxusermapdefault}}' + selinuxusermaporder: '{{previousconfig.config.selinuxusermaporder}}' + usersearch: '{{previousconfig.config.usersearch}}' + register: result + failed_when: not result.changed + + - name: check reset fields + ipaconfig: + ipaadmin_password: 'SomeADMINpassword' + configstring: '{{previousconfig.config.configstring}}' + emaildomain: '{{previousconfig.config.emaildomain}}' + defaultshell: '{{previousconfig.config.defaultshell}}' + defaultgroup: '{{previousconfig.config.defaultgroup}}' + groupsearch: '{{previousconfig.config.groupsearch}}' + homedirectory: '{{previousconfig.config.homedirectory}}' + pac_type: '{{previousconfig.config.pac_type}}' + maxusername: '{{previousconfig.config.maxusername}}' + enable_migration: '{{previousconfig.config.enable_migration}}' + pwdexpnotify: '{{previousconfig.config.pwdexpnotify}}' + searchrecordslimit: '{{previousconfig.config.searchrecordslimit}}' + searchtimelimit: '{{previousconfig.config.searchtimelimit}}' + selinuxusermapdefault: '{{previousconfig.config.selinuxusermapdefault}}' + selinuxusermaporder: '{{previousconfig.config.selinuxusermaporder}}' + usersearch: '{{previousconfig.config.usersearch}}' + register: result + failed_when: result.changed From 89ba344a0ba02c3628f3f5e93cd2403fe324b3b6 Mon Sep 17 00:00:00 2001 From: Thomas Woerner Date: Wed, 10 Jun 2020 11:59:22 +0200 Subject: [PATCH 2/3] tests/config/test_config.yml: Fix main name It should be `Playbook to handle server configuration` instead of `Playbook to handle users`. --- tests/config/test_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/config/test_config.yml b/tests/config/test_config.yml index 81f2f4e0..efa169de 100644 --- a/tests/config/test_config.yml +++ b/tests/config/test_config.yml @@ -1,5 +1,5 @@ --- -- name: Playbook to handle users +- name: Playbook to handle server configuration hosts: ipaserver become: true gather_facts: false From f7ca62e52b54f123295c316560633e85dc1056f4 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Wed, 10 Jun 2020 14:59:36 -0300 Subject: [PATCH 3/3] Add support for missing attributes, and enhance ipaconfig tests. This patch add support for the attributes `maxtostname` and `ca_renewal_master_server` attributes that were missing and also provide a more complete set of tests. --- README-config.md | 46 ++- playbooks/config/retrieve-config.yml | 14 + .../config/set-ca-renewal-master-server.yml | 11 + plugins/modules/ipaconfig.py | 95 +++-- tests/config/test_config.yml | 361 +++++++++++++++--- 5 files changed, 410 insertions(+), 117 deletions(-) create mode 100644 playbooks/config/retrieve-config.yml create mode 100644 playbooks/config/set-ca-renewal-master-server.yml diff --git a/README-config.md b/README-config.md index 608df548..ee969816 100644 --- a/README-config.md +++ b/README-config.md @@ -90,25 +90,27 @@ Variable | Description | Required -------- | ----------- | -------- `ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no `ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no -`maxusername` \| `ipamaxusernamelength` | Set the maximum username length (1 to 255) | false -`homedirectory` \| `ipahomesrootdir` | Set the default location of home directories | false -`defaultshell` \| `ipadefaultloginshell` | Set the default shell for new users | false -`defaultgroup` \| `ipadefaultprimarygroup` | Set the default group for new users | false +`maxusername` \| `ipamaxusernamelength` | Set the maximum username length (1 to 255) | no +`maxhostname` \| `ipamaxhostnamelength` | Set the maximum hostname length between 64-255 | no +`homedirectory` \| `ipahomesrootdir` | Set the default location of home directories | no +`defaultshell` \| `ipadefaultloginshell` | Set the default shell for new users | no +`defaultgroup` \| `ipadefaultprimarygroup` | Set the default group for new users | no `emaildomain`\| `ipadefaultemaildomain` | Set the default e-mail domain | false -`searchtimelimit` \| `ipasearchtimelimit` | Set maximum amount of time (seconds) for a search -1 to 2147483647 (-1 or 0 is unlimited) | false -`searchrecordslimit` \| `ipasearchrecordslimit` | Set maximum number of records to search -1 to 2147483647 (-1 or 0 is unlimited) | false -`usersearch` \| `ipausersearchfields` | Set list of fields to search when searching for users | false -`groupsearch` \| `ipagroupsearchfields` | Set list of fields to search in when searching for groups | false -`enable_migration` \| `ipamigrationenabled` | Enable migration mode (choices: True, False ) | false -`groupobjectclasses` \| `ipagroupobjectclasses` | Set default group objectclasses (list) | false -`userobjectclasses` \| `ipauserobjectclasses` | Set default user objectclasses (list) | false -`pwdexpnotify` \| `ipapwdexpadvnotify` | Set number of days's notice of impending password expiration (0 to 2147483647) | false -`configstring` \| `ipaconfigstring` | Set extra hashes to generate in password plug-in (choices:`AllowNThash`, `KDC:Disable Last Success`, `KDC:Disable Lockout`, `KDC:Disable Default Preauth for SPNs`) | false -`selinuxusermaporder` \| `ipaselinuxusermaporder`| Set ordered list in increasing priority of SELinux users | false -`selinuxusermapdefault`\| `ipaselinuxusermapdefault` | Set default SELinux user when no match is found in SELinux map rule | false -`pac_type` \| `ipakrbauthzdata` | set default types of PAC supported for services (choices: `MS-PAC`, `PAD`, `nfs:NONE`) -`user_auth_type` \| `ipauserauthtype` | set default types of supported user authentication (choices: `password`, `radius`, `otp`, `disabled`) | false -`domain_resolution_order` \| `ipadomainresolutionorder` | Set list of domains used for short name qualification | false +`searchtimelimit` \| `ipasearchtimelimit` | Set maximum amount of time (seconds) for a search -1 to 2147483647 (-1 or 0 is unlimited) | no +`searchrecordslimit` \| `ipasearchrecordslimit` | Set maximum number of records to search -1 to 2147483647 (-1 or 0 is unlimited) | no +`usersearch` \| `ipausersearchfields` | Set list of fields to search when searching for users | no +`groupsearch` \| `ipagroupsearchfields` | Set list of fields to search in when searching for groups | no +`enable_migration` \| `ipamigrationenabled` | Enable migration mode (choices: True, False ) | no +`groupobjectclasses` \| `ipagroupobjectclasses` | Set default group objectclasses (list) | no +`userobjectclasses` \| `ipauserobjectclasses` | Set default user objectclasses (list) | no +`pwdexpnotify` \| `ipapwdexpadvnotify` | Set number of days's notice of impending password expiration (0 to 2147483647) | no +`configstring` \| `ipaconfigstring` | Set extra hashes to generate in password plug-in (choices:`AllowNThash`, `KDC:Disable Last Success`, `KDC:Disable Lockout`, `KDC:Disable Default Preauth for SPNs`). Use `""` to clear this variable. | no +`selinuxusermaporder` \| `ipaselinuxusermaporder`| Set ordered list in increasing priority of SELinux users | no +`selinuxusermapdefault`\| `ipaselinuxusermapdefault` | Set default SELinux user when no match is found in SELinux map rule | no +`pac_type` \| `ipakrbauthzdata` | set default types of PAC supported for services (choices: `MS-PAC`, `PAD`, `nfs:NONE`). Use `""` to clear this variable. | no +`user_auth_type` \| `ipauserauthtype` | set default types of supported user authentication (choices: `password`, `radius`, `otp`, `disabled`). Use `""` to clear this variable. | no +`domain_resolution_order` \| `ipadomainresolutionorder` | Set list of domains used for short name qualification | no +`ca_renewal_master_server` \| `ipacarenewalmasterserver`| Renewal master for IPA certificate authority. | no Return Values @@ -117,6 +119,8 @@ Return Values Variable | Description | Returned When -------- | ----------- | ------------- `config` | config dict
Fields: | No values to configure are specified +  | `maxusername` |   +  | `maxhostname` |     | `homedirectory` |     | `defaultshell` |     | `defaultgroup` |   @@ -130,14 +134,14 @@ Variable | Description | Returned When   | `userobjectclasses` |     | `pwdexpnotify` |     | `configstring` |   -  | `selinuxusermaporder` |     | `selinuxusermapdefault` |   +  | `selinuxusermaporder` |     | `pac_type` |     | `user_auth_type` |     | `domain_resolution_order` |   +  | `ca_renewal_master_server` |   - -All returned fields take the same form as their namesake input parameters +All returned fields take the same form as their namesake input parameters Authors ======= diff --git a/playbooks/config/retrieve-config.yml b/playbooks/config/retrieve-config.yml new file mode 100644 index 00000000..7f05e802 --- /dev/null +++ b/playbooks/config/retrieve-config.yml @@ -0,0 +1,14 @@ +--- +- name: Playbook to handle global DNS configuration + hosts: ipaserver + become: no + gather_facts: no + + tasks: + - name: Query IPA global configuration + ipaconfig: + ipaadmin_password: SomeADMINpassword + register: serverconfig + + - debug: + msg: "{{ serverconfig }}" diff --git a/playbooks/config/set-ca-renewal-master-server.yml b/playbooks/config/set-ca-renewal-master-server.yml new file mode 100644 index 00000000..128ac8d9 --- /dev/null +++ b/playbooks/config/set-ca-renewal-master-server.yml @@ -0,0 +1,11 @@ +--- +- name: Playbook to handle global DNS configuration + hosts: ipaserver + become: no + gather_facts: no + + tasks: + - name: set ca_renewal_master_server + ipaconfig: + ipaadmin_password: SomeADMINpassword + ca_renewal_master_server: carenewal.example.com diff --git a/plugins/modules/ipaconfig.py b/plugins/modules/ipaconfig.py index d4383adc..41a6d0a8 100644 --- a/plugins/modules/ipaconfig.py +++ b/plugins/modules/ipaconfig.py @@ -45,6 +45,10 @@ options: description: Set the maximum username length between 1-255 required: false aliases: ['ipamaxusernamelength'] + maxhostname: + description: Set the maximum hostname length between 64-255 + required: false + aliases: ['ipamaxhostnamelength'] homedirectory: description: Set the default location of home directories required: false @@ -87,7 +91,7 @@ options: description: Enable migration mode type: bool required: false - aliases: ['enable-migration','ipamigrationenabled'] + aliases: ['ipamigrationenabled'] groupobjectclasses: description: Set default group objectclasses (comma-separated list) required: false @@ -113,6 +117,7 @@ options: - "KDC:Disable Last Success" - "KDC:Disable Lockout" - "KDC:Disable Default Preauth for SPNs" + - "" aliases: ['ipaconfigstring'] selinuxusermaporder: description: Set order in increasing priority of SELinux users @@ -127,21 +132,23 @@ options: description: set default types of PAC supported for services required: false type: list - choices: ["MS-PAC", "PAD", "nfs:NONE"] - aliases: ["pac-type","ipakrbauthzdata"] + choices: ["MS-PAC", "PAD", "nfs:NONE", ""] + aliases: ["ipakrbauthzdata"] user_auth_type: description: set default types of supported user authentication required: false type: list - choices: ["password", "radius", "otp", "disabled"] - aliases: ["user-auth_type","user-auth-type","ipauserauthtype"] + choices: ["password", "radius", "otp", "disabled", ""] + aliases: ["ipauserauthtype"] + ca_renewal_master_server: + description: Renewal master for IPA certificate authority. + required: false + type: string domain_resolution_order: description: set list of domains used for short name qualification required: false type: list - aliases: ["domain-resolution_order", - "domain-resolution-order", - "ipadomainresolutionorder"] + aliases: ["ipadomainresolutionorder"] ''' EXAMPLES = ''' @@ -174,6 +181,9 @@ config: maxusername: description: maximum username length returned: always + maxhostname: + description: maximum hostname length + returned: always homedirectory: description: default location of home directories returned: always @@ -232,6 +242,9 @@ config: user_auth_type: description: default types of supported user authentication returned: always + ca_renewal_master_server: + description: master for IPA certificate authority. + returned: always domain_resolution_order: description: list of domains used for short name qualification returned: always @@ -242,6 +255,7 @@ from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.ansible_freeipa_module import temp_kinit, \ temp_kdestroy, valid_creds, api_connect, api_command_no_name, \ compare_args_ipa, module_params_get +import ipalib.errors def config_show(module): @@ -267,6 +281,8 @@ def main(): ipaadmin_password=dict(type="str", required=False, no_log=True), maxusername=dict(type="int", required=False, aliases=['ipamaxusernamelength']), + maxhostname=dict(type="int", required=False, + aliases=['ipamaxhostnamelength']), homedirectory=dict(type="str", required=False, aliases=['ipahomesrootdir']), defaultshell=dict(type="str", required=False, @@ -285,8 +301,7 @@ def main(): groupsearch=dict(type="list", required=False, aliases=['ipagroupsearchfields']), enable_migration=dict(type="bool", required=False, - aliases=['ipamigrationenabled', - 'enable-migration']), + aliases=['ipamigrationenabled']), groupobjectclasses=dict(type="list", required=False, aliases=['ipagroupobjectclasses']), userobjectclasses=dict(type="list", required=False, @@ -298,22 +313,22 @@ def main(): choices=["AllowNThash", "KDC:Disable Last Success", "KDC:Disable Lockout", - "KDC:Disable Default Preauth for SPNs"]), # noqa E128 + "KDC:Disable Default Preauth for SPNs", + ""]), # noqa E128 selinuxusermaporder=dict(type="list", required=False, aliases=['ipaselinuxusermaporder']), selinuxusermapdefault=dict(type="str", required=False, aliases=['ipaselinuxusermapdefault']), pac_type=dict(type="list", required=False, - aliases=["ipakrbauthzdata", "pac-type"], - choices=["MS-PAC", "PAD", "nfs:NONE"]), + aliases=["ipakrbauthzdata"], + choices=["MS-PAC", "PAD", "nfs:NONE", ""]), user_auth_type=dict(type="list", required=False, - aliases=["ipauserauthtype", - "user-auth_type", - "user-auth-type"]), + choices=["password", "radius", "otp", + "disabled", ""], + aliases=["ipauserauthtype"]), + ca_renewal_master_server=dict(type="str", required=False), domain_resolution_order=dict(type="list", required=False, - aliases=["ipadomainresolutionorder", - "domain-resolution_order", - "domain-resolution-order"]) + aliases=["ipadomainresolutionorder"]) ), supports_check_mode=True, ) @@ -330,6 +345,7 @@ def main(): field_map = { "maxusername": "ipamaxusernamelength", + "maxhostname": "ipamaxhostnamelength", "homedirectory": "ipahomesrootdir", "defaultshell": "ipadefaultloginshell", "defaultgroup": "ipadefaultprimarygroup", @@ -347,6 +363,7 @@ def main(): "selinuxusermapdefault": "ipaselinuxusermapdefault", "pac_type": "ipakrbauthzdata", "user_auth_type": "ipauserauthtype", + "ca_renewal_master_server": "ca_renewal_master_server", "domain_resolution_order": "ipadomainresolutionorder" } reverse_field_map = {v: k for k, v in field_map.items()} @@ -378,22 +395,19 @@ def main(): params["ipagroupsearchfields"] = \ ",".join(params["ipagroupsearchfields"]) - if params.get("ipamaxusernamelength", 0) > 255 \ - or params.get("ipamaxusernamelength", 2) < 1: - ansible_module.fail_json( - msg="Argument 'maxusername' mustn range 1 to 255") - - for x in ["ipasearchtimelimit", - "ipasearchrecordslimit", - "ipapwdexpadvnotify"]: - if params.get(x, 0) > 2147483647: + # verify limits on INT values. + args_with_limits = [ + ("ipamaxusernamelength", 1, 255), + ("ipamaxhostnamelength", 64, 255), + ("ipasearchtimelimit", -1, 2147483647), + ("ipasearchrecordslimit", -1, 2147483647), + ("ipapwdexpadvnotify", 0, 2147483647), + ] + for arg, min, max in args_with_limits: + if arg in params and (params[arg] > max or params[arg] < min): ansible_module.fail_json( - msg="Argument '%s' has a maximum value of 2147483647" % (x)) - - for x in ["ipasearchtimelimit", "ipasearchrecordslimit"]: - if params.get(x, 0) < -2147483648: - ansible_module.fail_json( - msg="Argument '%s' has minimum value of -2147483648" % (x)) + msg="Argument '%s' must be between %d and %d." + % (arg, min, max)) changed = False exit_args = {} @@ -405,10 +419,14 @@ def main(): ccache_dir, ccache_name = temp_kinit(ipaadmin_principal, ipaadmin_password) api_connect() - - if params.keys(): + if params: res_show = config_show(ansible_module) - if not compare_args_ipa(ansible_module, params, res_show): + params = { + k: v for k, v in params.items() + if k not in res_show or res_show[k] != v + } + if params \ + and not compare_args_ipa(ansible_module, params, res_show): changed = True api_command_no_name(ansible_module, "config_mod", params) @@ -445,7 +463,8 @@ def main(): exit_args[k] = (v[0] == "TRUE") else: exit_args[k] = v - + except ipalib.errors.EmptyModlist: + changed = False except Exception as e: ansible_module.fail_json(msg="%s %s" % (params, str(e))) diff --git a/tests/config/test_config.yml b/tests/config/test_config.yml index efa169de..c288e451 100644 --- a/tests/config/test_config.yml +++ b/tests/config/test_config.yml @@ -5,6 +5,7 @@ gather_facts: false tasks: + # Retrieve current configuration. - name: return current values of the global configuration options ipaconfig: ipaadmin_password: SomeADMINpassword @@ -13,131 +14,375 @@ - debug: msg: "{{previousconfig}}" - - name: set default shell to default value + # setup environment. + - name: create test group + ipagroup: + ipaadmin_password: 'SomeADMINpassword' + name: somedefaultgroup + + - name: Ensure the default e-mail domain is ipa.test. + ipaconfig: + ipaadmin_password: SomeADMINpassword + emaildomain: ipa.test + + - name: set default shell to '/bin/sh' ipaconfig: ipaadmin_password: SomeADMINpassword defaultshell: /bin/sh - register: result - failed_when: result.changed - - name: set default shell to new value + - name: set default group ipaconfig: ipaadmin_password: SomeADMINpassword - defaultshell: /bin/bash + defaultgroup: ipausers + + - name: set default home directory + ipaconfig: + ipaadmin_password: SomeADMINpassword + homedirectory: /home + + - name: clear pac-type + ipaconfig: + ipaadmin_password: SomeADMINpassword + pac_type: "" + + - name: set maxusername to 255 + ipaconfig: + ipaadmin_password: SomeADMINpassword + maxusername: 255 + + - name: set maxhostname to 255 + ipaconfig: + ipaadmin_password: SomeADMINpassword + maxhostname: 255 + + - name: set pwdexpnotify to 0 + ipaconfig: + ipaadmin_password: SomeADMINpassword + pwdexpnotify: 0 + + - name: set searchrecordslimit to 10 + ipaconfig: + ipaadmin_password: SomeADMINpassword + searchrecordslimit: 10 + + - name: set searchtimelimit to 1 + ipaconfig: + ipaadmin_password: SomeADMINpassword + searchtimelimit: 1 + + - name: clear configstring + ipaconfig: + ipaadmin_password: SomeADMINpassword + configstring: "" + + - name: set configstring to AllowNThash + ipaconfig: + ipaadmin_password: SomeADMINpassword + configstring: 'KDC:Disable Lockout' + + - name: set selinuxusermapdefault + ipaconfig: + ipaadmin_password: SomeADMINpassword + selinuxusermapdefault: "staff_u:s0-s0:c0.c1023" + + - name: set selinuxusermaporder + ipaconfig: + ipaadmin_password: SomeADMINpassword + selinuxusermaporder: 'user_u:s0$staff_u:s0-s0:c0.c1023' + + - name: set usersearch to `uid` + ipaconfig: + ipaadmin_password: SomeADMINpassword + usersearch: uid + + - name: set groupsearch to `cn` + ipaconfig: + ipaadmin_password: SomeADMINpassword + groupsearch: cn + + # tests + - name: Ensure the default e-mail domain is somedomain.test. + ipaconfig: + ipaadmin_password: SomeADMINpassword + emaildomain: somedomain.test register: result failed_when: not result.changed - - name: check default shell is changed + - name: Ensure the default e-mail domain is somedomain.test, again. ipaconfig: ipaadmin_password: SomeADMINpassword - defaultshell: /bin/bash + emaildomain: somedomain.test register: result failed_when: result.changed - - name: reset default shell to old value + - name: set default shell to '/bin/someshell' ipaconfig: ipaadmin_password: SomeADMINpassword - defaultshell: '{{previousconfig.config.defaultshell }}' + defaultshell: /bin/someshell register: result failed_when: not result.changed - - name: check default shell is reset + - name: set default shell to '/bin/someshell', again. ipaconfig: ipaadmin_password: SomeADMINpassword - defaultshell: '{{previousconfig.config.defaultshell }}' + defaultshell: /bin/someshell register: result failed_when: result.changed - - name: Ensure the default e-mail domain is ansible.com. + - name: set default group ipaconfig: ipaadmin_password: SomeADMINpassword - emaildomain: ansible.com + defaultgroup: somedefaultgroup register: result failed_when: not result.changed - - name: Ensure the default e-mail domain is set + - name: set default group ipaconfig: ipaadmin_password: SomeADMINpassword - emaildomain: ansible.com + defaultgroup: somedefaultgroup register: result failed_when: result.changed - - name: reset default e-mail domain + - name: set default home directory ipaconfig: ipaadmin_password: SomeADMINpassword - emaildomain: '{{previousconfig.config.emaildomain }}' + homedirectory: /Users register: result failed_when: not result.changed + - name: set default home directory + ipaconfig: + ipaadmin_password: SomeADMINpassword + homedirectory: /Users + register: result + failed_when: result.changed + - name: set pac-type ipaconfig: ipaadmin_password: SomeADMINpassword - pac_type: - - nfs:NONE + pac_type: "nfs:NONE" register: result failed_when: not result.changed - - name: reset pac-type + - name: set pac-type, again. ipaconfig: ipaadmin_password: SomeADMINpassword - pac_type: '{{previousconfig.config.pac_type}}' + pac_type: "nfs:NONE" + register: result + failed_when: result.changed + + - name: set maxusername to 33 + ipaconfig: + ipaadmin_password: SomeADMINpassword + maxusername: 33 register: result failed_when: not result.changed - - name: set usersearch + - name: set maxusername to 33, again. ipaconfig: ipaadmin_password: SomeADMINpassword - usersearch: - - uid + maxusername: 33 + register: result + failed_when: result.changed + + - name: set maxhostname to 77 + ipaconfig: + ipaadmin_password: SomeADMINpassword + maxhostname: 77 register: result failed_when: not result.changed - - name: check usersearch + - name: set maxhostname to 77, again ipaconfig: ipaadmin_password: SomeADMINpassword - usersearch: - - uid + maxhostname: 77 + register: result + failed_when: result.changed + + - name: set pwdexpnotify to 17 + ipaconfig: + ipaadmin_password: SomeADMINpassword + pwdexpnotify: 17 + register: result + failed_when: not result.changed + + - name: set pwdexpnotify to 17, again + ipaconfig: + ipaadmin_password: SomeADMINpassword + pwdexpnotify: 17 + register: result + failed_when: result.changed + + - name: set searchrecordslimit to -1 + ipaconfig: + ipaadmin_password: SomeADMINpassword + searchrecordslimit: -1 + register: result + failed_when: not result.changed + + - name: set searchrecordslimit to -1, again. + ipaconfig: + ipaadmin_password: SomeADMINpassword + searchrecordslimit: -1 + register: result + failed_when: result.changed + + - name: set searchtimelimit to 12345 + ipaconfig: + ipaadmin_password: SomeADMINpassword + searchtimelimit: 12345 + register: result + failed_when: not result.changed + + - name: set searchtimelimit to 12345, again. + ipaconfig: + ipaadmin_password: SomeADMINpassword + searchtimelimit: 12345 + register: result + failed_when: result.changed + + - name: change enable_migration + ipaconfig: + ipaadmin_password: SomeADMINpassword + enable_migration: '{{ not previousconfig.config.enable_migration }}' + register: result + failed_when: not result.changed + + - name: change enable_migration, again + ipaconfig: + ipaadmin_password: SomeADMINpassword + enable_migration: '{{ not previousconfig.config.enable_migration }}' + register: result + failed_when: result.changed + + - name: set configstring to AllowNThash + ipaconfig: + ipaadmin_password: SomeADMINpassword + configstring: AllowNThash + register: result + failed_when: not result.changed + + - name: set configstring to AllowNThash, again. + ipaconfig: + ipaadmin_password: SomeADMINpassword + configstring: AllowNThash + register: result + failed_when: result.changed + + - name: set selinuxusermaporder + ipaconfig: + ipaadmin_password: SomeADMINpassword + selinuxusermaporder: 'user_u:s0$staff_u:s0-s0:c0.c1023$sysadm_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023' + register: result + failed_when: not result.changed + + - name: set selinuxusermaporder, again + ipaconfig: + ipaadmin_password: SomeADMINpassword + selinuxusermaporder: 'user_u:s0$staff_u:s0-s0:c0.c1023$sysadm_u:s0-s0:c0.c1023$unconfined_u:s0-s0:c0.c1023' + register: result + failed_when: result.changed + + - name: set selinuxusermapdefault + ipaconfig: + ipaadmin_password: SomeADMINpassword + selinuxusermapdefault: 'user_u:s0' + register: result + failed_when: not result.changed + + - name: set selinuxusermapdefault, again + ipaconfig: + ipaadmin_password: SomeADMINpassword + selinuxusermapdefault: 'user_u:s0' + register: result + failed_when: result.changed + + - name: set groupsearch to `description` + ipaconfig: + ipaadmin_password: SomeADMINpassword + groupsearch: description + register: result + failed_when: not result.changed + + - name: set groupsearch to `gidNumber`, again + ipaconfig: + ipaadmin_password: SomeADMINpassword + groupsearch: description + register: result + failed_when: result.changed + + - name: set usersearch to `uidNumber` + ipaconfig: + ipaadmin_password: SomeADMINpassword + usersearch: uidNumber + register: result + failed_when: not result.changed + + - name: set usersearch to `uidNumber`, again + ipaconfig: + ipaadmin_password: SomeADMINpassword + usersearch: uidNumber register: result failed_when: result.changed - name: reset changed fields ipaconfig: ipaadmin_password: 'SomeADMINpassword' - configstring: '{{previousconfig.config.configstring}}' - emaildomain: '{{previousconfig.config.emaildomain}}' - defaultshell: '{{previousconfig.config.defaultshell}}' - defaultgroup: '{{previousconfig.config.defaultgroup}}' - groupsearch: '{{previousconfig.config.groupsearch}}' - homedirectory: '{{previousconfig.config.homedirectory}}' - pac_type: '{{previousconfig.config.pac_type}}' - maxusername: '{{previousconfig.config.maxusername}}' - enable_migration: '{{previousconfig.config.enable_migration}}' - pwdexpnotify: '{{previousconfig.config.pwdexpnotify}}' - searchrecordslimit: '{{previousconfig.config.searchrecordslimit}}' - searchtimelimit: '{{previousconfig.config.searchtimelimit}}' - selinuxusermapdefault: '{{previousconfig.config.selinuxusermapdefault}}' - selinuxusermaporder: '{{previousconfig.config.selinuxusermaporder}}' - usersearch: '{{previousconfig.config.usersearch}}' + maxusername: '{{previousconfig.config.maxusername | default(omit)}}' + maxhostname: '{{previousconfig.config.maxhostname | default(omit)}}' + homedirectory: '{{previousconfig.config.homedirectory | default(omit)}}' + defaultshell: '{{previousconfig.config.defaultshell | default(omit)}}' + defaultgroup: '{{previousconfig.config.defaultgroup | default(omit)}}' + emaildomain: '{{previousconfig.config.emaildomain | default(omit)}}' + searchtimelimit: '{{previousconfig.config.searchtimelimit | default(omit)}}' + searchrecordslimit: '{{previousconfig.config.searchrecordslimit | default(omit)}}' + usersearch: '{{previousconfig.config.usersearch | default(omit)}}' + groupsearch: '{{previousconfig.config.groupsearch | default(omit)}}' + enable_migration: '{{previousconfig.config.enable_migration | default(omit)}}' + groupobjectclasses: '{{previousconfig.config.groupobjectclasses | default(omit)}}' + userobjectclasses: '{{previousconfig.config.userobjectclasses | default(omit)}}' + pwdexpnotify: '{{previousconfig.config.pwdexpnotify | default(omit)}}' + configstring: '{{previousconfig.config.configstring | default(omit)}}' + selinuxusermapdefault: '{{previousconfig.config.selinuxusermapdefault | default(omit)}}' + selinuxusermaporder: '{{previousconfig.config.selinuxusermaporder | default(omit)}}' + pac_type: '{{previousconfig.config.pac_type | default(omit)}}' + user_auth_type: '{{previousconfig.config.user_auth_type | default(omit)}}' + domain_resolution_order: '{{previousconfig.config.domain_resolution_order | default(omit)}}' + ca_renewal_master_server: '{{previousconfig.config.ca_renewal_master_server | default(omit)}}' register: result failed_when: not result.changed - - name: check reset fields + - name: reset changed fields, again ipaconfig: ipaadmin_password: 'SomeADMINpassword' - configstring: '{{previousconfig.config.configstring}}' - emaildomain: '{{previousconfig.config.emaildomain}}' - defaultshell: '{{previousconfig.config.defaultshell}}' - defaultgroup: '{{previousconfig.config.defaultgroup}}' - groupsearch: '{{previousconfig.config.groupsearch}}' - homedirectory: '{{previousconfig.config.homedirectory}}' - pac_type: '{{previousconfig.config.pac_type}}' - maxusername: '{{previousconfig.config.maxusername}}' - enable_migration: '{{previousconfig.config.enable_migration}}' - pwdexpnotify: '{{previousconfig.config.pwdexpnotify}}' - searchrecordslimit: '{{previousconfig.config.searchrecordslimit}}' - searchtimelimit: '{{previousconfig.config.searchtimelimit}}' - selinuxusermapdefault: '{{previousconfig.config.selinuxusermapdefault}}' - selinuxusermaporder: '{{previousconfig.config.selinuxusermaporder}}' - usersearch: '{{previousconfig.config.usersearch}}' + maxusername: '{{previousconfig.config.maxusername | default(omit)}}' + maxhostname: '{{previousconfig.config.maxhostname | default(omit)}}' + homedirectory: '{{previousconfig.config.homedirectory | default(omit)}}' + defaultshell: '{{previousconfig.config.defaultshell | default(omit)}}' + defaultgroup: '{{previousconfig.config.defaultgroup | default(omit)}}' + emaildomain: '{{previousconfig.config.emaildomain | default(omit)}}' + searchtimelimit: '{{previousconfig.config.searchtimelimit | default(omit)}}' + searchrecordslimit: '{{previousconfig.config.searchrecordslimit | default(omit)}}' + usersearch: '{{previousconfig.config.usersearch | default(omit)}}' + groupsearch: '{{previousconfig.config.groupsearch | default(omit)}}' + enable_migration: '{{previousconfig.config.enable_migration | default(omit)}}' + groupobjectclasses: '{{previousconfig.config.groupobjectclasses | default(omit)}}' + userobjectclasses: '{{previousconfig.config.userobjectclasses | default(omit)}}' + pwdexpnotify: '{{previousconfig.config.pwdexpnotify | default(omit)}}' + configstring: '{{previousconfig.config.configstring | default(omit)}}' + selinuxusermapdefault: '{{previousconfig.config.selinuxusermapdefault | default(omit)}}' + selinuxusermaporder: '{{previousconfig.config.selinuxusermaporder | default(omit)}}' + pac_type: '{{previousconfig.config.pac_type | default(omit)}}' + user_auth_type: '{{previousconfig.config.user_auth_type | default(omit)}}' + domain_resolution_order: '{{previousconfig.config.domain_resolution_order | default(omit)}}' + ca_renewal_master_server: '{{previousconfig.config.ca_renewal_master_server | default(omit)}}' register: result failed_when: result.changed + + # cleanup + + - name: cleanup test group + ipagroup: + ipaadmin_password: 'SomeADMINpassword' + name: somedefaultgroup + state: absent