diff --git a/.ansible-freeipa.metadata b/.ansible-freeipa.metadata index d534268..aaec13d 100644 --- a/.ansible-freeipa.metadata +++ b/.ansible-freeipa.metadata @@ -1 +1 @@ -583ac570c030eb68a2026a506054f2f93587beb4 SOURCES/ansible-freeipa-0.1.8.tar.gz +a139427bb9c6fd44bd59ab258d1b17827a3dbe9a SOURCES/ansible-freeipa-0.1.10.tar.gz diff --git a/.gitignore b/.gitignore index b19cd6f..154e3ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/ansible-freeipa-0.1.8.tar.gz +SOURCES/ansible-freeipa-0.1.10.tar.gz diff --git a/SOURCES/ansible-freeipa-0.1.8-Add-missing-attributes-to-ipasudorule_rhbz#1788168,1788035,1788024.patch b/SOURCES/ansible-freeipa-0.1.8-Add-missing-attributes-to-ipasudorule_rhbz#1788168,1788035,1788024.patch deleted file mode 100644 index f5c5147..0000000 --- a/SOURCES/ansible-freeipa-0.1.8-Add-missing-attributes-to-ipasudorule_rhbz#1788168,1788035,1788024.patch +++ /dev/null @@ -1,1129 +0,0 @@ -From dc0a5585fb036fbeba2200564e26c478465afeec Mon Sep 17 00:00:00 2001 -From: Rafael Guterres Jeffman -Date: Tue, 31 Dec 2019 11:04:49 -0300 -Subject: [PATCH] Add missing attributes to ipasudorule. - -This patch adds the following attributes to ipasudorule: - - - order - - sudooption - - runasuser - - runasgroup - -It also fixes behavior of sudocmd assigned to the the sudorule, with the -adittion of the attributes: - - - allow_sudocmds - - deny_sudocmds - - allow_sudocmdgroups - - deny_sudocmdgroups - -README-sudorule and tests have been updated to comply with the changes. ---- - README-sudorule.md | 14 +- - ...sure-sudorule-does-not-have-sudooption.yml | 14 + - .../ensure-sudorule-has-sudooption.yml | 13 + - .../ensure-sudorule-is-present-with-order.yml | 12 + - .../sudorule/ensure-sudorule-is-present.yml | 2 + - .../ensure-sudorule-runasuser-is-absent.yml | 14 + - .../ensure-sudorule-runasuser-is-present.yml | 13 + - .../ensure-sudorule-sudocmd-is-absent.yml | 7 +- - .../ensure-sudorule-sudocmd-is-present.yml | 7 +- - plugins/modules/ipasudorule.py | 353 +++++++++++++----- - tests/sudorule/test_sudorule.yml | 204 +++++++--- - 11 files changed, 504 insertions(+), 149 deletions(-) - create mode 100644 playbooks/sudorule/ensure-sudorule-does-not-have-sudooption.yml - create mode 100644 playbooks/sudorule/ensure-sudorule-has-sudooption.yml - create mode 100644 playbooks/sudorule/ensure-sudorule-is-present-with-order.yml - create mode 100644 playbooks/sudorule/ensure-sudorule-runasuser-is-absent.yml - create mode 100644 playbooks/sudorule/ensure-sudorule-runasuser-is-present.yml - -diff --git a/README-sudorule.md b/README-sudorule.md -index bb3498b..50c73ad 100644 ---- a/README-sudorule.md -+++ b/README-sudorule.md -@@ -68,7 +68,7 @@ Example playbook to make sure sudocmds are present in Sudo Rule: - - ipasudorule: - ipaadmin_password: MyPassword123 - name: testrule1 -- cmd: -+ allow_sudocmd: - - /sbin/ifconfig - action: member - ``` -@@ -87,7 +87,7 @@ Example playbook to make sure sudocmds are not present in Sudo Rule: - - ipasudorule: - ipaadmin_password: MyPassword123 - name: testrule1 -- cmd: -+ allow_sudocmd: - - /sbin/ifconfig - action: member - state: absent -@@ -130,8 +130,14 @@ Variable | Description | Required - `hostgroup` | List of host group name strings assigned to this sudorule. | no - `user` | List of user name strings assigned to this sudorule. | no - `group` | List of user group name strings assigned to this sudorule. | no --`cmd` | List of sudocmd name strings assigned to this sudorule. | no --`cmdgroup` | List of sudocmd group name strings assigned wto this sudorule. | no -+`allow_sudocmd` | List of sudocmd name strings assigned to the allow group of this sudorule. | no -+`deny_sudocmd` | List of sudocmd name strings assigned to the deny group of this sudorule. | no -+`allow_sudocmdgroup` | List of sudocmd groups name strings assigned to the allow group of this sudorule. | no -+`deny_sudocmdgroup` | List of sudocmd groups name strings assigned to the deny group of this sudorule. | no -+`sudooption` \| `option` | List of options to the sudorule | no -+`order` | Integer to order the sudorule | no -+`runasuser` | List of users for Sudo to execute as. | no -+`runasgroup` | List of groups for Sudo to execute as. | no - `action` | Work on sudorule or member level. It can be on of `member` or `sudorule` and defaults to `sudorule`. | no - `state` | The state to ensure. It can be one of `present`, `absent`, `enabled` or `disabled`, default: `present`. | no - -diff --git a/playbooks/sudorule/ensure-sudorule-does-not-have-sudooption.yml b/playbooks/sudorule/ensure-sudorule-does-not-have-sudooption.yml -new file mode 100644 -index 0000000..1307044 ---- /dev/null -+++ b/playbooks/sudorule/ensure-sudorule-does-not-have-sudooption.yml -@@ -0,0 +1,14 @@ -+--- -+- name: Tests -+ hosts: ipaserver -+ become: true -+ gather_facts: false -+ -+ tasks: -+ # Ensure sudooption is absent in sudorule -+ - ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ sudooption: "!root" -+ action: member -+ state: absent -diff --git a/playbooks/sudorule/ensure-sudorule-has-sudooption.yml b/playbooks/sudorule/ensure-sudorule-has-sudooption.yml -new file mode 100644 -index 0000000..1f32b9a ---- /dev/null -+++ b/playbooks/sudorule/ensure-sudorule-has-sudooption.yml -@@ -0,0 +1,13 @@ -+--- -+- name: Tests -+ hosts: ipaserver -+ become: true -+ gather_facts: false -+ -+ tasks: -+ # Ensure sudooption is present in sudorule -+ - ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ sudooption: "!root" -+ action: member -diff --git a/playbooks/sudorule/ensure-sudorule-is-present-with-order.yml b/playbooks/sudorule/ensure-sudorule-is-present-with-order.yml -new file mode 100644 -index 0000000..9a3c2b2 ---- /dev/null -+++ b/playbooks/sudorule/ensure-sudorule-is-present-with-order.yml -@@ -0,0 +1,12 @@ -+--- -+- name: Tests -+ hosts: ipaserver -+ become: true -+ gather_facts: false -+ -+ tasks: -+ # Ensure sudorule is present with the given order. -+ - ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ order: 2 -diff --git a/playbooks/sudorule/ensure-sudorule-is-present.yml b/playbooks/sudorule/ensure-sudorule-is-present.yml -index 5b8f32b..89041af 100644 ---- a/playbooks/sudorule/ensure-sudorule-is-present.yml -+++ b/playbooks/sudorule/ensure-sudorule-is-present.yml -@@ -9,4 +9,6 @@ - ipaadmin_password: MyPassword123 - name: testrule1 - description: A test sudo rule. -+ allow_sudocmd: /bin/ls -+ deny_sudocmd: /bin/vim - state: present -diff --git a/playbooks/sudorule/ensure-sudorule-runasuser-is-absent.yml b/playbooks/sudorule/ensure-sudorule-runasuser-is-absent.yml -new file mode 100644 -index 0000000..56612f1 ---- /dev/null -+++ b/playbooks/sudorule/ensure-sudorule-runasuser-is-absent.yml -@@ -0,0 +1,14 @@ -+--- -+- name: Tests -+ hosts: ipaserver -+ become: true -+ gather_facts: false -+ -+ tasks: -+ # Ensure sudorule is present with the given order. -+ - ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ runasuser: admin -+ action: member -+ state: absent -diff --git a/playbooks/sudorule/ensure-sudorule-runasuser-is-present.yml b/playbooks/sudorule/ensure-sudorule-runasuser-is-present.yml -new file mode 100644 -index 0000000..8af49b9 ---- /dev/null -+++ b/playbooks/sudorule/ensure-sudorule-runasuser-is-present.yml -@@ -0,0 +1,13 @@ -+--- -+- name: Tests -+ hosts: ipaserver -+ become: true -+ gather_facts: false -+ -+ tasks: -+ # Ensure sudorule is present with the given order. -+ - ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ runasuser: admin -+ action: member -diff --git a/playbooks/sudorule/ensure-sudorule-sudocmd-is-absent.yml b/playbooks/sudorule/ensure-sudorule-sudocmd-is-absent.yml -index 942d0b5..328242a 100644 ---- a/playbooks/sudorule/ensure-sudorule-sudocmd-is-absent.yml -+++ b/playbooks/sudorule/ensure-sudorule-sudocmd-is-absent.yml -@@ -8,8 +8,13 @@ - - ipasudorule: - ipaadmin_password: MyPassword123 - name: testrule1 -- cmd: -+ allow_sudocmd: - - /sbin/ifconfig -+ deny_sudocmd: - - /usr/bin/vim -+ allow_sudocmdgroup: -+ - devops -+ deny_sudocmdgroup: -+ - users - action: member - state: absent -diff --git a/playbooks/sudorule/ensure-sudorule-sudocmd-is-present.yml b/playbooks/sudorule/ensure-sudorule-sudocmd-is-present.yml -index 61fcbb0..55acd61 100644 ---- a/playbooks/sudorule/ensure-sudorule-sudocmd-is-present.yml -+++ b/playbooks/sudorule/ensure-sudorule-sudocmd-is-present.yml -@@ -8,7 +8,12 @@ - - ipasudorule: - ipaadmin_password: MyPassword123 - name: testrule1 -- cmd: -+ allow_sudocmd: - - /sbin/ifconfig -+ deny_sudocmd: - - /usr/bin/vim -+ allow_sudocmdgroup: -+ - devops -+ deny_sudocmdgroup: -+ - users - action: member -diff --git a/plugins/modules/ipasudorule.py b/plugins/modules/ipasudorule.py -index c21f247..285a946 100644 ---- a/plugins/modules/ipasudorule.py -+++ b/plugins/modules/ipasudorule.py -@@ -79,18 +79,43 @@ - description: Host category the sudo rule applies to. - required: false - choices: ["all"] -- cmd: -- description: List of sudocmds assigned to this sudorule. -+ allow_sudocmd: -+ description: List of allowed sudocmds assigned to this sudorule. - required: false - type: list -- cmdgroup: -- description: List of sudocmd groups assigned to this sudorule. -+ allow_sudocmdgroup: -+ description: List of allowed sudocmd groups assigned to this sudorule. -+ required: false -+ type: list -+ deny_sudocmd: -+ description: List of denied sudocmds assigned to this sudorule. -+ required: false -+ type: list -+ deny_sudocmdgroup: -+ description: List of denied sudocmd groups assigned to this sudorule. - required: false - type: list - cmdcategory: -- description: Cammand category the sudo rule applies to -+ description: Command category the sudo rule applies to - required: false - choices: ["all"] -+ order: -+ description: Order to apply this rule. -+ required: false -+ type: int -+ sudooption: -+ description: -+ required: false -+ type: list -+ aliases: ["options"] -+ runasuser: -+ description: List of users for Sudo to execute as. -+ required: false -+ type: list -+ runasgroup: -+ description: List of groups for Sudo to execute as. -+ required: false -+ type: list - action: - description: Work on sudorule or member level - default: sudorule -@@ -111,13 +136,13 @@ - - # Ensure sudocmd is present in Sudo Rule - - ipasudorule: -- ipaadmin_password: pass1234 -- name: testrule1 -- cmd: -- - /sbin/ifconfig -- - /usr/bin/vim -- action: member -- state: absent -+ ipaadmin_password: pass1234 -+ name: testrule1 -+ allow_sudocmd: -+ - /sbin/ifconfig -+ - /usr/bin/vim -+ action: member -+ state: absent - - # Ensure host server is present in Sudo Rule - - ipasudorule: -@@ -160,7 +185,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, compare_args_ipa, \ -- module_params_get -+ module_params_get, gen_add_del_lists - - - def find_sudorule(module, name): -@@ -180,14 +205,26 @@ def find_sudorule(module, name): - return None - - --def gen_args(ansible_module): -- arglist = ['description', 'usercategory', 'hostcategory', 'cmdcategory', -- 'runasusercategory', 'runasgroupcategory', 'nomembers'] -+def gen_args(description, usercat, hostcat, cmdcat, runasusercat, -+ runasgroupcat, order, nomembers): - _args = {} -- for arg in arglist: -- value = module_params_get(ansible_module, arg) -- if value is not None: -- _args[arg] = value -+ -+ if description is not None: -+ _args['description'] = description -+ if usercat is not None: -+ _args['usercategory'] = usercat -+ if hostcat is not None: -+ _args['hostcategory'] = hostcat -+ if cmdcat is not None: -+ _args['cmdcategory'] = cmdcat -+ if runasusercat is not None: -+ _args['ipasudorunasusercategory'] = runasusercat -+ if runasgroupcat is not None: -+ _args['ipasudorunasgroupcategory'] = runasgroupcat -+ if order is not None: -+ _args['sudoorder'] = order -+ if nomembers is not None: -+ _args['nomembers'] = nomembers - - return _args - -@@ -212,13 +249,21 @@ def main(): - hostgroup=dict(required=False, type='list', default=None), - user=dict(required=False, type='list', default=None), - group=dict(required=False, type='list', default=None), -- cmd=dict(required=False, type="list", default=None), -+ allow_sudocmd=dict(required=False, type="list", default=None), -+ deny_sudocmd=dict(required=False, type="list", default=None), -+ allow_sudocmdgroup=dict(required=False, type="list", default=None), -+ deny_sudocmdgroup=dict(required=False, type="list", default=None), - cmdcategory=dict(required=False, type="str", default=None, - choices=["all"]), - runasusercategory=dict(required=False, type="str", default=None, - choices=["all"]), - runasgroupcategory=dict(required=False, type="str", default=None, - choices=["all"]), -+ runasuser=dict(required=False, type="list", default=None), -+ runasgroup=dict(required=False, type="list", default=None), -+ order=dict(type="int", required=False, aliases=['sudoorder']), -+ sudooption=dict(required=False, type='list', default=None, -+ aliases=["options"]), - action=dict(type="str", default="sudorule", - choices=["member", "sudorule"]), - # state -@@ -256,8 +301,16 @@ def main(): - hostgroup = module_params_get(ansible_module, "hostgroup") - user = module_params_get(ansible_module, "user") - group = module_params_get(ansible_module, "group") -- cmd = module_params_get(ansible_module, 'cmd') -- cmdgroup = module_params_get(ansible_module, 'cmdgroup') -+ allow_sudocmd = module_params_get(ansible_module, 'allow_sudocmd') -+ allow_sudocmdgroup = module_params_get(ansible_module, -+ 'allow_sudocmdgroup') -+ deny_sudocmd = module_params_get(ansible_module, 'deny_sudocmd') -+ deny_sudocmdgroup = module_params_get(ansible_module, -+ 'deny_sudocmdgroup') -+ sudooption = module_params_get(ansible_module, "sudooption") -+ order = module_params_get(ansible_module, "order") -+ runasuser = module_params_get(ansible_module, "runasuser") -+ runasgroup = module_params_get(ansible_module, "runasgroup") - action = module_params_get(ansible_module, "action") - - # state -@@ -272,28 +325,30 @@ def main(): - if action == "member": - invalid = ["description", "usercategory", "hostcategory", - "cmdcategory", "runasusercategory", -- "runasgroupcategory", "nomembers"] -+ "runasgroupcategory", "order", "nomembers"] - -- for x in invalid: -- if x in vars() and vars()[x] is not None: -+ for arg in invalid: -+ if arg in vars() and vars()[arg] is not None: - ansible_module.fail_json( - msg="Argument '%s' can not be used with action " -- "'%s'" % (x, action)) -+ "'%s'" % (arg, action)) - - elif state == "absent": - if len(names) < 1: - ansible_module.fail_json(msg="No name given.") - invalid = ["description", "usercategory", "hostcategory", - "cmdcategory", "runasusercategory", -- "runasgroupcategory", "nomembers"] -+ "runasgroupcategory", "nomembers", "order"] - if action == "sudorule": - invalid.extend(["host", "hostgroup", "user", "group", -- "cmd", "cmdgroup"]) -- for x in invalid: -- if vars()[x] is not None: -+ "runasuser", "runasgroup", "allow_sudocmd", -+ "allow_sudocmdgroup", "deny_sudocmd", -+ "deny_sudocmdgroup", "sudooption"]) -+ for arg in invalid: -+ if vars()[arg] is not None: - ansible_module.fail_json( - msg="Argument '%s' can not be used with state '%s'" % -- (x, state)) -+ (arg, state)) - - elif state in ["enabled", "disabled"]: - if len(names) < 1: -@@ -305,12 +360,14 @@ def main(): - invalid = ["description", "usercategory", "hostcategory", - "cmdcategory", "runasusercategory", "runasgroupcategory", - "nomembers", "nomembers", "host", "hostgroup", -- "user", "group", "cmd", "cmdgroup"] -- for x in invalid: -- if vars()[x] is not None: -+ "user", "group", "allow_sudocmd", "allow_sudocmdgroup", -+ "deny_sudocmd", "deny_sudocmdgroup", "runasuser", -+ "runasgroup", "order", "sudooption"] -+ for arg in invalid: -+ if vars()[arg] is not None: - ansible_module.fail_json( - msg="Argument '%s' can not be used with state '%s'" % -- (x, state)) -+ (arg, state)) - else: - ansible_module.fail_json(msg="Invalid state '%s'" % state) - -@@ -335,7 +392,9 @@ def main(): - # Create command - if state == "present": - # Generate args -- args = gen_args(ansible_module) -+ args = gen_args(description, usercategory, hostcategory, -+ cmdcategory, runasusercategory, -+ runasgroupcategory, order, nomembers) - if action == "sudorule": - # Found the sudorule - if res_find is not None: -@@ -351,44 +410,42 @@ def main(): - res_find = {} - - # Generate addition and removal lists -- host_add = list( -- set(host or []) - -- set(res_find.get("member_host", []))) -- host_del = list( -- set(res_find.get("member_host", [])) - -- set(host or [])) -- hostgroup_add = list( -- set(hostgroup or []) - -- set(res_find.get("member_hostgroup", []))) -- hostgroup_del = list( -- set(res_find.get("member_hostgroup", [])) - -- set(hostgroup or [])) -- -- user_add = list( -- set(user or []) - -- set(res_find.get("member_user", []))) -- user_del = list( -- set(res_find.get("member_user", [])) - -- set(user or [])) -- group_add = list( -- set(group or []) - -- set(res_find.get("member_group", []))) -- group_del = list( -- set(res_find.get("member_group", [])) - -- set(group or [])) -- -- cmd_add = list( -- set(cmd or []) - -- set(res_find.get("member_cmd", []))) -- cmd_del = list( -- set(res_find.get("member_cmd", [])) - -- set(cmd or [])) -- cmdgroup_add = list( -- set(cmdgroup or []) - -- set(res_find.get("member_cmdgroup", []))) -- cmdgroup_del = list( -- set(res_find.get("member_cmdgroup", [])) - -- set(cmdgroup or [])) -+ host_add, host_del = gen_add_del_lists( -+ host, res_find.get('member_host', [])) -+ -+ hostgroup_add, hostgroup_del = gen_add_del_lists( -+ hostgroup, res_find.get('member_hostgroup', [])) -+ -+ user_add, user_del = gen_add_del_lists( -+ user, res_find.get('member_user', [])) -+ -+ group_add, group_del = gen_add_del_lists( -+ group, res_find.get('member_group', [])) -+ -+ allow_cmd_add, allow_cmd_del = gen_add_del_lists( -+ allow_sudocmd, -+ res_find.get('memberallowcmd_sudocmd', [])) -+ -+ allow_cmdgroup_add, allow_cmdgroup_del = gen_add_del_lists( -+ allow_sudocmdgroup, -+ res_find.get('memberallowcmd_sudocmdgroup', [])) -+ -+ deny_cmd_add, deny_cmd_del = gen_add_del_lists( -+ deny_sudocmd, -+ res_find.get('memberdenycmd_sudocmd', [])) -+ -+ deny_cmdgroup_add, deny_cmdgroup_del = gen_add_del_lists( -+ deny_sudocmdgroup, -+ res_find.get('memberdenycmd_sudocmdgroup', [])) -+ -+ sudooption_add, sudooption_del = gen_add_del_lists( -+ sudooption, res_find.get('ipasudoopt', [])) -+ -+ runasuser_add, runasuser_del = gen_add_del_lists( -+ runasuser, res_find.get('ipasudorunas_user', [])) -+ -+ runasgroup_add, runasgroup_del = gen_add_del_lists( -+ runasgroup, res_find.get('ipasudorunas_group', [])) - - # Add hosts and hostgroups - if len(host_add) > 0 or len(hostgroup_add) > 0: -@@ -420,20 +477,59 @@ def main(): - "group": group_del, - }]) - -- # Add commands -- if len(cmd_add) > 0 or len(cmdgroup_add) > 0: -+ # Add commands allowed -+ if len(allow_cmd_add) > 0 or len(allow_cmdgroup_add) > 0: - commands.append([name, "sudorule_add_allow_command", -- { -- "sudocmd": cmd_add, -- "sudocmdgroup": cmdgroup_add, -- }]) -- -- if len(cmd_del) > 0 or len(cmdgroup_del) > 0: -+ {"sudocmd": allow_cmd_add, -+ "sudocmdgroup": allow_cmdgroup_add, -+ }]) -+ -+ if len(allow_cmd_del) > 0 or len(allow_cmdgroup_del) > 0: -+ commands.append([name, "sudorule_remove_allow_command", -+ {"sudocmd": allow_cmd_del, -+ "sudocmdgroup": allow_cmdgroup_del -+ }]) -+ -+ # Add commands denied -+ if len(deny_cmd_add) > 0 or len(deny_cmdgroup_add) > 0: - commands.append([name, "sudorule_add_deny_command", -- { -- "sudocmd": cmd_del, -- "sudocmdgroup": cmdgroup_del -- }]) -+ {"sudocmd": deny_cmd_add, -+ "sudocmdgroup": deny_cmdgroup_add, -+ }]) -+ -+ if len(deny_cmd_del) > 0 or len(deny_cmdgroup_del) > 0: -+ commands.append([name, "sudorule_remove_deny_command", -+ {"sudocmd": deny_cmd_del, -+ "sudocmdgroup": deny_cmdgroup_del -+ }]) -+ -+ # Add RunAS Users -+ if len(runasuser_add) > 0: -+ commands.append([name, "sudorule_add_runasuser", -+ {"user": runasuser_add}]) -+ # Remove RunAS Users -+ if len(runasuser_del) > 0: -+ commands.append([name, "sudorule_remove_runasuser", -+ {"user": runasuser_del}]) -+ -+ # Add RunAS Groups -+ if len(runasgroup_add) > 0: -+ commands.append([name, "sudorule_add_runasgroup", -+ {"group": runasgroup_add}]) -+ # Remove RunAS Groups -+ if len(runasgroup_del) > 0: -+ commands.append([name, "sudorule_remove_runasgroup", -+ {"group": runasgroup_del}]) -+ -+ # Add sudo options -+ for sudoopt in sudooption_add: -+ commands.append([name, "sudorule_add_option", -+ {"ipasudoopt": sudoopt}]) -+ -+ # Remove sudo options -+ for sudoopt in sudooption_del: -+ commands.append([name, "sudorule_remove_option", -+ {"ipasudoopt": sudoopt}]) - - elif action == "member": - if res_find is None: -@@ -456,11 +552,38 @@ def main(): - }]) - - # Add commands -- if cmd is not None: -+ if allow_sudocmd is not None \ -+ or allow_sudocmdgroup is not None: - commands.append([name, "sudorule_add_allow_command", -- { -- "sudocmd": cmd, -- }]) -+ {"sudocmd": allow_sudocmd, -+ "sudocmdgroup": allow_sudocmdgroup, -+ }]) -+ -+ # Add commands -+ if deny_sudocmd is not None \ -+ or deny_sudocmdgroup is not None: -+ commands.append([name, "sudorule_add_deny_command", -+ {"sudocmd": deny_sudocmd, -+ "sudocmdgroup": deny_sudocmdgroup, -+ }]) -+ -+ # Add RunAS Users -+ if runasuser is not None: -+ commands.append([name, "sudorule_add_runasuser", -+ {"user": runasuser}]) -+ -+ # Add RunAS Groups -+ if runasgroup is not None: -+ commands.append([name, "sudorule_add_runasgroup", -+ {"group": runasgroup}]) -+ -+ # Add options -+ if sudooption is not None: -+ existing_opts = res_find.get('ipasudoopt', []) -+ for sudoopt in sudooption: -+ if sudoopt not in existing_opts: -+ commands.append([name, "sudorule_add_option", -+ {"ipasudoopt": sudoopt}]) - - elif state == "absent": - if action == "sudorule": -@@ -487,12 +610,40 @@ def main(): - "group": group, - }]) - -- # Remove commands -- if cmd is not None: -- commands.append([name, "sudorule_add_deny_command", -- { -- "sudocmd": cmd, -- }]) -+ # Remove allow commands -+ if allow_sudocmd is not None \ -+ or allow_sudocmdgroup is not None: -+ commands.append([name, "sudorule_remove_allow_command", -+ {"sudocmd": allow_sudocmd, -+ "sudocmdgroup": allow_sudocmdgroup -+ }]) -+ -+ # Remove deny commands -+ if deny_sudocmd is not None \ -+ or deny_sudocmdgroup is not None: -+ commands.append([name, "sudorule_remove_deny_command", -+ {"sudocmd": deny_sudocmd, -+ "sudocmdgroup": deny_sudocmdgroup -+ }]) -+ -+ # Remove RunAS Users -+ if runasuser is not None: -+ commands.append([name, "sudorule_remove_runasuser", -+ {"user": runasuser}]) -+ -+ # Remove RunAS Groups -+ if runasgroup is not None: -+ commands.append([name, "sudorule_remove_runasgroup", -+ {"group": runasgroup}]) -+ -+ # Remove options -+ if sudooption is not None: -+ existing_opts = res_find.get('ipasudoopt', []) -+ for sudoopt in sudooption: -+ if sudoopt in existing_opts: -+ commands.append([name, -+ "sudorule_remove_option", -+ {"ipasudoopt": sudoopt}]) - - elif state == "enabled": - if res_find is None: -@@ -530,9 +681,9 @@ def main(): - changed = True - else: - changed = True -- except Exception as e: -+ except Exception as ex: - ansible_module.fail_json(msg="%s: %s: %s" % (command, name, -- str(e))) -+ str(ex))) - # Get all errors - # All "already a member" and "not a member" failures in the - # result are ignored. All others are reported. -@@ -549,8 +700,8 @@ def main(): - if len(errors) > 0: - ansible_module.fail_json(msg=", ".join(errors)) - -- except Exception as e: -- ansible_module.fail_json(msg=str(e)) -+ except Exception as ex: -+ ansible_module.fail_json(msg=str(ex)) - - finally: - temp_kdestroy(ccache_dir, ccache_name) -diff --git a/tests/sudorule/test_sudorule.yml b/tests/sudorule/test_sudorule.yml -index 88ed90a..25090bb 100644 ---- a/tests/sudorule/test_sudorule.yml -+++ b/tests/sudorule/test_sudorule.yml -@@ -16,15 +16,22 @@ - - - name: Ensure some sudocmds are available - ipasudocmd: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: - - /sbin/ifconfig - - /usr/bin/vim - state: present - -+ - name: Ensure sudocmdgroup is available -+ ipasudocmdgroup: -+ ipaadmin_password: MyPassword123 -+ name: test_sudorule -+ sudocmd: /usr/bin/vim -+ state: present -+ - - name: Ensure sudorules are absent - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: - - testrule1 - - allusers -@@ -34,21 +41,21 @@ - - - name: Ensure sudorule is present - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - register: result - failed_when: not result.changed - - - name: Ensure sudorule is present again - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - register: result - failed_when: result.changed - - - name: Ensure sudorule is present, runAsUserCategory. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - runAsUserCategory: all - register: result -@@ -56,7 +63,7 @@ - - - name: Ensure sudorule is present, with usercategory 'all' - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allusers - usercategory: all - register: result -@@ -64,7 +71,7 @@ - - - name: Ensure sudorule is present, with usercategory 'all', again - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allusers - usercategory: all - register: result -@@ -72,7 +79,7 @@ - - - name: Ensure sudorule is present, with hostategory 'all' - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allhosts - hostcategory: all - register: result -@@ -80,7 +87,7 @@ - - - name: Ensure sudorule is present, with hostategory 'all', again - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allhosts - hostcategory: all - register: result -@@ -88,13 +95,13 @@ - - - name: Ensure sudorule is disabled - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - state: disabled - - - name: Ensure sudorule is disabled, again - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - state: disabled - register: result -@@ -102,7 +109,7 @@ - - - name: Ensure sudorule is enabled - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - state: enabled - register: result -@@ -110,37 +117,77 @@ - - - name: Ensure sudorule is enabled, again - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - state: enabled - register: result - failed_when: result.changed - -- - name: Ensure sudorule is present and some sudocmd are a member of it. -+ - name: Ensure sudorule is present and some sudocmd are allowed. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 -- cmd: -+ allow_sudocmd: - - /sbin/ifconfig -- - /usr/bin/vim - action: member - register: result - failed_when: not result.changed - -- - name: Ensure sudorule is present and some sudocmd are a member of it, again. -+ - name: Ensure sudorule is present and some sudocmd are allowed, again. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 -- cmd: -+ allow_sudocmd: - - /sbin/ifconfig -+ action: member -+ register: result -+ failed_when: result.changed -+ -+ - name: Ensure sudorule is present and some sudocmd are denyed. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ deny_sudocmd: -+ - /usr/bin/vim -+ action: member -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure sudorule is present and some sudocmd are denyed, again. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ deny_sudocmd: - - /usr/bin/vim - action: member - register: result - failed_when: result.changed - -+ - name: Ensure sudorule is present and, sudocmds are absent. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ allow_sudocmd: /sbin/ifconfig -+ deny_sudocmd: /usr/bin/vim -+ action: member -+ state: absent -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure sudorule is present and, sudocmds are absent, again. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ allow_sudocmd: /sbin/ifconfig -+ deny_sudocmd: /usr/bin/vim -+ action: member -+ state: absent -+ register: result -+ failed_when: result.changed -+ - - name: Ensure sudorule is present with cmdcategory 'all'. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allcommands - cmdcategory: all - register: result -@@ -148,7 +195,7 @@ - - - name: Ensure sudorule is present with cmdcategory 'all', again. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allcommands - cmdcategory: all - register: result -@@ -156,7 +203,7 @@ - - - name: Ensure host "{{ groups.ipaserver[0] }}" is present in sudorule. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - host: "{{ groups.ipaserver[0] }}" - action: member -@@ -165,7 +212,7 @@ - - - name: Ensure host "{{ groups.ipaserver[0] }}" is present in sudorule, again. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - host: "{{ groups.ipaserver[0] }}" - action: member -@@ -190,25 +237,77 @@ - register: result - failed_when: result.changed - -- - name: Ensure sudorule sudocmds are absent -+ - name: Ensure sudorule is present, with an allow_sudocmdgroup. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 -- cmd: -- - /sbin/ifconfig -- - /usr/bin/vim -+ allow_sudocmdgroup: test_sudorule -+ state: present -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure sudorule is present, with an allow_sudocmdgroup, again. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ allow_sudocmdgroup: test_sudorule -+ state: present -+ register: result -+ failed_when: result.changed -+ -+ - name: Ensure sudorule is present, but allow_sudocmdgroup is absent. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ allow_sudocmdgroup: test_sudorule - action: member - state: absent - register: result - failed_when: not result.changed - -- - name: Ensure sudorule sudocmds are absent, again -+ - name: Ensure sudorule is present, but allow_sudocmdgroup is absent. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 -- cmd: -- - /sbin/ifconfig -- - /usr/bin/vim -+ allow_sudocmdgroup: test_sudorule -+ action: member -+ state: absent -+ register: result -+ failed_when: result.changed -+ -+ - name: Ensure sudorule is present, with an deny_sudocmdgroup. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ deny_sudocmdgroup: test_sudorule -+ state: present -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure sudorule is present, with an deny_sudocmdgroup, again. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ deny_sudocmdgroup: test_sudorule -+ state: present -+ register: result -+ failed_when: result.changed -+ -+ - name: Ensure sudorule is present, but deny_sudocmdgroup is absent. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ deny_sudocmdgroup: test_sudorule -+ action: member -+ state: absent -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure sudorule is present, but deny_sudocmdgroup is absent, again. -+ ipasudorule: -+ ipaadmin_password: MyPassword123 -+ name: testrule1 -+ deny_sudocmdgroup: test_sudorule - action: member - state: absent - register: result -@@ -216,7 +315,7 @@ - - - name: Ensure sudorule is absent - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - state: absent - register: result -@@ -224,7 +323,7 @@ - - - name: Ensure sudorule is absent, again. - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: testrule1 - state: absent - register: result -@@ -232,7 +331,7 @@ - - - name: Ensure sudorule allhosts is absent - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allhosts - state: absent - register: result -@@ -240,7 +339,7 @@ - - - name: Ensure sudorule allhosts is absent, again - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allhosts - state: absent - register: result -@@ -248,7 +347,7 @@ - - - name: Ensure sudorule allusers is absent - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allusers - state: absent - register: result -@@ -256,7 +355,7 @@ - - - name: Ensure sudorule allusers is absent, again - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allusers - state: absent - register: result -@@ -264,7 +363,7 @@ - - - name: Ensure sudorule allcommands is absent - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allcommands - state: absent - register: result -@@ -272,8 +371,29 @@ - - - name: Ensure sudorule allcommands is absent, again - ipasudorule: -- ipaadmin_password: pass1234 -+ ipaadmin_password: MyPassword123 - name: allcommands - state: absent - register: result - failed_when: result.changed -+ -+ # cleanup -+ - name : Ensure sudocmdgroup is absent -+ ipasudocmdgroup: -+ ipaadmin_password: MyPassword123 -+ name: test_sudorule -+ state: absent -+ -+ - name: Ensure hostgroup is absent. -+ ipahostgroup: -+ ipaadmin_password: MyPassword123 -+ name: cluster -+ state: absent -+ -+ - name: Ensure sudocmds are absent -+ ipasudocmd: -+ ipaadmin_password: MyPassword123 -+ name: -+ - /sbin/ifconfig -+ - /usr/bin/vim -+ state: absent diff --git a/SOURCES/ansible-freeipa-0.1.8-ansible_freeipa_module-Fix-comparison-of-bool-parameters-in-compare_args_ipa_rhbz#1784514.patch b/SOURCES/ansible-freeipa-0.1.8-ansible_freeipa_module-Fix-comparison-of-bool-parameters-in-compare_args_ipa_rhbz#1784514.patch deleted file mode 100644 index 767f487..0000000 --- a/SOURCES/ansible-freeipa-0.1.8-ansible_freeipa_module-Fix-comparison-of-bool-parameters-in-compare_args_ipa_rhbz#1784514.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 3780a9a00e77ae0fd2944b36adad446d094fc90f Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Tue, 11 Feb 2020 10:34:39 +0100 -Subject: [PATCH] ansible_freeipa_module: Fix comparison of bool parameters in - compare_args_ipa - -Bool types are not iterable. Therefore the comparison using sets was failing -with a TypeError. This prevented to change the bool parameters for hosts. - -A test for the host module has been added to verify that the bool parameters -can be modified. - -New test: - - tests/host/test_host_bool_params.yml - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1784514 ---- - .../module_utils/ansible_freeipa_module.py | 18 ++- - tests/host/test_host_bool_params.yml | 119 ++++++++++++++++++ - 2 files changed, 133 insertions(+), 4 deletions(-) - create mode 100644 tests/host/test_host_bool_params.yml - -diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py -index 8154a12..9e97b88 100644 ---- a/plugins/module_utils/ansible_freeipa_module.py -+++ b/plugins/module_utils/ansible_freeipa_module.py -@@ -222,10 +222,20 @@ def compare_args_ipa(module, args, ipa): - arg = [to_text(_arg) for _arg in arg] - if isinstance(ipa_arg[0], unicode) and isinstance(arg[0], int): - arg = [to_text(_arg) for _arg in arg] -- # module.warn("%s <=> %s" % (arg, ipa_arg)) -- if set(arg) != set(ipa_arg): -- # module.warn("DIFFERENT") -- return False -+ # module.warn("%s <=> %s" % (repr(arg), repr(ipa_arg))) -+ try: -+ arg_set = set(arg) -+ ipa_arg_set = set(ipa_arg) -+ except TypeError: -+ if arg != ipa_arg: -+ # module.warn("%s != %s" % (repr(arg), repr(ipa_arg))) -+ return False -+ else: -+ if arg_set != ipa_arg_set: -+ # module.warn("%s != %s" % (repr(arg), repr(ipa_arg))) -+ return False -+ -+ # module.warn("%s == %s" % (repr(arg), repr(ipa_arg))) - - return True - -diff --git a/tests/host/test_host_bool_params.yml b/tests/host/test_host_bool_params.yml -new file mode 100644 -index 0000000..824ea99 ---- /dev/null -+++ b/tests/host/test_host_bool_params.yml -@@ -0,0 +1,119 @@ -+--- -+- name: Test host bool parameters -+ hosts: ipaserver -+ become: true -+ -+ tasks: -+ - name: Get Domain from server name -+ set_fact: -+ ipaserver_domain: "{{ groups.ipaserver[0].split('.')[1:] | join ('.') }}" -+ when: ipaserver_domain is not defined -+ -+ - name: Set host1_fqdn .. host6_fqdn -+ set_fact: -+ host1_fqdn: "{{ 'host1.' + ipaserver_domain }}" -+ -+ - name: Host absent -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: -+ - "{{ host1_fqdn }}" -+ update_dns: yes -+ state: absent -+ -+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ force: yes -+ requires_pre_auth: yes -+ ok_as_delegate: yes -+ ok_to_auth_as_delegate: yes -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ requires_pre_auth: yes -+ ok_as_delegate: yes -+ ok_to_auth_as_delegate: yes -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate set to no -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ requires_pre_auth: no -+ ok_as_delegate: no -+ ok_to_auth_as_delegate: no -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth, ok_as_delegate and ok_to_auth_as_delegate set to no again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ requires_pre_auth: no -+ ok_as_delegate: no -+ ok_to_auth_as_delegate: no -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ requires_pre_auth: yes -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present with requires_pre_auth again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ requires_pre_auth: yes -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present with ok_as_delegate -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ok_as_delegate: yes -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present with ok_as_delegate again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ok_as_delegate: yes -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present with ok_to_auth_as_delegate -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ok_to_auth_as_delegate: yes -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present with ok_to_auth_as_delegate again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ok_to_auth_as_delegate: yes -+ register: result -+ failed_when: result.changed -+ -+ - name: Host absent -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: -+ - "{{ host1_fqdn }}" -+ update_dns: yes -+ state: absent diff --git a/SOURCES/ansible-freeipa-0.1.8-ipahbacrule-Fix-handing-of-members-with-action-hbacrule_rhbz#1787996.patch b/SOURCES/ansible-freeipa-0.1.8-ipahbacrule-Fix-handing-of-members-with-action-hbacrule_rhbz#1787996.patch deleted file mode 100644 index 9e04d44..0000000 --- a/SOURCES/ansible-freeipa-0.1.8-ipahbacrule-Fix-handing-of-members-with-action-hbacrule_rhbz#1787996.patch +++ /dev/null @@ -1,838 +0,0 @@ -From 3865ce657e3ea1b621aa054c792201aedfde2d11 Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Fri, 7 Feb 2020 10:11:38 +0100 -Subject: [PATCH] ipahbacrule: Fix handing of members with action hbacrule - -Changing members (host, hostgroup, hbacsvc, hbacsvcgroup, user, group) with -action hbacrule was not working due to the use of the wrong parameter -prefix. This has been fixed and the old members are removed correctly now. - -The test script has been reworked completely to verify the fix. - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1787996 ---- - plugins/modules/ipahbacrule.py | 24 +- - tests/hbacrule/test_hbacrule.yml | 549 +++++++++++++++++++++++-------- - 2 files changed, 432 insertions(+), 141 deletions(-) - -diff --git a/plugins/modules/ipahbacrule.py b/plugins/modules/ipahbacrule.py -index 385876b..82340c2 100644 ---- a/plugins/modules/ipahbacrule.py -+++ b/plugins/modules/ipahbacrule.py -@@ -344,41 +344,41 @@ def main(): - # Generate addition and removal lists - host_add = list( - set(host or []) - -- set(res_find.get("member_host", []))) -+ set(res_find.get("memberhost_host", []))) - host_del = list( -- set(res_find.get("member_host", [])) - -+ set(res_find.get("memberhost_host", [])) - - set(host or [])) - hostgroup_add = list( - set(hostgroup or []) - -- set(res_find.get("member_hostgroup", []))) -+ set(res_find.get("memberhost_hostgroup", []))) - hostgroup_del = list( -- set(res_find.get("member_hostgroup", [])) - -+ set(res_find.get("memberhost_hostgroup", [])) - - set(hostgroup or [])) - - hbacsvc_add = list( - set(hbacsvc or []) - -- set(res_find.get("member_hbacsvc", []))) -+ set(res_find.get("memberservice_hbacsvc", []))) - hbacsvc_del = list( -- set(res_find.get("member_hbacsvc", [])) - -+ set(res_find.get("memberservice_hbacsvc", [])) - - set(hbacsvc or [])) - hbacsvcgroup_add = list( - set(hbacsvcgroup or []) - -- set(res_find.get("member_hbacsvcgroup", []))) -+ set(res_find.get("memberservice_hbacsvcgroup", []))) - hbacsvcgroup_del = list( -- set(res_find.get("member_hbacsvcgroup", [])) - -+ set(res_find.get("memberservice_hbacsvcgroup", [])) - - set(hbacsvcgroup or [])) - - user_add = list( - set(user or []) - -- set(res_find.get("member_user", []))) -+ set(res_find.get("memberuser_user", []))) - user_del = list( -- set(res_find.get("member_user", [])) - -+ set(res_find.get("memberuser_user", [])) - - set(user or [])) - group_add = list( - set(group or []) - -- set(res_find.get("member_group", []))) -+ set(res_find.get("memberuser_group", []))) - group_del = list( -- set(res_find.get("member_group", [])) - -+ set(res_find.get("memberuser_group", [])) - - set(group or [])) - - # Add hosts and hostgroups -diff --git a/tests/hbacrule/test_hbacrule.yml b/tests/hbacrule/test_hbacrule.yml -index a5615cc..38858d3 100644 ---- a/tests/hbacrule/test_hbacrule.yml -+++ b/tests/hbacrule/test_hbacrule.yml -@@ -1,338 +1,629 @@ - --- --- name: Tests -+- name: Playbook to handle hbacrules - hosts: ipaserver - become: true -- gather_facts: false - - tasks: -- - name: Ensure HBAC Rule allhosts is absent -- ipahbacrule: -+ - name: Get Domain from server name -+ set_fact: -+ ipaserver_domain: "{{ groups.ipaserver[0].split('.')[1:] | join ('.') }}" -+ when: ipaserver_domain is not defined -+ -+ # CLEANUP TEST ITEMS -+ -+ - name: Ensure test hosts are absent -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: -+ - "{{ 'testhost01.' + ipaserver_domain }}" -+ - "{{ 'testhost02.' + ipaserver_domain }}" -+ - "{{ 'testhost03.' + ipaserver_domain }}" -+ - "{{ 'testhost04.' + ipaserver_domain }}" -+ state: absent -+ -+ - name: Ensure test hostgroups are absent -+ ipahostgroup: - ipaadmin_password: MyPassword123 -- name: allhosts,sshd-pinky,loginRule -+ name: testhostgroup01,testhostgroup02,testhostgroup03,testhostgroup04 - state: absent - -- - name: User pinky absent -+ - name: Ensure test users are absent - ipauser: - ipaadmin_password: MyPassword123 -- name: pinky -+ name: testuser01,testuser02,testuser03,testuser04 - state: absent - -- - name: User group login absent -+ - name: Ensure test user groups are absent - ipagroup: - ipaadmin_password: MyPassword123 -- name: login -+ name: testgroup01,testgroup02,testgroup03,testgroup04 -+ state: absent -+ -+ - name: Ensure test HBAC Services are absent -+ ipahbacsvc: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvc01,testhbacsvc02,testhbacsvc03,testhbacsvc04 -+ state: absent -+ -+ - name: Ensure test HBAC Service Groups are absent -+ ipahbacsvcgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvcgroup01,testhbacsvcgroup02,testhbacsvcgroup03,testhbacsvcgroup04 - state: absent - -- - name: User pinky present -+ # CREATE TEST ITEMS -+ -+ - name: Ensure hosts "{{ 'host[1..4].' + ipaserver_domain }}" are present -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: "{{ 'testhost01.' + ipaserver_domain }}" -+ force: yes -+ - name: "{{ 'testhost02.' + ipaserver_domain }}" -+ force: yes -+ - name: "{{ 'testhost03.' + ipaserver_domain }}" -+ force: yes -+ - name: "{{ 'testhost04.' + ipaserver_domain }}" -+ force: yes -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure host-group testhostgroup01 is present -+ ipahostgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhostgroup01 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure host-group testhostgroup02 is present -+ ipahostgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhostgroup02 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure host-group testhostgroup03 is present -+ ipahostgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhostgroup03 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure host-group testhostgroup04 is present -+ ipahostgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhostgroup04 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure testusers are present - ipauser: - ipaadmin_password: MyPassword123 -- name: pinky -- uid: 10001 -- gid: 100 -- phone: "+555123457" -- email: pinky@acme.com -- principalexpiration: "20220119235959" -- #passwordexpiration: "2022-01-19 23:59:59" -- first: pinky -- last: Acme -+ users: -+ - name: testuser01 -+ first: test -+ last: user01 -+ - name: testuser02 -+ first: test -+ last: user02 -+ - name: testuser03 -+ first: test -+ last: user03 -+ - name: testuser04 -+ first: test -+ last: user04 - register: result - failed_when: not result.changed - -- - name: User group login present -+ - name: Ensure user group testgroup01 is present - ipagroup: - ipaadmin_password: MyPassword123 -- name: login -+ name: testgroup01 - register: result - failed_when: not result.changed - -- - name: Ensure HBAC Rule allhosts is present -- ipahbacrule: -+ - name: Ensure user group testgroup02 is present -+ ipagroup: - ipaadmin_password: MyPassword123 -- name: allhosts -- usercategory: all -+ name: testgroup02 - register: result - failed_when: not result.changed - -- - name: Ensure HBAC Rule allhosts is present again -- ipahbacrule: -+ - name: Ensure user group testgroup03 is present -+ ipagroup: - ipaadmin_password: MyPassword123 -- name: allhosts -- usercategory: all -+ name: testgroup03 - register: result -- failed_when: result.changed -+ failed_when: not result.changed - -- - name: Ensure host "{{ groups.ipaserver[0] }}" is present in HBAC Rule allhosts -+ - name: Ensure user group testgroup04 is present -+ ipagroup: -+ ipaadmin_password: MyPassword123 -+ name: testgroup04 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure HBAC Service testhbacsvc01 is present -+ ipahbacsvc: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvc01 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure HBAC Service testhbacsvc02 is present -+ ipahbacsvc: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvc02 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure HBAC Service testhbacsvc03 is present -+ ipahbacsvc: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvc03 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure HBAC Service testhbacsvc04 is present -+ ipahbacsvc: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvc04 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure HBAC Service Group testhbacsvcgroup01 is present -+ ipahbacsvcgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvcgroup01 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure HBAC Service Group testhbacsvcgroup02 is present -+ ipahbacsvcgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvcgroup02 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure HBAC Service Group testhbacsvcgroup03 is present -+ ipahbacsvcgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvcgroup03 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure HBAC Service Group testhbacsvcgroup04 is present -+ ipahbacsvcgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvcgroup04 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure test HBAC rule hbacrule01 is absent - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: allhosts -- host: "{{ groups.ipaserver[0] }}" -- action: member -+ name: hbacrule01 -+ state: absent -+ -+ # ENSURE HBACRULE -+ -+ - name: Ensure HBAC rule hbacrule01 is present -+ ipahbacrule: -+ ipaadmin_password: MyPassword123 -+ name: hbacrule01 - register: result - failed_when: not result.changed - -- - name: Ensure host "{{ groups.ipaserver[0] }}" is present in HBAC Rule allhosts again -+ - name: Ensure HBAC rule hbacrule01 is present again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: allhosts -- host: "{{ groups.ipaserver[0] }}" -- action: member -+ name: hbacrule01 - register: result - failed_when: result.changed - -- - name: Ensure HBAC Rule sshd-pinky is present -+ # CHANGE HBACRULE WITH ALL MEMBERS -+ -+ - name: Ensure HBAC rule hbacrule01 is present with hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- hostcategory: all -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost01.' + ipaserver_domain }}" -+ - "{{ 'testhost02.' + ipaserver_domain }}" -+ hostgroup: testhostgroup01,testhostgroup02 -+ user: testuser01,testuser02 -+ group: testgroup01,testgroup02 -+ hbacsvc: testhbacsvc01,testhbacsvc02 -+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 - register: result - failed_when: not result.changed - -- - name: Ensure HBAC Rule sshd-pinky is present again -+ - name: Ensure HBAC rule hbacrule01 is present with hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- hostcategory: all -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost01.' + ipaserver_domain }}" -+ - "{{ 'testhost02.' + ipaserver_domain }}" -+ hostgroup: testhostgroup01,testhostgroup02 -+ user: testuser01,testuser02 -+ group: testgroup01,testgroup02 -+ hbacsvc: testhbacsvc01,testhbacsvc02 -+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 - register: result - failed_when: result.changed - -- - name: Ensure user pinky is present in HBAC Rule sshd-pinky -+ # REMOVE MEMBERS ONE BY ONE -+ -+ - name: Ensure test HBAC rule hbacrule01 host members are absent - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- user: pinky -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost01.' + ipaserver_domain }}" -+ - "{{ 'testhost02.' + ipaserver_domain }}" -+ state: absent - action: member - register: result - failed_when: not result.changed - -- - name: Ensure user pinky is present in HBAC Rule sshd-pinky again -+ - name: Ensure test HBAC rule hbacrule01 host members are absent again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- user: pinky -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost01.' + ipaserver_domain }}" -+ - "{{ 'testhost02.' + ipaserver_domain }}" -+ state: absent - action: member - register: result - failed_when: result.changed - -- - name: Ensure HBAC service sshd is present in HBAC Rule sshd-pinky -+ - name: Ensure test HBAC rule hbacrule01 hostgroup members are absent - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- hbacsvc: sshd -+ name: hbacrule01 -+ hostgroup: testhostgroup01,testhostgroup02 -+ state: absent - action: member - register: result - failed_when: not result.changed - -- - name: Ensure HBAC service sshd is present in HBAC Rule sshd-pinky again -+ - name: Ensure test HBAC rule hbacrule01 hostgroup members are absent again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- hbacsvc: sshd -+ name: hbacrule01 -+ hostgroup: testhostgroup01,testhostgroup02 -+ state: absent - action: member - register: result - failed_when: result.changed - -- - name: Ensure HBAC Rule loginRule is present with HBAC service sshd -+ - name: Ensure test HBAC rule hbacrule01 user members are absent - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: loginRule -- group: login -+ name: hbacrule01 -+ user: testuser01,testuser02 -+ state: absent -+ action: member - register: result - failed_when: not result.changed - -- - name: Ensure HBAC Rule loginRule is present with HBAC service sshd again -+ - name: Ensure test HBAC rule hbacrule01 user members are absent again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: loginRule -- group: login -+ name: hbacrule01 -+ user: testuser01,testuser02 -+ state: absent -+ action: member - register: result - failed_when: result.changed - -- - name: Ensure user pinky is present in HBAC Rule loginRule -+ - name: Ensure test HBAC rule hbacrule01 user group members are absent - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: loginRule -- user: pinky -+ name: hbacrule01 -+ group: testgroup01,testgroup02 -+ state: absent - action: member - register: result - failed_when: not result.changed - -- - name: Ensure user pinky is present in HBAC Rule loginRule again -+ - name: Ensure test HBAC rule hbacrule01 user group members are absent again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: loginRule -- user: pinky -+ name: hbacrule01 -+ group: testgroup01,testgroup02 -+ state: absent - action: member - register: result - failed_when: result.changed - -- - name: Ensure user pinky is absent in HBAC Rule loginRule -+ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are absent - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: loginRule -- user: pinky -- action: member -+ name: hbacrule01 -+ hbacsvc: testhbacsvc01,testhbacsvc02 - state: absent -+ action: member - register: result - failed_when: not result.changed - -- - name: Ensure user pinky is absent in HBAC Rule loginRule again -+ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are absent again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: loginRule -- user: pinky -- action: member -+ name: hbacrule01 -+ hbacsvc: testhbacsvc01,testhbacsvc02 - state: absent -+ action: member - register: result - failed_when: result.changed - -- - name: Ensure HBAC Rule loginRule is absent -+ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are absent - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: loginRule -+ name: hbacrule01 -+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 - state: absent -+ action: member - register: result - failed_when: not result.changed - -- - name: Ensure HBAC Rule loginRule is absent again -+ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are absent again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: loginRule -+ name: hbacrule01 -+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 - state: absent -+ action: member - register: result - failed_when: result.changed - -- - name: Ensure HBAC service sshd is absent in HBAC Rule sshd-pinky -+ # ADD MEMBERS BACK -+ -+ - name: Ensure test HBAC rule hbacrule01 host members are present - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- hbacsvc: sshd -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost01.' + ipaserver_domain }}" -+ - "{{ 'testhost02.' + ipaserver_domain }}" - action: member -- state: absent - register: result - failed_when: not result.changed - -- - name: Ensure HBAC service sshd is absent in HBAC Rule sshd-pinky again -+ - name: Ensure test HBAC rule hbacrule01 host members are present again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- hbacsvc: sshd -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost01.' + ipaserver_domain }}" -+ - "{{ 'testhost02.' + ipaserver_domain }}" - action: member -- state: absent - register: result - failed_when: result.changed - -- - name: Ensure user pinky is absent in HBAC Rule sshd-pinky -+ - name: Ensure test HBAC rule hbacrule01 hostgroup members are present - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- user: pinky -+ name: hbacrule01 -+ hostgroup: testhostgroup01,testhostgroup02 - action: member -- state: absent - register: result - failed_when: not result.changed - -- - name: Ensure user pinky is absent in HBAC Rule sshd-pinky again -+ - name: Ensure test HBAC rule hbacrule01 hostgroup members are present again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- user: pinky -+ name: hbacrule01 -+ hostgroup: testhostgroup01,testhostgroup02 - action: member -- state: absent - register: result - failed_when: result.changed - -- - name: Ensure HBAC Rule sshd-pinky is disabled -+ - name: Ensure test HBAC rule hbacrule01 user members are present - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- state: disabled -+ name: hbacrule01 -+ user: testuser01,testuser02 -+ action: member - register: result - failed_when: not result.changed - -- - name: Ensure HBAC Rule sshd-pinky is disabled again -+ - name: Ensure test HBAC rule hbacrule01 user members are present again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- state: disabled -+ name: hbacrule01 -+ user: testuser01,testuser02 -+ action: member - register: result - failed_when: result.changed - -- - name: Ensure HBAC Rule sshd-pinky is enabled -+ - name: Ensure test HBAC rule hbacrule01 user group members are present - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- state: enabled -+ name: hbacrule01 -+ group: testgroup01,testgroup02 -+ action: member - register: result - failed_when: not result.changed - -- - name: Ensure HBAC Rule sshd-pinky is enabled again -+ - name: Ensure test HBAC rule hbacrule01 user group members are present again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- state: enabled -+ name: hbacrule01 -+ group: testgroup01,testgroup02 -+ action: member - register: result - failed_when: result.changed - -- - name: Ensure HBAC Rule sshd-pinky is absent -+ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are present - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- state: absent -+ name: hbacrule01 -+ hbacsvc: testhbacsvc01,testhbacsvc02 -+ action: member - register: result - failed_when: not result.changed - -- - name: Ensure HBAC Rule sshd-pinky is absent again -+ - name: Ensure test HBAC rule hbacrule01 hbacsvc members are present again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: sshd-pinky -- state: absent -+ name: hbacrule01 -+ hbacsvc: testhbacsvc01,testhbacsvc02 -+ action: member - register: result - failed_when: result.changed - -- - name: Ensure host "{{ groups.ipaserver[0] }}" is absent in HBAC Rule allhosts -+ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are present - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: allhosts -- host: "{{ groups.ipaserver[0] }}" -+ name: hbacrule01 -+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 - action: member -- state: absent - register: result - failed_when: not result.changed - -- - name: Ensure host "{{ groups.ipaserver[0] }}" is absent in HBAC Rule allhosts again -+ - name: Ensure test HBAC rule hbacrule01 hbacsvcgroup members are present again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: allhosts -- host: "{{ groups.ipaserver[0] }}" -+ name: hbacrule01 -+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 - action: member -+ register: result -+ failed_when: result.changed -+ -+ # CHANGE TO DIFFERENT MEMBERS -+ -+ - name: Ensure HBAC rule hbacrule01 is present with different hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups -+ ipahbacrule: -+ ipaadmin_password: MyPassword123 -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost03.' + ipaserver_domain }}" -+ - "{{ 'testhost04.' + ipaserver_domain }}" -+ hostgroup: testhostgroup03,testhostgroup04 -+ user: testuser03,testuser04 -+ group: testgroup03,testgroup04 -+ hbacsvc: testhbacsvc03,testhbacsvc04 -+ hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure HBAC rule hbacrule01 is present with different hosts, hostgroups, users, groups, hbassvcs and hbacsvcgroups again -+ ipahbacrule: -+ ipaadmin_password: MyPassword123 -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost03.' + ipaserver_domain }}" -+ - "{{ 'testhost04.' + ipaserver_domain }}" -+ hostgroup: testhostgroup03,testhostgroup04 -+ user: testuser03,testuser04 -+ group: testgroup03,testgroup04 -+ hbacsvc: testhbacsvc03,testhbacsvc04 -+ hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04 -+ register: result -+ failed_when: result.changed -+ -+ # ENSURE OLD TEST MEMBERS ARE ABSENT -+ -+ - name: Ensure HBAC rule hbacrule01 members (same) are present -+ ipahbacrule: -+ ipaadmin_password: MyPassword123 -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost01.' + ipaserver_domain }}" -+ - "{{ 'testhost02.' + ipaserver_domain }}" -+ hostgroup: testhostgroup01,testhostgroup02 -+ user: testuser01,testuser02 -+ group: testgroup01,testgroup02 -+ hbacsvc: testhbacsvc01,testhbacsvc02 -+ hbacsvcgroup: testhbacsvcgroup01,testhbacsvcgroup02 - state: absent -+ action: member - register: result - failed_when: result.changed - -- - name: Ensure HBAC Rule allhosts is absent -+ # ENSURE NEW TEST MEMBERS ARE ABSENT -+ -+ - name: Ensure HBAC rule hbacrule01 members are absent - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: allhosts -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost03.' + ipaserver_domain }}" -+ - "{{ 'testhost04.' + ipaserver_domain }}" -+ hostgroup: testhostgroup03,testhostgroup04 -+ user: testuser03,testuser04 -+ group: testgroup03,testgroup04 -+ hbacsvc: testhbacsvc03,testhbacsvc04 -+ hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04 - state: absent -+ action: member - register: result - failed_when: not result.changed - -- - name: Ensure HBAC Rule allhosts is absent again -+ - name: Ensure HBAC rule hbacrule01 members are absent again - ipahbacrule: - ipaadmin_password: MyPassword123 -- name: allhosts -+ name: hbacrule01 -+ host: -+ - "{{ 'testhost03.' + ipaserver_domain }}" -+ - "{{ 'testhost04.' + ipaserver_domain }}" -+ hostgroup: testhostgroup03,testhostgroup04 -+ user: testuser03,testuser04 -+ group: testgroup03,testgroup04 -+ hbacsvc: testhbacsvc03,testhbacsvc04 -+ hbacsvcgroup: testhbacsvcgroup03,testhbacsvcgroup04 - state: absent -+ action: member - register: result - failed_when: result.changed - -- - name: User pinky absent -+ # CLEANUP TEST ITEMS -+ -+ - name: Ensure test HBAC rule hbacrule01 is absent -+ ipahbacrule: -+ ipaadmin_password: MyPassword123 -+ name: hbacrule01 -+ state: absent -+ -+ - name: Ensure test hosts are absent -+ ipahostgroup: -+ ipaadmin_password: MyPassword123 -+ name: -+ - "{{ 'testhost01.' + ipaserver_domain }}" -+ - "{{ 'testhost02.' + ipaserver_domain }}" -+ - "{{ 'testhost03.' + ipaserver_domain }}" -+ - "{{ 'testhost04.' + ipaserver_domain }}" -+ state: absent -+ -+ - name: Ensure test hostgroups are absent -+ ipahostgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhostgroup01,testhostgroup02,testhostgroup03,testhostgroup04 -+ state: absent -+ -+ - name: Ensure test users are absent - ipauser: - ipaadmin_password: MyPassword123 -- name: pinky -+ name: testuser01,testuser02,testuser03,testuser04 - state: absent - -- - name: User group login absent -+ - name: Ensure test user groups are absent - ipagroup: - ipaadmin_password: MyPassword123 -- name: login -+ name: testgroup01,testgroup02,testgroup03,testgroup04 -+ state: absent -+ -+ - name: Ensure test HBAC Services are absent -+ ipahbacsvc: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvc01,testhbacsvc02,testhbacsvc03,testhbacsvc04 -+ state: absent -+ -+ - name: Ensure test HBAC Service Groups are absent -+ ipahbacsvcgroup: -+ ipaadmin_password: MyPassword123 -+ name: testhbacsvcgroup01,testhbacsvcgroup02,testhbacsvcgroup03,testhbacsvcgroup04 - state: absent diff --git a/SOURCES/ansible-freeipa-0.1.8-ipahost-Do-not-fail-on-missing-DNS-or-zone-when-no-IP-address-given_rhbz#1804838.patch b/SOURCES/ansible-freeipa-0.1.8-ipahost-Do-not-fail-on-missing-DNS-or-zone-when-no-IP-address-given_rhbz#1804838.patch deleted file mode 100644 index 512a213..0000000 --- a/SOURCES/ansible-freeipa-0.1.8-ipahost-Do-not-fail-on-missing-DNS-or-zone-when-no-IP-address-given_rhbz#1804838.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 22d8784da29dcfede0744ef6b691b4506eae5deb Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Thu, 20 Feb 2020 12:58:11 +0100 -Subject: [PATCH] ipahost: Do not fail on missing DNS or zone when no IP - address given - -If no IP address is given and either DNS is not configured or if the zone is -not found then ipahost may not fail in dnsrecord_find. - -The error happened for example by ensuring the absence of a host that is not -part of the domain or for a host that has been added with force and is using -a domain that is not served by the DNS server in the domain. It also -happened if there was no DNS server in the domain at all. - -A new test case has been added to test_host_ipaddresses.yml - -The fix requires ipalib_errors provided by ansible_freeipa_module. - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1804838 ---- - plugins/modules/ipahost.py | 17 +++++++++++++++-- - tests/host/test_host_ipaddresses.yml | 9 +++++++++ - 2 files changed, 24 insertions(+), 2 deletions(-) - -diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py -index 558560e..062f768 100644 ---- a/plugins/modules/ipahost.py -+++ b/plugins/modules/ipahost.py -@@ -409,7 +409,7 @@ - from ansible.module_utils.ansible_freeipa_module import temp_kinit, \ - temp_kdestroy, valid_creds, api_connect, api_command, compare_args_ipa, \ - module_params_get, gen_add_del_lists, encode_certificate, api_get_realm, \ -- is_ipv4_addr, is_ipv6_addr -+ is_ipv4_addr, is_ipv6_addr, ipalib_errors - import six - - -@@ -871,7 +871,20 @@ def main(): - - # Make sure host exists - res_find = find_host(ansible_module, name) -- res_find_dnsrecord = find_dnsrecord(ansible_module, name) -+ try: -+ res_find_dnsrecord = find_dnsrecord(ansible_module, name) -+ except ipalib_errors.NotFound as e: -+ msg = str(e) -+ if ip_address is None and \ -+ ("DNS is not configured" in msg or \ -+ "DNS zone not found" in msg): -+ # IP address(es) not given and no DNS support in IPA -+ # -> Ignore failure -+ # IP address(es) not given and DNS zone is not found -+ # -> Ignore failure -+ res_find_dnsrecord = None -+ else: -+ ansible_module.fail_json(msg="%s: %s" % (host, msg)) - - # Create command - if state == "present": -diff --git a/tests/host/test_host_ipaddresses.yml b/tests/host/test_host_ipaddresses.yml -index 0a97dd5..136a610 100644 ---- a/tests/host/test_host_ipaddresses.yml -+++ b/tests/host/test_host_ipaddresses.yml -@@ -301,6 +301,15 @@ - register: result - failed_when: result.changed - -+ - name: Absent host01.ihavenodns.info test -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: host01.ihavenodns.info -+ state: absent -+ register: result -+ failed_when: result.changed -+ - - name: Host absent - ipahost: - ipaadmin_password: MyPassword123 -From 4d94cb09a9fb09dd2576223b9be7f77d515202fb Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Thu, 20 Feb 2020 12:54:32 +0100 -Subject: [PATCH] ansible_freeipa_module: Import ipalib.errors as ipalib_errors - -For beeing able to catch ipalib.errors.NotFound errors in ipahost it is -needed to import ipalib.errors. ipalib.errors is now imported as -ipalib_errors to not have name conflicts with the errors list used in some -of the modules. - -Related: https://bugzilla.redhat.com/show_bug.cgi?id=1804838 ---- - plugins/module_utils/ansible_freeipa_module.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py -index 6acdbef..5066de3 100644 ---- a/plugins/module_utils/ansible_freeipa_module.py -+++ b/plugins/module_utils/ansible_freeipa_module.py -@@ -28,6 +28,7 @@ - import gssapi - from datetime import datetime - from ipalib import api -+from ipalib import errors as ipalib_errors - from ipalib.config import Env - from ipalib.constants import DEFAULT_CONFIG, LDAP_GENERALIZED_TIME_FORMAT - try: diff --git a/SOURCES/ansible-freeipa-0.1.8-ipahost-Enhanced-failure-msg-for-member-params-used-without-member-action_rhbz#1783948.patch b/SOURCES/ansible-freeipa-0.1.8-ipahost-Enhanced-failure-msg-for-member-params-used-without-member-action_rhbz#1783948.patch deleted file mode 100644 index aea3a62..0000000 --- a/SOURCES/ansible-freeipa-0.1.8-ipahost-Enhanced-failure-msg-for-member-params-used-without-member-action_rhbz#1783948.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 24515e40ad289552d45bddd33c7a0dda93117a7f Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Wed, 18 Dec 2019 12:28:03 +0100 -Subject: [PATCH] ipahost: Enhanced failure msg for member params used without - member action - -The failure message if member parameters like certificate, managedby_host, -principal, allow_create_keytab_* and allow_retrieve_keytab_* are used -without member action for state absent has been enhanced to propose the -member action. ---- - plugins/modules/ipahost.py | 20 +++++++++++++------- - 1 file changed, 13 insertions(+), 7 deletions(-) - -diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py -index ec5e196..8ee9532 100644 ---- a/plugins/modules/ipahost.py -+++ b/plugins/modules/ipahost.py -@@ -511,19 +511,25 @@ def check_parameters( - "userclass", "auth_ind", "requires_pre_auth", - "ok_as_delegate", "ok_to_auth_as_delegate", "force", - "reverse", "ip_address", "update_password"] -+ for x in invalid: -+ if vars()[x] is not None: -+ module.fail_json( -+ msg="Argument '%s' can not be used with state '%s'" % -+ (x, state)) - if action == "host": -- invalid.extend([ -+ invalid = [ - "certificate", "managedby_host", "principal", - "allow_create_keytab_user", "allow_create_keytab_group", - "allow_create_keytab_host", "allow_create_keytab_hostgroup", - "allow_retrieve_keytab_user", "allow_retrieve_keytab_group", - "allow_retrieve_keytab_host", -- "allow_retrieve_keytab_hostgroup"]) -- for x in invalid: -- if vars()[x] is not None: -- module.fail_json( -- msg="Argument '%s' can not be used with state '%s'" % -- (x, state)) -+ "allow_retrieve_keytab_hostgroup" -+ ] -+ for x in invalid: -+ if vars()[x] is not None: -+ module.fail_json( -+ msg="Argument '%s' can only be used with action " -+ "'member' for state '%s'" % (x, state)) - - - def main(): diff --git a/SOURCES/ansible-freeipa-0.1.8-ipahost-Fail-on-action-member-for-new-hosts-fix-dnsrecord_add-reverse-flag_rhbz#1803026.patch b/SOURCES/ansible-freeipa-0.1.8-ipahost-Fail-on-action-member-for-new-hosts-fix-dnsrecord_add-reverse-flag_rhbz#1803026.patch deleted file mode 100644 index fa2dadd..0000000 --- a/SOURCES/ansible-freeipa-0.1.8-ipahost-Fail-on-action-member-for-new-hosts-fix-dnsrecord_add-reverse-flag_rhbz#1803026.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 0816b0773b1535780c7c3e5f05bda39434ab6bac Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Fri, 14 Feb 2020 13:21:54 +0100 -Subject: [PATCH] ipahost: Fail on action member for new hosts, fix - dnsrecord_add reverse flag - -The check to make sure that member can not be used on non existing hosts -has bee missing. Also the reverse flag for the dnsrecord_add call was None -if the varaible was not set. - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1803026 ---- - plugins/modules/ipahost.py | 23 +++++++++++++++-------- - 1 file changed, 15 insertions(+), 8 deletions(-) - -diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py -index a5fd482..558560e 100644 ---- a/plugins/modules/ipahost.py -+++ b/plugins/modules/ipahost.py -@@ -1005,6 +1005,11 @@ def main(): - dnsrecord_args.get("aaaarecord"), - _dnsrec.get("aaaarecord")) - -+ else: -+ if res_find is None: -+ ansible_module.fail_json( -+ msg="No host '%s'" % name) -+ - if action != "host" or (action == "host" and res_find is None): - certificate_add = certificate or [] - certificate_del = [] -@@ -1178,15 +1183,17 @@ def main(): - domain_name = name[name.find(".")+1:] - host_name = name[:name.find(".")] - -+ _args = {"idnsname": host_name} -+ if reverse is not None: -+ _args["a_extra_create_reverse"] = reverse -+ _args["aaaa_extra_create_reverse"] = reverse -+ if len(dnsrecord_a_add) > 0: -+ _args["arecord"] = dnsrecord_a_add -+ if len(dnsrecord_aaaa_add) > 0: -+ _args["aaaarecord"] = dnsrecord_aaaa_add -+ - commands.append([domain_name, -- "dnsrecord_add", -- { -- "idnsname": host_name, -- "arecord": dnsrecord_a_add, -- "a_extra_create_reverse": reverse, -- "aaaarecord": dnsrecord_aaaa_add, -- "aaaa_extra_create_reverse": reverse -- }]) -+ "dnsrecord_add", _args]) - - if len(dnsrecord_a_del) > 0 or len(dnsrecord_aaaa_del) > 0: - domain_name = name[name.find(".")+1:] diff --git a/SOURCES/ansible-freeipa-0.1.8-ipahost-Fix-choices-of-auth_ind-parameter-allow-to-reset-parameter_rhbz#1783992.patch b/SOURCES/ansible-freeipa-0.1.8-ipahost-Fix-choices-of-auth_ind-parameter-allow-to-reset-parameter_rhbz#1783992.patch deleted file mode 100644 index 592da6e..0000000 --- a/SOURCES/ansible-freeipa-0.1.8-ipahost-Fix-choices-of-auth_ind-parameter-allow-to-reset-parameter_rhbz#1783992.patch +++ /dev/null @@ -1,78 +0,0 @@ -From b6100f0c19e2caf73ab70bbc572d3e47e6066b48 Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Tue, 17 Dec 2019 14:04:43 +0100 -Subject: [PATCH] ipahost: Fix choices of auth_ind parameter, allow to reset - parameter - -The choices for the auth_ind parameter have been wrong. The choices are now -['radius', 'otp', 'pkinit', 'hardened', '']. The empty string has been added -to be able to rest auth_ind for the host entry. ---- - README-host.md | 2 +- - plugins/modules/ipahost.py | 15 ++++++++++++--- - 2 files changed, 13 insertions(+), 4 deletions(-) - -diff --git a/README-host.md b/README-host.md -index edec8d9..be5ad79 100644 ---- a/README-host.md -+++ b/README-host.md -@@ -280,7 +280,7 @@ Variable | Description | Required - `mac_address` \| `macaddress` | List of hardware MAC addresses. | no - `sshpubkey` \| `ipasshpubkey` | List of SSH public keys | no - `userclass` \| `class` | Host category (semantics placed on this attribute are for local interpretation) | no --`auth_ind` \| `krbprincipalauthind` | Defines a whitelist for Authentication Indicators. Use 'otp' to allow OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA authentications. Other values may be used for custom configurations. choices: ["radius", "otp", "pkinit", "hardened"] | no -+`auth_ind` \| `krbprincipalauthind` | Defines a whitelist for Authentication Indicators. Use 'otp' to allow OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA authentications. Use empty string to reset auth_ind to the initial value. Other values may be used for custom configurations. choices: ["radius", "otp", "pkinit", "hardened", ""] | no - `requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service (bool) | no - `ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service (bool) | no - `ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client (bool) | no -diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py -index ec5e196..b130395 100644 ---- a/plugins/modules/ipahost.py -+++ b/plugins/modules/ipahost.py -@@ -147,9 +147,10 @@ - Defines a whitelist for Authentication Indicators. Use 'otp' to allow - OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA - authentications. Other values may be used for custom configurations. -+ Use empty string to reset auth_ind to the initial value. - type: list - aliases: ["krbprincipalauthind"] -- choices: ["radius", "otp", "pkinit", "hardened"] -+ choices: ["radius", "otp", "pkinit", "hardened", ""] - required: false - requires_pre_auth: - description: Pre-authentication is required for the service -@@ -277,9 +278,10 @@ - Defines a whitelist for Authentication Indicators. Use 'otp' to allow - OTP-based 2FA authentications. Use 'radius' to allow RADIUS-based 2FA - authentications. Other values may be used for custom configurations. -+ Use empty string to reset auth_ind to the initial value. - type: list - aliases: ["krbprincipalauthind"] -- choices: ["radius", "otp", "pkinit", "hardened"] -+ choices: ["radius", "otp", "pkinit", "hardened", ""] - required: false - requires_pre_auth: - description: Pre-authentication is required for the service -@@ -590,7 +592,7 @@ def main(): - default=None), - auth_ind=dict(type='list', aliases=["krbprincipalauthind"], - default=None, -- choices=['password', 'radius', 'otp']), -+ choices=['radius', 'otp', 'pkinit', 'hardened', '']), - requires_pre_auth=dict(type="bool", aliases=["ipakrbrequirespreauth"], - default=None), - ok_as_delegate=dict(type="bool", aliases=["ipakrbokasdelegate"], -@@ -835,6 +837,13 @@ def main(): - if x in args: - del args[x] - -+ # Ignore auth_ind if it is empty (for resetting) -+ # and not set in for the host -+ if "krbprincipalauthind" not in res_find and \ -+ "krbprincipalauthind" in args and \ -+ args["krbprincipalauthind"] == ['']: -+ del args["krbprincipalauthind"] -+ - # For all settings is args, check if there are - # different settings in the find result. - # If yes: modify diff --git a/SOURCES/ansible-freeipa-0.1.8-ipapwpolicy-Use-global_policy-if-name-is-not-set_rhbz#1797532.patch b/SOURCES/ansible-freeipa-0.1.8-ipapwpolicy-Use-global_policy-if-name-is-not-set_rhbz#1797532.patch deleted file mode 100644 index bde4624..0000000 --- a/SOURCES/ansible-freeipa-0.1.8-ipapwpolicy-Use-global_policy-if-name-is-not-set_rhbz#1797532.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 4dd1d25eacd1481be0a881a017144ff4d3396ccd Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Thu, 6 Feb 2020 15:38:00 +0100 -Subject: [PATCH] ipapwpolicy: Use global_policy if name is not set - -If the name is not set, the policy global_policy is now used. It was needed -before to explicitly name the global_policy. Also a check has been added -to fail early if global_policy is used with state absent. - -The README for pwpolicy has been extended with an example for global_policy -and also the description of the name variable. - -The test has also been extended to check a change of maxlife for -global_policy and that global_policy can not be used with state: absent - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1797532 ---- - README-pwpolicy.md | 19 +++++++++++-- - plugins/modules/ipapwpolicy.py | 9 ++++-- - tests/pwpolicy/test_pwpolicy.yml | 49 ++++++++++++++++++++++++++++++++ - 3 files changed, 73 insertions(+), 4 deletions(-) - -diff --git a/README-pwpolicy.md b/README-pwpolicy.md -index 16306b7..847b32d 100644 ---- a/README-pwpolicy.md -+++ b/README-pwpolicy.md -@@ -56,7 +56,7 @@ Example playbook to ensure presence of pwpolicies for exisiting group ops: - maxfail: 3 - ``` - --Example playbook to ensure absence of pwpolicies for group ops -+Example playbook to ensure absence of pwpolicies for group ops: - - ```yaml - --- -@@ -72,6 +72,21 @@ Example playbook to ensure absence of pwpolicies for group ops - state: absent - ``` - -+Example playbook to ensure maxlife is set to 49 in global policy: -+ -+```yaml -+--- -+- name: Playbook to handle pwpolicies -+ hosts: ipaserver -+ become: true -+ -+ tasks: -+ # Ensure absence of pwpolicies for group ops -+ - ipapwpolicy: -+ ipaadmin_password: MyPassword123 -+ maxlife: 49 -+``` -+ - - Variables - ========= -@@ -83,7 +98,7 @@ 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 --`name` \| `cn` | The list of pwpolicy name strings. | no -+`name` \| `cn` | The list of pwpolicy name strings. If name is not given, `global_policy` will be used automatically. | no - `maxlife` \| `krbmaxpwdlife` | Maximum password lifetime in days. (int) | no - `minlife` \| `krbminpwdlife` | Minimum password lifetime in hours. (int) | no - `history` \| `krbpwdhistorylength` | Password history size. (int) | no -diff --git a/plugins/modules/ipapwpolicy.py b/plugins/modules/ipapwpolicy.py -index 9437b59..f168703 100644 ---- a/plugins/modules/ipapwpolicy.py -+++ b/plugins/modules/ipapwpolicy.py -@@ -167,7 +167,7 @@ def main(): - ipaadmin_password=dict(type="str", required=False, no_log=True), - - name=dict(type="list", aliases=["cn"], default=None, -- required=True), -+ required=False), - # present - - maxlife=dict(type="int", aliases=["krbmaxpwdlife"], default=None), -@@ -218,6 +218,9 @@ def main(): - - # Check parameters - -+ if names is None: -+ names = ["global_policy"] -+ - if state == "present": - if len(names) != 1: - ansible_module.fail_json( -@@ -225,8 +228,10 @@ def main(): - - if state == "absent": - if len(names) < 1: -+ ansible_module.fail_json(msg="No name given.") -+ if "global_policy" in names: - ansible_module.fail_json( -- msg="No name given.") -+ msg="'global_policy' can not be made absent.") - invalid = ["maxlife", "minlife", "history", "minclasses", - "minlength", "priority", "maxfail", "failinterval", - "lockouttime"] -diff --git a/tests/pwpolicy/test_pwpolicy.yml b/tests/pwpolicy/test_pwpolicy.yml -index 5c69345..f93f275 100644 ---- a/tests/pwpolicy/test_pwpolicy.yml -+++ b/tests/pwpolicy/test_pwpolicy.yml -@@ -5,10 +5,30 @@ - gather_facts: false - - tasks: -+ - name: Ensure maxlife of 90 for global_policy -+ ipapwpolicy: -+ ipaadmin_password: SomeADMINpassword -+ maxlife: 90 -+ -+ - name: Ensure absence of group ops -+ ipagroup: -+ ipaadmin_password: SomeADMINpassword -+ name: ops -+ state: absent -+ -+ - name: Ensure absence of pwpolicies for group ops -+ ipapwpolicy: -+ ipaadmin_password: SomeADMINpassword -+ name: ops -+ state: absent -+ - - name: Ensure presence of group ops - ipagroup: - ipaadmin_password: SomeADMINpassword - name: ops -+ state: present -+ register: result -+ failed_when: not result.changed - - - name: Ensure presence of pwpolicies for group ops - ipapwpolicy: -@@ -42,6 +62,28 @@ - register: result - failed_when: result.changed - -+ - name: Ensure maxlife of 49 for global_policy -+ ipapwpolicy: -+ ipaadmin_password: SomeADMINpassword -+ maxlife: 49 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Ensure maxlife of 49 for global_policy again -+ ipapwpolicy: -+ ipaadmin_password: SomeADMINpassword -+ maxlife: 49 -+ register: result -+ failed_when: result.changed -+ -+ - name: Ensure absence of pwpoliciy global_policy will fail -+ ipapwpolicy: -+ ipaadmin_password: SomeADMINpassword -+ state: absent -+ register: result -+ ignore_errors: True -+ failed_when: result is defined and result -+ - - name: Ensure absence of pwpolicies for group ops - ipapwpolicy: - ipaadmin_password: SomeADMINpassword -@@ -50,6 +92,13 @@ - register: result - failed_when: not result.changed - -+ - name: Ensure maxlife of 90 for global_policy -+ ipapwpolicy: -+ ipaadmin_password: MyPassword123 -+ maxlife: 90 -+ register: result -+ failed_when: not result.changed -+ - - name: Ensure absence of pwpolicies for group ops - ipapwpolicy: - ipaadmin_password: SomeADMINpassword diff --git a/SOURCES/ansible-freeipa-0.1.8-ipauser-Allow-reset-of-userauthtype-do-not-depend-on-first-last-for-mod_rhbz#1784474.patch b/SOURCES/ansible-freeipa-0.1.8-ipauser-Allow-reset-of-userauthtype-do-not-depend-on-first-last-for-mod_rhbz#1784474.patch deleted file mode 100644 index cb0a7ef..0000000 --- a/SOURCES/ansible-freeipa-0.1.8-ipauser-Allow-reset-of-userauthtype-do-not-depend-on-first-last-for-mod_rhbz#1784474.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 36c1c837086c42049f09cf689a1ebd61627abae0 Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Tue, 17 Dec 2019 15:30:45 +0100 -Subject: [PATCH] ipauser: Allow reset of userauthtype, do not depend on - first,last for mod - -It was not possible to reset the userauthtype. The empty string has been -added to userauthtype for this. - -Also ipauser will only depend on given first and last name if the user -does not exist yet. For the update operation these parameters are not -needed anymore. ---- - README-user.md | 2 +- - plugins/modules/ipauser.py | 38 ++++++++++++++++++++++++++------------ - 2 files changed, 27 insertions(+), 13 deletions(-) - -diff --git a/README-user.md b/README-user.md -index 56772a7..991121c 100644 ---- a/README-user.md -+++ b/README-user.md -@@ -408,7 +408,7 @@ Variable | Description | Required - `manager` | List of manager user names. | no - `carlicense` | List of car licenses. | no - `sshpubkey` \| `ipasshpubkey` | List of SSH public keys. | no --`userauthtype` | List of supported user authentication types. Choices: `password`, `radius` and `otp` | no -+`userauthtype` | List of supported user authentication types. Choices: `password`, `radius`, `otp` and ``. Use empty string to reset userauthtype to the initial value. | no - `userclass` | User category. (semantics placed on this attribute are for local interpretation). | no - `radius` | RADIUS proxy configuration | no - `radiususer` | RADIUS proxy username | no -diff --git a/plugins/modules/ipauser.py b/plugins/modules/ipauser.py -index ac45295..36e8bae 100644 ---- a/plugins/modules/ipauser.py -+++ b/plugins/modules/ipauser.py -@@ -153,9 +153,12 @@ - required: false - aliases: ["ipasshpubkey"] - userauthtype: -- description: List of supported user authentication types -- choices=['password', 'radius', 'otp'] -+ description: -+ List of supported user authentication types -+ Use empty string to reset userauthtype to the initial value. -+ choices=['password', 'radius', 'otp', ''] - required: false -+ aliases: ["ipauserauthtype"] - userclass: - description: - - User category -@@ -310,9 +313,12 @@ - required: false - aliases: ["ipasshpubkey"] - userauthtype: -- description: List of supported user authentication types -- choices=['password', 'radius', 'otp'] -+ description: -+ List of supported user authentication types -+ Use empty string to reset userauthtype to the initial value. -+ choices=['password', 'radius', 'otp', ''] - required: false -+ aliases: ["ipauserauthtype"] - userclass: - description: - - User category -@@ -701,7 +707,7 @@ def main(): - default=None), - userauthtype=dict(type='list', aliases=["ipauserauthtype"], - default=None, -- choices=['password', 'radius', 'otp']), -+ choices=['password', 'radius', 'otp', '']), - userclass=dict(type="list", aliases=["class"], - default=None), - radius=dict(type="str", aliases=["ipatokenradiusconfiglink"], -@@ -845,13 +851,6 @@ def main(): - if names is not None and len(names) != 1: - ansible_module.fail_json( - msg="Only one user can be added at a time using name.") -- if action != "member": -- # Only check first and last here if names is set -- if names is not None: -- if first is None: -- ansible_module.fail_json(msg="First name is needed") -- if last is None: -- ansible_module.fail_json(msg="Last name is needed") - - check_parameters( - ansible_module, state, action, -@@ -1011,6 +1010,13 @@ def main(): - if "noprivate" in args: - del args["noprivate"] - -+ # Ignore userauthtype if it is empty (for resetting) -+ # and not set in for the user -+ if "ipauserauthtype" not in res_find and \ -+ "ipauserauthtype" in args and \ -+ args["ipauserauthtype"] == ['']: -+ del args["ipauserauthtype"] -+ - # For all settings is args, check if there are - # different settings in the find result. - # If yes: modify -@@ -1019,6 +1025,14 @@ def main(): - commands.append([name, "user_mod", args]) - - else: -+ # Make sure we have a first and last name -+ if first is None: -+ ansible_module.fail_json( -+ msg="First name is needed") -+ if last is None: -+ ansible_module.fail_json( -+ msg="Last name is needed") -+ - commands.append([name, "user_add", args]) - - # Handle members: principal, manager, certificate and diff --git a/SOURCES/ansible-freeipa-ipahost-Add-support-for-several-IP-addresses-and-also-to-change-them_rhbz#1783979,1783976.patch b/SOURCES/ansible-freeipa-ipahost-Add-support-for-several-IP-addresses-and-also-to-change-them_rhbz#1783979,1783976.patch deleted file mode 100644 index 4f2093d..0000000 --- a/SOURCES/ansible-freeipa-ipahost-Add-support-for-several-IP-addresses-and-also-to-change-them_rhbz#1783979,1783976.patch +++ /dev/null @@ -1,915 +0,0 @@ -From 167c76311da72c2bfabf4b2bce9e128c11d519d0 Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Wed, 12 Feb 2020 16:54:13 +0100 -Subject: [PATCH] ipahost: Add support for several IP addresses and also to - change them - -ipahost was so far ignoring IP addresses when the host already existed. -This happened because host_mod is not providing functionality to do this. -Now ipaddress is a list and it is possible to ensure a host with several -IP addresses (these can be IPv4 and IPv6). Also it is possible to ensure -presence and absence of IP addresses for an exising host using action -member. - -There are no IP address conclict checks as this would lead into issues with -updating an existing host that already is using a duplicate IP address for -example for round-robin (RR). Also this might lead into issues with ensuring -a new host with several IP addresses in this case. Also to ensure a list of -hosts with changing the IP address of one host to another in the list would -result in issues here. - -New example playbooks have been added: - - playbooks/host/host-present-with-several-ip-addresses.yml - playbooks/host/host-member-ipaddresses-absent.yml - playbooks/host/host-member-ipaddresses-present.yml - -A new test has been added for verification: - - tests/host/test_host_ipaddresses.yml - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1783976 - https://bugzilla.redhat.com/show_bug.cgi?id=1783979 ---- - README-host.md | 79 ++++- - .../host/host-member-ipaddresses-absent.yml | 17 + - .../host/host-member-ipaddresses-present.yml | 16 + - ...host-present-with-several-ip-addresses.yml | 24 ++ - .../module_utils/ansible_freeipa_module.py | 23 ++ - plugins/modules/ipahost.py | 179 +++++++--- - tests/host/test_host_ipaddresses.yml | 312 ++++++++++++++++++ - 7 files changed, 600 insertions(+), 50 deletions(-) - create mode 100644 playbooks/host/host-member-ipaddresses-absent.yml - create mode 100644 playbooks/host/host-member-ipaddresses-present.yml - create mode 100644 playbooks/host/host-present-with-several-ip-addresses.yml - create mode 100644 tests/host/test_host_ipaddresses.yml - -diff --git a/README-host.md b/README-host.md -index be5ad79..ecc59a9 100644 ---- a/README-host.md -+++ b/README-host.md -@@ -65,6 +65,79 @@ Example playbook to ensure host presence: - - "52:54:00:BD:97:1E" - state: present - ``` -+Compared to `ipa host-add` command no IP address conflict check is done as the ipahost module supports to have several IPv4 and IPv6 addresses for a host. -+ -+ -+Example playbook to ensure host presence with several IP addresses: -+ -+```yaml -+--- -+- name: Playbook to handle hosts -+ hosts: ipaserver -+ become: true -+ -+ tasks: -+ # Ensure host is present -+ - ipahost: -+ ipaadmin_password: MyPassword123 -+ name: host01.example.com -+ description: Example host -+ ip_address: -+ - 192.168.0.123 -+ - 192.168.0.124 -+ - fe80::20c:29ff:fe02:a1b3 -+ - fe80::20c:29ff:fe02:a1b4 -+ locality: Lab -+ ns_host_location: Lab -+ ns_os_version: CentOS 7 -+ ns_hardware_platform: Lenovo T61 -+ mac_address: -+ - "08:00:27:E3:B1:2D" -+ - "52:54:00:BD:97:1E" -+ state: present -+``` -+ -+ -+Example playbook to ensure IP addresses are present for a host: -+ -+```yaml -+--- -+- name: Playbook to handle hosts -+ hosts: ipaserver -+ become: true -+ -+ tasks: -+ # Ensure host is present -+ - ipahost: -+ ipaadmin_password: MyPassword123 -+ name: host01.example.com -+ ip_address: -+ - 192.168.0.124 -+ - fe80::20c:29ff:fe02:a1b4 -+ action: member -+ state: present -+``` -+ -+ -+Example playbook to ensure IP addresses are absent for a host: -+ -+```yaml -+--- -+- name: Playbook to handle hosts -+ hosts: ipaserver -+ become: true -+ -+ tasks: -+ # Ensure host is present -+ - ipahost: -+ ipaadmin_password: MyPassword123 -+ name: host01.example.com -+ ip_address: -+ - 192.168.0.124 -+ - fe80::20c:29ff:fe02:a1b4 -+ action: member -+ state: absent -+``` - - - Example playbook to ensure host presence without DNS: -@@ -215,7 +288,7 @@ Example playbook to disable a host: - update_dns: yes - state: disabled - ``` --`update_dns` controls if the DNS entries will be updated. -+`update_dns` controls if the DNS entries will be updated in this case. For `state` present it is controlling the update of the DNS SSHFP records, but not the the other DNS records. - - - Example playbook to ensure a host is absent: -@@ -286,8 +359,8 @@ Variable | Description | Required - `ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client (bool) | no - `force` | Force host name even if not in DNS. | no - `reverse` | Reverse DNS detection. | no --`ip_address` \| `ipaddress` | The host IP address. | no --`update_dns` | Update DNS entries. | no -+`ip_address` \| `ipaddress` | The host IP address list. It can contain IPv4 and IPv6 addresses. No conflict check for IP addresses is done. | no -+`update_dns` | For existing hosts: DNS SSHFP records are updated with `state` present and all DNS entries for a host removed with `state` absent. | no - - - Return Values -diff --git a/playbooks/host/host-member-ipaddresses-absent.yml b/playbooks/host/host-member-ipaddresses-absent.yml -new file mode 100644 -index 0000000..2466dbd ---- /dev/null -+++ b/playbooks/host/host-member-ipaddresses-absent.yml -@@ -0,0 +1,17 @@ -+--- -+- name: Host member IP addresses absent -+ hosts: ipaserver -+ become: true -+ -+ tasks: -+ - name: Ensure host01.example.com IP addresses absent -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: host01.example.com -+ ip_address: -+ - 192.168.0.123 -+ - fe80::20c:29ff:fe02:a1b3 -+ - 192.168.0.124 -+ - fe80::20c:29ff:fe02:a1b4 -+ action: member -+ state: absent -diff --git a/playbooks/host/host-member-ipaddresses-present.yml b/playbooks/host/host-member-ipaddresses-present.yml -new file mode 100644 -index 0000000..f473993 ---- /dev/null -+++ b/playbooks/host/host-member-ipaddresses-present.yml -@@ -0,0 +1,16 @@ -+--- -+- name: Host member IP addresses present -+ hosts: ipaserver -+ become: true -+ -+ tasks: -+ - name: Ensure host01.example.com IP addresses present -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: host01.example.com -+ ip_address: -+ - 192.168.0.123 -+ - fe80::20c:29ff:fe02:a1b3 -+ - 192.168.0.124 -+ - fe80::20c:29ff:fe02:a1b4 -+ action: member -diff --git a/playbooks/host/host-present-with-several-ip-addresses.yml b/playbooks/host/host-present-with-several-ip-addresses.yml -new file mode 100644 -index 0000000..4956562 ---- /dev/null -+++ b/playbooks/host/host-present-with-several-ip-addresses.yml -@@ -0,0 +1,24 @@ -+--- -+- name: Host present with several IP addresses -+ hosts: ipaserver -+ become: true -+ -+ tasks: -+ - name: Ensure host is present -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: host01.example.com -+ description: Example host -+ ip_address: -+ - 192.168.0.123 -+ - fe80::20c:29ff:fe02:a1b3 -+ - 192.168.0.124 -+ - fe80::20c:29ff:fe02:a1b4 -+ locality: Lab -+ ns_host_location: Lab -+ ns_os_version: CentOS 7 -+ ns_hardware_platform: Lenovo T61 -+ mac_address: -+ - "08:00:27:E3:B1:2D" -+ - "52:54:00:BD:97:1E" -+ state: present -diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py -index 9e97b88..6acdbef 100644 ---- a/plugins/module_utils/ansible_freeipa_module.py -+++ b/plugins/module_utils/ansible_freeipa_module.py -@@ -42,6 +42,7 @@ - from ipalib.x509 import Encoding - except ImportError: - from cryptography.hazmat.primitives.serialization import Encoding -+import socket - import base64 - import six - -@@ -285,3 +286,25 @@ def encode_certificate(cert): - if not six.PY2: - encoded = encoded.decode('ascii') - return encoded -+ -+ -+def is_ipv4_addr(ipaddr): -+ """ -+ Test if figen IP address is a valid IPv4 address -+ """ -+ try: -+ socket.inet_pton(socket.AF_INET, ipaddr) -+ except socket.error: -+ return False -+ return True -+ -+ -+def is_ipv6_addr(ipaddr): -+ """ -+ Test if figen IP address is a valid IPv6 address -+ """ -+ try: -+ socket.inet_pton(socket.AF_INET6, ipaddr) -+ except socket.error: -+ return False -+ return True -diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py -index dba4181..a5fd482 100644 ---- a/plugins/modules/ipahost.py -+++ b/plugins/modules/ipahost.py -@@ -176,11 +176,16 @@ - default: true - required: false - ip_address: -- description: The host IP address -+ description: -+ The host IP address list (IPv4 and IPv6). No IP address conflict -+ check will be done. - aliases: ["ipaddress"] - required: false - update_dns: -- description: Update DNS entries -+ description: -+ Controls the update of the DNS SSHFP records for existing hosts and -+ the removal of all DNS entries if a host gets removed with state -+ absent. - required: false - description: - description: The host description -@@ -306,11 +311,16 @@ - default: true - required: false - ip_address: -- description: The host IP address -+ description: -+ The host IP address list (IPv4 and IPv6). No IP address conflict -+ check will be done. - aliases: ["ipaddress"] - required: false - update_dns: -- description: Update DNS entries -+ description: -+ Controls the update of the DNS SSHFP records for existing hosts and -+ the removal of all DNS entries if a host gets removed with state -+ absent. - required: false - update_password: - description: -@@ -398,7 +408,8 @@ - from ansible.module_utils._text import to_text - from ansible.module_utils.ansible_freeipa_module import temp_kinit, \ - temp_kdestroy, valid_creds, api_connect, api_command, compare_args_ipa, \ -- module_params_get, gen_add_del_lists, encode_certificate, api_get_realm -+ module_params_get, gen_add_del_lists, encode_certificate, api_get_realm, \ -+ is_ipv4_addr, is_ipv6_addr - import six - - -@@ -428,6 +439,32 @@ def find_host(module, name): - return None - - -+def find_dnsrecord(module, name): -+ domain_name = name[name.find(".")+1:] -+ host_name = name[:name.find(".")] -+ -+ _args = { -+ "all": True, -+ "idnsname": to_text(host_name), -+ } -+ -+ _result = api_command(module, "dnsrecord_find", to_text(domain_name), -+ _args) -+ -+ if len(_result["result"]) > 1: -+ module.fail_json( -+ msg="There is more than one host '%s'" % (name)) -+ elif len(_result["result"]) == 1: -+ _res = _result["result"][0] -+ certs = _res.get("usercertificate") -+ if certs is not None: -+ _res["usercertificate"] = [encode_certificate(cert) for -+ cert in certs] -+ return _res -+ else: -+ return None -+ -+ - def show_host(module, name): - _result = api_command(module, "host_show", to_text(name), {}) - return _result["result"] -@@ -470,16 +507,34 @@ def gen_args(description, locality, location, platform, os, password, random, - _args["ipakrboktoauthasdelegate"] = ok_to_auth_as_delegate - if force is not None: - _args["force"] = force -- if reverse is not None: -- _args["no_reverse"] = not reverse - if ip_address is not None: -- _args["ip_address"] = ip_address -+ # IP addresses are handed extra, therefore it is needed to set -+ # the force option here to make sure that host-add is able to -+ # add a host without IP address. -+ _args["force"] = True - if update_dns is not None: - _args["updatedns"] = update_dns - - return _args - - -+def gen_dnsrecord_args(module, ip_address, reverse): -+ _args = {} -+ if reverse is not None: -+ _args["a_extra_create_reverse"] = reverse -+ _args["aaaa_extra_create_reverse"] = reverse -+ if ip_address is not None: -+ for ip in ip_address: -+ if is_ipv4_addr(ip): -+ _args.setdefault("arecord", []).append(ip) -+ elif is_ipv6_addr(ip): -+ _args.setdefault("aaaarecord", []).append(ip) -+ else: -+ module.fail_json(msg="'%s' is not a valid IP address." % ip) -+ -+ return _args -+ -+ - def check_parameters( - module, state, action, - description, locality, location, platform, os, password, random, -@@ -499,8 +554,7 @@ def check_parameters( - "os", "password", "random", "mac_address", "sshpubkey", - "userclass", "auth_ind", "requires_pre_auth", - "ok_as_delegate", "ok_to_auth_as_delegate", "force", -- "reverse", "ip_address", "update_dns", -- "update_password"] -+ "reverse", "update_dns", "update_password"] - for x in invalid: - if vars()[x] is not None: - module.fail_json( -@@ -512,7 +566,7 @@ def check_parameters( - "password", "random", "mac_address", "sshpubkey", - "userclass", "auth_ind", "requires_pre_auth", - "ok_as_delegate", "ok_to_auth_as_delegate", "force", -- "reverse", "ip_address", "update_password"] -+ "reverse", "update_password"] - for x in invalid: - if vars()[x] is not None: - module.fail_json( -@@ -549,9 +603,6 @@ def main(): - default=None, no_log=True), - random=dict(type="bool", aliases=["random_password"], - default=None), -- -- -- - certificate=dict(type="list", aliases=["usercertificate"], - default=None), - managedby_host=dict(type="list", -@@ -608,7 +659,7 @@ def main(): - default=None), - force=dict(type='bool', default=None), - reverse=dict(type='bool', default=None), -- ip_address=dict(type="str", aliases=["ipaddress"], -+ ip_address=dict(type="list", aliases=["ipaddress"], - default=None), - update_dns=dict(type="bool", aliases=["updatedns"], - default=None), -@@ -820,6 +871,7 @@ def main(): - - # Make sure host exists - res_find = find_host(ansible_module, name) -+ res_find_dnsrecord = find_dnsrecord(ansible_module, name) - - # Create command - if state == "present": -@@ -829,6 +881,8 @@ def main(): - random, mac_address, sshpubkey, userclass, auth_ind, - requires_pre_auth, ok_as_delegate, ok_to_auth_as_delegate, - force, reverse, ip_address, update_dns) -+ dnsrecord_args = gen_dnsrecord_args( -+ ansible_module, ip_address, reverse) - - if action == "host": - # Found the host -@@ -938,39 +992,20 @@ def main(): - res_find.get( - "ipaallowedtoperform_read_keys_hostgroup")) - -- else: -- certificate_add = certificate or [] -- certificate_del = [] -- managedby_host_add = managedby_host or [] -- managedby_host_del = [] -- principal_add = principal or [] -- principal_del = [] -- allow_create_keytab_user_add = \ -- allow_create_keytab_user or [] -- allow_create_keytab_user_del = [] -- allow_create_keytab_group_add = \ -- allow_create_keytab_group or [] -- allow_create_keytab_group_del = [] -- allow_create_keytab_host_add = \ -- allow_create_keytab_host or [] -- allow_create_keytab_host_del = [] -- allow_create_keytab_hostgroup_add = \ -- allow_create_keytab_hostgroup or [] -- allow_create_keytab_hostgroup_del = [] -- allow_retrieve_keytab_user_add = \ -- allow_retrieve_keytab_user or [] -- allow_retrieve_keytab_user_del = [] -- allow_retrieve_keytab_group_add = \ -- allow_retrieve_keytab_group or [] -- allow_retrieve_keytab_group_del = [] -- allow_retrieve_keytab_host_add = \ -- allow_retrieve_keytab_host or [] -- allow_retrieve_keytab_host_del = [] -- allow_retrieve_keytab_hostgroup_add = \ -- allow_retrieve_keytab_hostgroup or [] -- allow_retrieve_keytab_hostgroup_del = [] -+ # IP addresses are not really a member of hosts, but -+ # we will simply treat it as this to enable the -+ # addition and removal of IPv4 and IPv6 addresses in -+ # a simple way. -+ _dnsrec = res_find_dnsrecord or {} -+ dnsrecord_a_add, dnsrecord_a_del = gen_add_del_lists( -+ dnsrecord_args.get("arecord"), -+ _dnsrec.get("arecord")) -+ dnsrecord_aaaa_add, dnsrecord_aaaa_del = \ -+ gen_add_del_lists( -+ dnsrecord_args.get("aaaarecord"), -+ _dnsrec.get("aaaarecord")) - -- else: -+ if action != "host" or (action == "host" and res_find is None): - certificate_add = certificate or [] - certificate_del = [] - managedby_host_add = managedby_host or [] -@@ -1001,6 +1036,10 @@ def main(): - allow_retrieve_keytab_hostgroup_add = \ - allow_retrieve_keytab_hostgroup or [] - allow_retrieve_keytab_hostgroup_del = [] -+ dnsrecord_a_add = dnsrecord_args.get("arecord") or [] -+ dnsrecord_a_del = [] -+ dnsrecord_aaaa_add = dnsrecord_args.get("aaaarecord") or [] -+ dnsrecord_aaaa_del = [] - - # Remove canonical principal from principal_del - canonical_principal = "host/" + name + "@" + server_realm -@@ -1135,6 +1174,36 @@ def main(): - "hostgroup": allow_retrieve_keytab_hostgroup_del, - }]) - -+ if len(dnsrecord_a_add) > 0 or len(dnsrecord_aaaa_add) > 0: -+ domain_name = name[name.find(".")+1:] -+ host_name = name[:name.find(".")] -+ -+ commands.append([domain_name, -+ "dnsrecord_add", -+ { -+ "idnsname": host_name, -+ "arecord": dnsrecord_a_add, -+ "a_extra_create_reverse": reverse, -+ "aaaarecord": dnsrecord_aaaa_add, -+ "aaaa_extra_create_reverse": reverse -+ }]) -+ -+ if len(dnsrecord_a_del) > 0 or len(dnsrecord_aaaa_del) > 0: -+ domain_name = name[name.find(".")+1:] -+ host_name = name[:name.find(".")] -+ -+ # There seems to be an issue with dnsrecord_del (not -+ # for dnsrecord_add) if aaaarecord is an empty list. -+ # Therefore this is done differently here: -+ _args = {"idnsname": host_name} -+ if len(dnsrecord_a_del) > 0: -+ _args["arecord"] = dnsrecord_a_del -+ if len(dnsrecord_aaaa_del) > 0: -+ _args["aaaarecord"] = dnsrecord_aaaa_del -+ -+ commands.append([domain_name, -+ "dnsrecord_del", _args]) -+ - elif state == "absent": - if action == "host": - -@@ -1215,6 +1284,17 @@ def main(): - "hostgroup": allow_retrieve_keytab_hostgroup, - }]) - -+ dnsrecord_args = gen_dnsrecord_args(ansible_module, -+ ip_address, reverse) -+ if "arecord" in dnsrecord_args or \ -+ "aaaarecord" in dnsrecord_args: -+ domain_name = name[name.find(".")+1:] -+ host_name = name[:name.find(".")] -+ dnsrecord_args["idnsname"] = host_name -+ -+ commands.append([domain_name, "dnsrecord_del", -+ dnsrecord_args]) -+ - elif state == "disabled": - if res_find is not None: - commands.append([name, "host_disable", {}]) -@@ -1259,6 +1339,11 @@ def main(): - # Host is already disabled, ignore error - if "This entry is already disabled" in msg: - continue -+ -+ # Ignore no modification error. -+ if "no modifications to be performed" in msg: -+ continue -+ - ansible_module.fail_json(msg="%s: %s: %s" % (command, name, - msg)) - -diff --git a/tests/host/test_host_ipaddresses.yml b/tests/host/test_host_ipaddresses.yml -new file mode 100644 -index 0000000..0a97dd5 ---- /dev/null -+++ b/tests/host/test_host_ipaddresses.yml -@@ -0,0 +1,312 @@ -+--- -+- name: Test host IP addresses -+ hosts: ipaserver -+ become: true -+ -+ tasks: -+ - name: Get Domain from server name -+ set_fact: -+ ipaserver_domain: "{{ groups.ipaserver[0].split('.')[1:] | join ('.') }}" -+ when: ipaserver_domain is not defined -+ -+ - name: Set host1_fqdn .. host6_fqdn -+ set_fact: -+ host1_fqdn: "{{ 'host1.' + ipaserver_domain }}" -+ host2_fqdn: "{{ 'host2.' + ipaserver_domain }}" -+ host3_fqdn: "{{ 'host3.' + ipaserver_domain }}" -+ -+ - name: Get IPv4 address prefix from server node -+ set_fact: -+ ipv4_prefix: "{{ ansible_default_ipv4.address.split('.')[:-1] | -+ join('.') }}" -+ -+ - name: Host absent -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: -+ - "{{ host1_fqdn }}" -+ - "{{ host2_fqdn }}" -+ - "{{ host3_fqdn }}" -+ update_dns: yes -+ state: absent -+ -+ - name: Host "{{ host1_fqdn }}" present -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.201' }}" -+ - fe80::20c:29ff:fe02:a1b2 -+ update_dns: yes -+ reverse: no -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.201' }}" -+ - fe80::20c:29ff:fe02:a1b2 -+ update_dns: yes -+ reverse: no -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present again with new IP address -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ update_dns: yes -+ reverse: no -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" present again with new IP address again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ update_dns: yes -+ reverse: no -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host1_fqdn }}" member IPv4 address present -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: "{{ ipv4_prefix + '.201' }}" -+ action: member -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" member IPv4 address present again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: "{{ ipv4_prefix + '.201' }}" -+ action: member -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host1_fqdn }}" member IPv4 address absent -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: "{{ ipv4_prefix + '.201' }}" -+ action: member -+ state: absent -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" member IPv4 address absent again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: "{{ ipv4_prefix + '.201' }}" -+ action: member -+ state: absent -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host1_fqdn }}" member IPv6 address present -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: fe80::20c:29ff:fe02:a1b2 -+ action: member -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" member IPv6 address present again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: fe80::20c:29ff:fe02:a1b2 -+ action: member -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host1_fqdn }}" member IPv6 address absent -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: fe80::20c:29ff:fe02:a1b2 -+ action: member -+ state: absent -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" member IPv6 address absent again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: fe80::20c:29ff:fe02:a1b2 -+ action: member -+ state: absent -+ register: result -+ -+ - name: Host "{{ host1_fqdn }}" member all ip-addresses absent -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ action: member -+ state: absent -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host1_fqdn }}" all member ip-addresses absent again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: "{{ host1_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ action: member -+ state: absent -+ register: result -+ failed_when: result.changed -+ -+ - name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" present with same IP addresses -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: "{{ host1_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ - name: "{{ host2_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Hosts "{{ host1_fqdn }}" and "{{ host2_fqdn }}" present with same IP addresses again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: "{{ host1_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ - name: "{{ host2_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ register: result -+ failed_when: result.changed -+ -+ - name: Hosts "{{ host3_fqdn }}" present with same IP addresses -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: "{{ host3_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Hosts "{{ host3_fqdn }}" present with same IP addresses again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: "{{ host3_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host3_fqdn }}" present with differnt IP addresses -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: "{{ host3_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.111' }}" -+ - fe80::20c:29ff:fe02:a1b1 -+ - "{{ ipv4_prefix + '.121' }}" -+ - fe80::20c:29ff:fe02:a1b2 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host3_fqdn }}" present with different IP addresses again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: "{{ host3_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.111' }}" -+ - fe80::20c:29ff:fe02:a1b1 -+ - "{{ ipv4_prefix + '.121' }}" -+ - fe80::20c:29ff:fe02:a1b2 -+ register: result -+ failed_when: result.changed -+ -+ - name: Host "{{ host3_fqdn }}" present with old IP addresses -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: "{{ host3_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ register: result -+ failed_when: not result.changed -+ -+ - name: Host "{{ host3_fqdn }}" present with old IP addresses again -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ hosts: -+ - name: "{{ host3_fqdn }}" -+ ip_address: -+ - "{{ ipv4_prefix + '.211' }}" -+ - fe80::20c:29ff:fe02:a1b3 -+ - "{{ ipv4_prefix + '.221' }}" -+ - fe80::20c:29ff:fe02:a1b4 -+ register: result -+ failed_when: result.changed -+ -+ - name: Host absent -+ ipahost: -+ ipaadmin_password: MyPassword123 -+ name: -+ - "{{ host1_fqdn }}" -+ - "{{ host2_fqdn }}" -+ - "{{ host3_fqdn }}" -+ update_dns: yes -+ state: absent -From 8f32cb04c1e161e1e3217f10413685a2cc9bf492 Mon Sep 17 00:00:00 2001 -From: Thomas Woerner -Date: Thu, 13 Feb 2020 14:10:38 +0100 -Subject: [PATCH] tests/host/test_host: Fix use of wrong host in the host5 test - -host1 was used instead of host5 in the repeated host5 test. This lead to an -error with the new IP address handling in ipahost. It was correctly -reporting a change for host1 which resulted in a failed test. ---- - tests/host/test_host.yml | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tests/host/test_host.yml b/tests/host/test_host.yml -index 1a555a1..f3ec11d 100644 ---- a/tests/host/test_host.yml -+++ b/tests/host/test_host.yml -@@ -129,7 +129,7 @@ - - name: Host "{{ host5_fqdn }}" present again - ipahost: - ipaadmin_password: MyPassword123 -- name: "{{ host1_fqdn }}" -+ name: "{{ host5_fqdn }}" - ip_address: "{{ ipv4_prefix + '.205' }}" - update_dns: yes - reverse: no diff --git a/SPECS/ansible-freeipa.spec b/SPECS/ansible-freeipa.spec index 0b748d4..9ef5da6 100644 --- a/SPECS/ansible-freeipa.spec +++ b/SPECS/ansible-freeipa.spec @@ -5,28 +5,19 @@ Summary: Roles and playbooks to deploy FreeIPA servers, replicas and clients Name: ansible-freeipa -Version: 0.1.8 -Release: 3%{?dist} +Version: 0.1.10 +Release: 1%{?dist} URL: https://github.com/freeipa/ansible-freeipa License: GPLv3+ Source: https://github.com/freeipa/ansible-freeipa/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz -Patch1: ansible-freeipa-0.1.8-ipahost-Fix-choices-of-auth_ind-parameter-allow-to-reset-parameter_rhbz#1783992.patch -Patch2: ansible-freeipa-0.1.8-ipauser-Allow-reset-of-userauthtype-do-not-depend-on-first-last-for-mod_rhbz#1784474.patch -Patch3: ansible-freeipa-0.1.8-ipahost-Enhanced-failure-msg-for-member-params-used-without-member-action_rhbz#1783948.patch -Patch4: ansible-freeipa-0.1.8-Add-missing-attributes-to-ipasudorule_rhbz#1788168,1788035,1788024.patch -Patch5: ansible-freeipa-0.1.8-ipapwpolicy-Use-global_policy-if-name-is-not-set_rhbz#1797532.patch -Patch6: ansible-freeipa-0.1.8-ipahbacrule-Fix-handing-of-members-with-action-hbacrule_rhbz#1787996.patch -Patch7: ansible-freeipa-0.1.8-ansible_freeipa_module-Fix-comparison-of-bool-parameters-in-compare_args_ipa_rhbz#1784514.patch -Patch8: ansible-freeipa-ipahost-Add-support-for-several-IP-addresses-and-also-to-change-them_rhbz#1783979,1783976.patch -Patch9: ansible-freeipa-0.1.8-ipahost-Fail-on-action-member-for-new-hosts-fix-dnsrecord_add-reverse-flag_rhbz#1803026.patch -Patch10: ansible-freeipa-0.1.8-ipahost-Do-not-fail-on-missing-DNS-or-zone-when-no-IP-address-given_rhbz#1804838.patch BuildArch: noarch #Requires: ansible %description ansible-freeipa provides Ansible roles and playbooks to install and uninstall -FreeIPA servers, replicas and clients also modules for management. +FreeIPA servers, replicas and clients. Also modules for group, host, topology +and user management. Note: The ansible playbooks and roles require a configured ansible environment where the ansible nodes are reachable and are properly set up to have an IP @@ -38,6 +29,8 @@ Features - Cluster deployments: Server, replicas and clients in one playbook - One-time-password (OTP) support for client installation - Repair mode for clients +- Modules for dns forwarder management +- Modules for dns zone management - Modules for group management - Modules for hbacrule management - Modules for hbacsvc management @@ -45,11 +38,13 @@ Features - Modules for host management - Modules for hostgroup management - Modules for pwpolicy management +- Modules for service management - Modules for sudocmd management - Modules for sudocmdgroup management - Modules for sudorule management - Modules for topology management - Modules for user management +- Modules for vault management Supported FreeIPA Versions @@ -69,37 +64,29 @@ Supported Distributions Requirements Controller + - Ansible version: 2.8+ (ansible-freeipa is an Ansible Collection) - - /usr/bin/kinit is required on the controller if a one time password (OTP) + /usr/bin/kinit is required on the controller if a one time password (OTP) is used - python3-gssapi is required on the controller if a one time password (OTP) is used with keytab to install the client. Node + - Supported FreeIPA version (see above) - Supported distribution (needed for package installation only, see above) Limitations -External CA support is not supported or working. The currently needed two step -process is an issue for the processing in the role. The configuration of the -server is partly done already and needs to be continued after the CSR has been -handled. This is for example breaking the deployment of a server with replicas -or clients in one playbook. +External signed CA is now supported. But the currently needed two step process +is an issue for the processing in a simple playbook. +Work is planned to have a new method to handle CSR for external signed CAs in +a separate step before starting the server installation. + %prep %setup -q # Do not create backup files with patches -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 -%patch8 -p1 -%patch9 -p1 -%patch10 -p1 # Fix python modules and module utils: # - Remove shebang # - Remove execute flag @@ -130,11 +117,34 @@ cp -rp plugins/* %{buildroot}%{_datadir}/ansible/plugins/ %{_datadir}/ansible/roles/ipaclient %{_datadir}/ansible/plugins/module_utils %{_datadir}/ansible/plugins/modules -%doc README.md -%doc README-*.md +%doc README*.md %doc playbooks %changelog +* Mon Apr 27 2020 Thomas Woerner - 0.1.10-1 +- Update to version 0.1.10: + - ipaclient: Not delete keytab when ipaclient_on_master is true + - New module to manage dns forwarder zones in ipa + - Enhancements of sudorule module tests + - Gracefully handle RuntimeError raised during parameter validation in + fail_jso + - ipareplica_prepare: Fix module DOCUMENTATION + - ipa[server,replica,client]: setup_logging wrapper for + standard_logging_setup + - Created FreeIPABaseModule class to facilitate creation of new modules + - New IPADNSZone module + - Add admin password to the ipadnsconfig module tests + - Added alias module arguments in dnszone module + - Fixed a bug in AnsibleFreeIPAParams + - utils/build-galaxy-release: Do not add release tag to version for galaxy + - ipaserver docs: Calm down module linter + - galaxy.yml: Add system tag + - ipareplica_setup_kra: Remove unused ccache parameter + - ipareplica_setup_krb: krb is assigned to but never used + - utils/galaxy: Make galaxy scripts more generic + - galaxyfy-playbook.py: Fixed script name + Related: RHBZ#1818768 + * Thu Feb 20 2020 Thomas Woerner - 0.1.8-3 - ipahost: Do not fail on missing DNS or zone when no IP address given Resolves: RHBZ#1804838