From c3c4733c4ea97a92900fd8e815c55531b87f31ad Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman Date: Mon, 26 Sep 2022 22:43:58 -0300 Subject: [PATCH] ipasudorule: Refactor member management. --- plugins/modules/ipasudorule.py | 423 ++++++++------------------------- 1 file changed, 105 insertions(+), 318 deletions(-) diff --git a/plugins/modules/ipasudorule.py b/plugins/modules/ipasudorule.py index 05184c3293..c0fee63844 100644 --- a/plugins/modules/ipasudorule.py +++ b/plugins/modules/ipasudorule.py @@ -318,13 +318,15 @@ def main(): allow_sudocmd = ansible_module.params_get('allow_sudocmd') allow_sudocmdgroup = \ ansible_module.params_get_lowercase('allow_sudocmdgroup') + # pylint: disable=possibly-unused-variable deny_sudocmd = ansible_module.params_get('deny_sudocmd') deny_sudocmdgroup = \ ansible_module.params_get_lowercase('deny_sudocmdgroup') sudooption = ansible_module.params_get("sudooption") - order = ansible_module.params_get("order") runasuser = ansible_module.params_get_lowercase("runasuser") runasgroup = ansible_module.params_get_lowercase("runasgroup") + # pylint: enable=possibly-unused-variable + order = ansible_module.params_get("order") action = ansible_module.params_get("action") # state @@ -403,18 +405,51 @@ def main(): ) commands = [] - host_add, host_del = [], [] - user_add, user_del = [], [] - group_add, group_del = [], [] - hostgroup_add, hostgroup_del = [], [] - hostmask_add, hostmask_del = [], [] - allow_cmd_add, allow_cmd_del = [], [] - allow_cmdgroup_add, allow_cmdgroup_del = [], [] - deny_cmd_add, deny_cmd_del = [], [] - deny_cmdgroup_add, deny_cmdgroup_del = [], [] - sudooption_add, sudooption_del = [], [] - runasuser_add, runasuser_del = [], [] - runasgroup_add, runasgroup_del = [], [] + + # Command configuration for managing members + member_args = { + "add": {}, + "remove": {} + } + member_map = { + ("memberhost_host",): "host", + ("memberhost_hostgroup",): "hostgroup", + ("hostmask",): "hostmask", + ("memberuser_user",): "user", + ("memberuser_group",): "group", + ("memberallowcmd_sudocmd",): "allow_sudocmd", + ("memberallowcmd_sudocmdgroup",): "allow_sudocmdgroup", + ("memberdenycmd_sudocmd",): "deny_sudocmd", + ("memberdenycmd_sudocmdgroup",): "deny_sudocmdgroup", + ("ipasudoopt",): "sudooption", + ("ipasudorunas_user", "ipasudorunasextuser"): "runasuser", + ("ipasudorunasgroup_group", "ipasudorunasextgroup"): "runasgroup" + } + member_manage = { + "sudorule_{add_del}_host": { + "host": "host", + "hostgroup": "hostgroup", + "hostmask": "hostmask", + }, + "sudorule_{add_del}_user": { + "user": "user", + "group": "group", + }, + "sudorule_{add_del}_allow_command": { + "sudocmd": "allow_sudocmd", + "sudocmdgroup": "allow_sudocmdgroup", + }, + "sudorule_{add_del}_deny_command": { + "sudocmd": "deny_sudocmd", + "sudocmdgroup": "deny_sudocmdgroup", + }, + "sudorule_{add_del}_runasuser": { + "user": "runasuser", + }, + "sudorule_{add_del}_runasgroup": { + "group": "runasgroup", + }, + } for name in names: # Make sure sudorule exists @@ -434,26 +469,14 @@ def main(): # from args if "" and if the category is not in the # sudorule. The empty string is used to reset the # category. - if "usercategory" in args \ - and args["usercategory"] == "" \ - and "usercategory" not in res_find: - del args["usercategory"] - if "hostcategory" in args \ - and args["hostcategory"] == "" \ - and "hostcategory" not in res_find: - del args["hostcategory"] - if "cmdcategory" in args \ - and args["cmdcategory"] == "" \ - and "cmdcategory" not in res_find: - del args["cmdcategory"] - if "ipasudorunasusercategory" in args \ - and args["ipasudorunasusercategory"] == "" \ - and "ipasudorunasusercategory" not in res_find: - del args["ipasudorunasusercategory"] - if "ipasudorunasgroupcategory" in args \ - and args["ipasudorunasgroupcategory"] == "" \ - and "ipasudorunasgroupcategory" not in res_find: - del args["ipasudorunasgroupcategory"] + remove_args = [ + "usercategory", "hostcategory", "cmdcategory", + "ipasudorunasusercategory", + "ipasudorunasgroupcategory", + ] + for arg in remove_args: + if args.get(arg) == "" and arg not in res_find: + del args[arg] # For all settings is args, check if there are # different settings in the find result. @@ -467,133 +490,33 @@ def main(): res_find = {} # Generate addition and removal lists - host_add, host_del = gen_add_del_lists( - host, res_find.get('memberhost_host', [])) - - hostgroup_add, hostgroup_del = gen_add_del_lists( - hostgroup, res_find.get('memberhost_hostgroup', [])) - - hostmask_add, hostmask_del = gen_add_del_lists( - hostmask, res_find.get('hostmask', [])) - - user_add, user_del = gen_add_del_lists( - user, res_find.get('memberuser_user', [])) - - group_add, group_del = gen_add_del_lists( - group, res_find.get('memberuser_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 attribute can be used with both IPA and - # non-IPA (external) users. IPA will handle the correct - # attribute to properly store data, so we need to compare - # the provided list against both users and external - # users list. - runasuser_add, runasuser_del = gen_add_del_lists( - runasuser, - ( - res_find.get('ipasudorunas_user', []) - + res_find.get('ipasudorunasextuser', []) - ) - ) - - # runasgroup attribute can be used with both IPA and - # non-IPA (external) groups. IPA will handle the correct - # attribute to properly store data, so we need to compare - # the provided list against both groups and external - # groups list. - runasgroup_add, runasgroup_del = gen_add_del_lists( - runasgroup, - ( - res_find.get('ipasudorunasgroup_group', []) - + res_find.get('ipasudorunasextgroup', []) + all_data = locals() + for fields, param in member_map.items(): + add_data, del_data = gen_add_del_lists( + all_data[param], + sum( + [list(res_find.get(x, [])) for x in fields], + [] + ) ) - ) + member_args["add"][param] = add_data + member_args["remove"][param] = del_data elif action == "member": if res_find is None: ansible_module.fail_json(msg="No sudorule '%s'" % name) - # Generate add lists for host, hostgroup, user, group, - # allow_sudocmd, allow_sudocmdgroup, deny_sudocmd, - # deny_sudocmdgroup, sudooption, runasuser, runasgroup - # and res_find to only try to add the items that not in - # the sudorule already - if host is not None: - host_add = gen_add_list( - host, res_find.get("memberhost_host")) - if hostgroup is not None: - hostgroup_add = gen_add_list( - hostgroup, res_find.get("memberhost_hostgroup")) - if hostmask is not None: - hostmask_add = gen_add_list( - hostmask, res_find.get("hostmask")) - if user is not None: - user_add = gen_add_list( - user, res_find.get("memberuser_user")) - if group is not None: - group_add = gen_add_list( - group, res_find.get("memberuser_group")) - if allow_sudocmd is not None: - allow_cmd_add = gen_add_list( - allow_sudocmd, - res_find.get("memberallowcmd_sudocmd") - ) - if allow_sudocmdgroup is not None: - allow_cmdgroup_add = gen_add_list( - allow_sudocmdgroup, - res_find.get("memberallowcmd_sudocmdgroup") - ) - if deny_sudocmd is not None: - deny_cmd_add = gen_add_list( - deny_sudocmd, - res_find.get("memberdenycmd_sudocmd") - ) - if deny_sudocmdgroup is not None: - deny_cmdgroup_add = gen_add_list( - deny_sudocmdgroup, - res_find.get("memberdenycmd_sudocmdgroup") - ) - if sudooption is not None: - sudooption_add = gen_add_list( - sudooption, res_find.get("ipasudoopt")) - # runasuser attribute can be used with both IPA and - # non-IPA (external) users, so we need to compare - # the provided list against both users and external - # users list. - if runasuser is not None: - runasuser_add = gen_add_list( - runasuser, - (list(res_find.get('ipasudorunas_user', [])) - + list(res_find.get('ipasudorunasextuser', []))) - ) - # runasgroup attribute can be used with both IPA and - # non-IPA (external) groups, so we need to compare - # the provided list against both users and external - # groups list. - if runasgroup is not None: - runasgroup_add = gen_add_list( - runasgroup, - (list(res_find.get("ipasudorunasgroup_group", [])) - + list(res_find.get("ipasudorunasextgroup", []))) + # Generate add lists + all_data = locals() + for fields, param in member_map.items(): + add_data = gen_add_list( + all_data[param], + sum( + [list(res_find.get(x, [])) for x in fields], + [] + ) ) + member_args["add"][param] = add_data elif state == "absent": if action == "sudorule": @@ -604,80 +527,17 @@ def main(): if res_find is None: ansible_module.fail_json(msg="No sudorule '%s'" % name) - # Generate intersection lists for host, hostgroup, user, - # group, allow_sudocmd, allow_sudocmdgroup, deny_sudocmd - # deny_sudocmdgroup, sudooption, runasuser, runasgroup - # and res_find to only try to remove the items that are - # in sudorule - if host is not None: - host_del = gen_intersection_list( - host, res_find.get("memberhost_host")) - - if hostgroup is not None: - hostgroup_del = gen_intersection_list( - hostgroup, res_find.get("memberhost_hostgroup")) - - if hostmask is not None: - hostmask_del = gen_intersection_list( - hostmask, res_find.get("hostmask")) - - if user is not None: - user_del = gen_intersection_list( - user, res_find.get("memberuser_user")) - - if group is not None: - group_del = gen_intersection_list( - group, res_find.get("memberuser_group")) - - if allow_sudocmd is not None: - allow_cmd_del = gen_intersection_list( - allow_sudocmd, - res_find.get("memberallowcmd_sudocmd") - ) - if allow_sudocmdgroup is not None: - allow_cmdgroup_del = gen_intersection_list( - allow_sudocmdgroup, - res_find.get("memberallowcmd_sudocmdgroup") - ) - if deny_sudocmd is not None: - deny_cmd_del = gen_intersection_list( - deny_sudocmd, - res_find.get("memberdenycmd_sudocmd") - ) - if deny_sudocmdgroup is not None: - deny_cmdgroup_del = gen_intersection_list( - deny_sudocmdgroup, - res_find.get("memberdenycmd_sudocmdgroup") - ) - if sudooption is not None: - sudooption_del = gen_intersection_list( - sudooption, res_find.get("ipasudoopt")) - # runasuser attribute can be used with both IPA and - # non-IPA (external) users, so we need to compare - # the provided list against both users and external - # users list. - if runasuser is not None: - runasuser_del = gen_intersection_list( - runasuser, - ( - list(res_find.get('ipasudorunas_user', [])) - + list(res_find.get('ipasudorunasextuser', [])) - ) - ) - # runasgroup attribute can be used with both IPA and - # non-IPA (external) groups, so we need to compare - # the provided list against both groups and external - # groups list. - if runasgroup is not None: - runasgroup_del = gen_intersection_list( - runasgroup, - ( - list(res_find.get( - "ipasudorunasgroup_group", [])) - + list(res_find.get( - "ipasudorunasextgroup", [])) + # Generate intersection lists + all_data = locals() + for fields, param in member_map.items(): + del_data = gen_intersection_list( + all_data[param], + sum( + [list(res_find.get(x, [])) for x in fields], + [] ) ) + member_args["remove"][param] = del_data elif state == "enabled": if res_find is None: @@ -711,101 +571,28 @@ def main(): ansible_module.fail_json(msg="Unkown state '%s'" % state) # Manage members. - # Manage hosts and hostgroups - if any([host_add, hostgroup_add, hostmask_add]): - params = {"host": host_add, "hostgroup": hostgroup_add} - # An empty Hostmask cannot be used, or IPA API will fail. - if hostmask_add: - params["hostmask"] = hostmask_add - commands.append([name, "sudorule_add_host", params]) - - if any([host_del, hostgroup_del, hostmask_del]): - params = {"host": host_del, "hostgroup": hostgroup_del} - # An empty Hostmask cannot be used, or IPA API will fail. - if hostmask_del: - params["hostmask"] = hostmask_del - commands.append([name, "sudorule_remove_host", params]) - - # Manage users and groups - if user_add or group_add: - commands.append([ - name, "sudorule_add_user", - {"user": user_add, "group": group_add} - ]) - if user_del or group_del: - commands.append([ - name, "sudorule_remove_user", - {"user": user_del, "group": group_del} - ]) - - # Manage commands allowed - if allow_cmd_add or allow_cmdgroup_add: - commands.append([ - name, "sudorule_add_allow_command", - { - "sudocmd": allow_cmd_add, - "sudocmdgroup": allow_cmdgroup_add, - } - ]) - if allow_cmd_del or allow_cmdgroup_del: - commands.append([ - name, "sudorule_remove_allow_command", - { - "sudocmd": allow_cmd_del, - "sudocmdgroup": allow_cmdgroup_del - } - ]) - # Manage commands denied - if deny_cmd_add or deny_cmdgroup_add: - commands.append([ - name, "sudorule_add_deny_command", - { - "sudocmd": deny_cmd_add, - "sudocmdgroup": deny_cmdgroup_add, - } - ]) - if deny_cmd_del or deny_cmdgroup_del: - commands.append([ - name, "sudorule_remove_deny_command", - { - "sudocmd": deny_cmd_del, - "sudocmdgroup": deny_cmdgroup_del - } - ]) - # Manage RunAS users - if runasuser_add: - commands.append([ - name, "sudorule_add_runasuser", {"user": runasuser_add} - ]) - if runasuser_del: - commands.append([ - name, "sudorule_remove_runasuser", {"user": runasuser_del} - ]) - - # Manage RunAS Groups - if runasgroup_add: - commands.append([ - name, "sudorule_add_runasgroup", {"group": runasgroup_add} - ]) - if runasgroup_del: - commands.append([ - name, "sudorule_remove_runasgroup", - {"group": runasgroup_del} - ]) - # Manage sudo options - if sudooption_add: - for option in sudooption_add: - commands.append([ - name, "sudorule_add_option", {"ipasudoopt": option} - ]) - if sudooption_del: - for option in sudooption_del: - commands.append([ - name, "sudorule_remove_option", {"ipasudoopt": option} - ]) + for add_del in ["add", "remove"]: + for command, fields in member_manage.items(): + params = {} + run_command = False + for field, param in fields.items(): + data = member_args[add_del].get(param) + if data: + params[field] = data + run_command = True + if run_command: + commands.append( + [name, command.format(add_del=add_del), params] + ) + # Sudo options must be added one by one. + for add_del in ["add", "remove"]: + data = member_args[add_del].get("sudooption") + if data: + cmd = "sudorule_{add_del}_option".format(add_del=add_del) + for option in data: + commands.append([name, cmd, {"ipasudoopt": option}]) # Execute commands - changed = ansible_module.execute_ipa_commands( commands, fail_on_member_errors=True)