def main(): ansible_module = IPAAnsibleModule( argument_spec=dict( # general name=dict(type="list", aliases=["cn"], default=None, required=True), # present description=dict(required=False, type="str", default=None), usercategory=dict(required=False, type="str", default=None, choices=["all", ""], aliases=['usercat']), hostcategory=dict(required=False, type="str", default=None, choices=["all", ""], aliases=['hostcat']), nomembers=dict(required=False, type='bool', default=None), host=dict(required=False, type='list', default=None), hostgroup=dict(required=False, type='list', default=None), user=dict(required=False, type='list', default=None), group=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", ""], aliases=['cmdcat']), runasusercategory=dict(required=False, type="str", default=None, choices=["all", ""], aliases=['runasusercat']), runasgroupcategory=dict(required=False, type="str", default=None, choices=["all", ""], aliases=['runasgroupcat']), 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 state=dict(type="str", default="present", choices=["present", "absent", "enabled", "disabled"]), ), supports_check_mode=True, ) ansible_module._ansible_debug = True # Get parameters # general names = ansible_module.params_get("name") # present # The 'noqa' variables are not used here, but required for vars(). # The use of 'noqa' ensures flake8 does not complain about them. description = ansible_module.params_get("description") # noqa cmdcategory = ansible_module.params_get('cmdcategory') # noqa usercategory = ansible_module.params_get("usercategory") # noqa hostcategory = ansible_module.params_get("hostcategory") # noqa runasusercategory = ansible_module.params_get( # noqa "runasusercategory") runasgroupcategory = ansible_module.params_get( # noqa "runasgroupcategory") hostcategory = ansible_module.params_get("hostcategory") # noqa nomembers = ansible_module.params_get("nomembers") # noqa host = ansible_module.params_get("host") hostgroup = ansible_module.params_get_lowercase("hostgroup") user = ansible_module.params_get_lowercase("user") group = ansible_module.params_get_lowercase("group") allow_sudocmd = ansible_module.params_get('allow_sudocmd') allow_sudocmdgroup = \ ansible_module.params_get_lowercase('allow_sudocmdgroup') 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") action = ansible_module.params_get("action") # state state = ansible_module.params_get("state") # Check parameters invalid = [] if state == "present": if len(names) != 1: ansible_module.fail_json( msg="Only one sudorule can be added at a time.") if action == "member": invalid = [ "description", "usercategory", "hostcategory", "cmdcategory", "runasusercategory", "runasgroupcategory", "order", "nomembers" ] else: if hostcategory == 'all' and any([host, hostgroup]): ansible_module.fail_json( msg="Hosts cannot be added when host category='all'") if usercategory == 'all' and any([user, group]): ansible_module.fail_json( msg="Users cannot be added when user category='all'") if cmdcategory == 'all' \ and any([allow_sudocmd, allow_sudocmdgroup]): ansible_module.fail_json( msg="Commands cannot be added when command category='all'") elif state == "absent": if len(names) < 1: ansible_module.fail_json(msg="No name given.") invalid = [ "description", "usercategory", "hostcategory", "cmdcategory", "runasusercategory", "runasgroupcategory", "nomembers", "order" ] if action == "sudorule": invalid.extend([ "host", "hostgroup", "user", "group", "runasuser", "runasgroup", "allow_sudocmd", "allow_sudocmdgroup", "deny_sudocmd", "deny_sudocmdgroup", "sudooption" ]) elif state in ["enabled", "disabled"]: if len(names) < 1: ansible_module.fail_json(msg="No name given.") if action == "member": ansible_module.fail_json( msg="Action member can not be used with states enabled and " "disabled") invalid = [ "description", "usercategory", "hostcategory", "cmdcategory", "runasusercategory", "runasgroupcategory", "nomembers", "nomembers", "host", "hostgroup", "user", "group", "allow_sudocmd", "allow_sudocmdgroup", "deny_sudocmd", "deny_sudocmdgroup", "runasuser", "runasgroup", "order", "sudooption" ] else: ansible_module.fail_json(msg="Invalid state '%s'" % state) ansible_module.params_fail_used_invalid(invalid, state, action) # Init changed = False exit_args = {} # Connect to IPA API with ansible_module.ipa_connect(): default_domain = api_get_domain() # Ensure host is not short hostname. if host: host = list( {ensure_fqdn(value.lower(), default_domain) for value in host}) commands = [] host_add, host_del = [], [] user_add, user_del = [], [] group_add, group_del = [], [] hostgroup_add, hostgroup_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 = [], [] for name in names: # Make sure sudorule exists res_find = find_sudorule(ansible_module, name) # Create command if state == "present": # Generate args args = gen_args(description, usercategory, hostcategory, cmdcategory, runasusercategory, runasgroupcategory, order, nomembers) if action == "sudorule": # Found the sudorule if res_find is not None: # Remove empty usercategory, hostcategory, # cmdcaterory, runasusercategory and hostcategory # 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"] # For all settings is args, check if there are # different settings in the find result. # If yes: modify if not compare_args_ipa(ansible_module, args, res_find): commands.append([name, "sudorule_mod", args]) else: commands.append([name, "sudorule_add", args]) # Set res_find to empty dict for next step 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', [])) 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', []))) 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 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", [])))) elif state == "absent": if action == "sudorule": if res_find is not None: commands.append([name, "sudorule_del", {}]) elif action == "member": 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 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", [])))) elif state == "enabled": if res_find is None: ansible_module.fail_json(msg="No sudorule '%s'" % name) # sudorule_enable is not failing on an enabled sudorule # Therefore it is needed to have a look at the ipaenabledflag # in res_find. if "ipaenabledflag" not in res_find or \ res_find["ipaenabledflag"][0] != "TRUE": commands.append([name, "sudorule_enable", {}]) elif state == "disabled": if res_find is None: ansible_module.fail_json(msg="No sudorule '%s'" % name) # sudorule_disable is not failing on an disabled sudorule # Therefore it is needed to have a look at the ipaenabledflag # in res_find. if "ipaenabledflag" not in res_find or \ res_find["ipaenabledflag"][0] != "FALSE": commands.append([name, "sudorule_disable", {}]) else: ansible_module.fail_json(msg="Unkown state '%s'" % state) # Manage members. # Manage hosts and hostgroups if host_add or hostgroup_add: commands.append([ name, "sudorule_add_host", { "host": host_add, "hostgroup": hostgroup_add, } ]) if host_del or hostgroup_del: commands.append([ name, "sudorule_remove_host", { "host": host_del, "hostgroup": hostgroup_del, } ]) # 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 } ]) # Execute commands changed = ansible_module.execute_ipa_commands( commands, fail_on_member_errors=True) # Done ansible_module.exit_json(changed=changed, **exit_args)
def main(): ansible_module = IPAAnsibleModule( argument_spec=dict( # general name=dict(type="list", aliases=["cn"], default=None, required=True), # present description=dict(type="str", default=None), nomembers=dict(required=False, type='bool', default=None), hbacsvc=dict(required=False, type='list', default=None), action=dict(type="str", default="hbacsvcgroup", choices=["member", "hbacsvcgroup"]), # state state=dict(type="str", default="present", choices=["present", "absent"]), ), supports_check_mode=True, ) ansible_module._ansible_debug = True # Get parameters # general names = ansible_module.params_get("name") # present description = ansible_module.params_get("description") nomembers = ansible_module.params_get("nomembers") hbacsvc = ansible_module.params_get_lowercase("hbacsvc") action = ansible_module.params_get("action") # state state = ansible_module.params_get("state") # Check parameters invalid = [] if state == "present": if len(names) != 1: ansible_module.fail_json( msg="Only one hbacsvcgroup can be added at a time.") if action == "member": invalid = ["description", "nomembers"] if state == "absent": if len(names) < 1: ansible_module.fail_json(msg="No name given.") invalid = ["description", "nomembers"] if action == "hbacsvcgroup": invalid.extend(["hbacsvc"]) ansible_module.params_fail_used_invalid(invalid, state, action) # Init changed = False exit_args = {} # Connect to IPA API with ansible_module.ipa_connect(): commands = [] for name in names: # Make sure hbacsvcgroup exists res_find = find_hbacsvcgroup(ansible_module, name) hbacsvc_add, hbacsvc_del = [], [] # Create command if state == "present": # Generate args args = gen_args(description, nomembers) if action == "hbacsvcgroup": # Found the hbacsvcgroup if res_find is not None: # For all settings is args, check if there are # different settings in the find result. # If yes: modify if not compare_args_ipa(ansible_module, args, res_find): commands.append([name, "hbacsvcgroup_mod", args]) else: commands.append([name, "hbacsvcgroup_add", args]) # Set res_find to empty dict for next step res_find = {} member_args = gen_member_args(hbacsvc) if not compare_args_ipa(ansible_module, member_args, res_find): # Generate addition and removal lists if hbacsvc is not None: hbacsvc_add, hbacsvc_del = gen_add_del_lists( hbacsvc, res_find.get("member_hbacsvc")) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No hbacsvcgroup '%s'" % name) # Ensure members are present if hbacsvc: hbacsvc_add = gen_add_list( hbacsvc, res_find.get("member_hbacsvc")) elif state == "absent": if action == "hbacsvcgroup": if res_find is not None: commands.append([name, "hbacsvcgroup_del", {}]) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No hbacsvcgroup '%s'" % name) # Ensure members are absent if hbacsvc: hbacsvc_del = gen_intersection_list( hbacsvc, res_find.get("member_hbacsvc")) else: ansible_module.fail_json(msg="Unkown state '%s'" % state) # Manage members if len(hbacsvc_add) > 0: commands.append([ name, "hbacsvcgroup_add_member", { "hbacsvc": hbacsvc_add } ]) # Remove members if len(hbacsvc_del) > 0: commands.append([ name, "hbacsvcgroup_remove_member", { "hbacsvc": hbacsvc_del } ]) # Execute commands changed = ansible_module.execute_ipa_commands(commands, result_handler) # Done ansible_module.exit_json(changed=changed, **exit_args)
def main(): ansible_module = IPAAnsibleModule( argument_spec=dict( # general name=dict(type="list", aliases=["cn"], default=None, required=True), # present description=dict(type="str", default=None), usercategory=dict(type="str", default=None, aliases=["usercat"], choices=["all", ""]), hostcategory=dict(type="str", default=None, aliases=["hostcat"], choices=["all", ""]), servicecategory=dict(type="str", default=None, aliases=["servicecat"], choices=["all", ""]), nomembers=dict(required=False, type='bool', default=None), host=dict(required=False, type='list', default=None), hostgroup=dict(required=False, type='list', default=None), hbacsvc=dict(required=False, type='list', default=None), hbacsvcgroup=dict(required=False, type='list', default=None), user=dict(required=False, type='list', default=None), group=dict(required=False, type='list', default=None), action=dict(type="str", default="hbacrule", choices=["member", "hbacrule"]), # state state=dict(type="str", default="present", choices=["present", "absent", "enabled", "disabled"]), ), supports_check_mode=True, ) ansible_module._ansible_debug = True # Get parameters # general names = ansible_module.params_get("name") # present description = ansible_module.params_get("description") usercategory = ansible_module.params_get("usercategory") hostcategory = ansible_module.params_get("hostcategory") servicecategory = ansible_module.params_get("servicecategory") nomembers = ansible_module.params_get("nomembers") host = ansible_module.params_get_lowercase("host") hostgroup = ansible_module.params_get_lowercase("hostgroup") hbacsvc = ansible_module.params_get_lowercase("hbacsvc") hbacsvcgroup = ansible_module.params_get_lowercase("hbacsvcgroup") user = ansible_module.params_get_lowercase("user") group = ansible_module.params_get_lowercase("group") action = ansible_module.params_get("action") # state state = ansible_module.params_get("state") # Check parameters invalid = [] if state == "present": if len(names) != 1: ansible_module.fail_json( msg="Only one hbacrule can be added at a time.") if action == "member": invalid = [ "description", "usercategory", "hostcategory", "servicecategory", "nomembers" ] else: if hostcategory == 'all' and any([host, hostgroup]): ansible_module.fail_json( msg="Hosts cannot be added when host category='all'") if usercategory == 'all' and any([user, group]): ansible_module.fail_json( msg="Users cannot be added when user category='all'") if servicecategory == 'all' and any([hbacsvc, hbacsvcgroup]): ansible_module.fail_json( msg="Services cannot be added when service category='all'") elif state == "absent": if len(names) < 1: ansible_module.fail_json(msg="No name given.") invalid = [ "description", "usercategory", "hostcategory", "servicecategory", "nomembers" ] if action == "hbacrule": invalid.extend([ "host", "hostgroup", "hbacsvc", "hbacsvcgroup", "user", "group" ]) elif state in ["enabled", "disabled"]: if len(names) < 1: ansible_module.fail_json(msg="No name given.") if action == "member": ansible_module.fail_json( msg="Action member can not be used with states enabled and " "disabled") invalid = [ "description", "usercategory", "hostcategory", "servicecategory", "nomembers", "host", "hostgroup", "hbacsvc", "hbacsvcgroup", "user", "group" ] else: ansible_module.fail_json(msg="Invalid state '%s'" % state) ansible_module.params_fail_used_invalid(invalid, state, action) # Init changed = False exit_args = {} # Connect to IPA API with ansible_module.ipa_connect(): # Get default domain default_domain = ansible_module.ipa_get_domain() # Ensure fqdn host names, use default domain for simple names if host is not None: _host = [ensure_fqdn(x, default_domain).lower() for x in host] host = _host commands = [] for name in names: # Make sure hbacrule exists res_find = find_hbacrule(ansible_module, name) host_add, host_del = [], [] hostgroup_add, hostgroup_del = [], [] hbacsvc_add, hbacsvc_del = [], [] hbacsvcgroup_add, hbacsvcgroup_del = [], [] user_add, user_del = [], [] group_add, group_del = [], [] # Create command if state == "present": # Generate args args = gen_args(description, usercategory, hostcategory, servicecategory, nomembers) if action == "hbacrule": # Found the hbacrule if res_find is not None: # Remove usercategory, hostcategory and # servicecategory from args if "" and category # not in res_find (needed for idempotency) 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 "servicecategory" in args and \ args["servicecategory"] == "" and \ "servicecategory" not in res_find: del args["servicecategory"] # For all settings is args, check if there are # different settings in the find result. # If yes: modify if not compare_args_ipa(ansible_module, args, res_find): commands.append([name, "hbacrule_mod", args]) else: commands.append([name, "hbacrule_add", args]) # Set res_find to empty dict for next step res_find = {} # Generate addition and removal lists if host is not None: host_add, host_del = gen_add_del_lists( host, res_find.get("memberhost_host")) if hostgroup is not None: hostgroup_add, hostgroup_del = gen_add_del_lists( hostgroup, res_find.get("memberhost_hostgroup")) if hbacsvc is not None: hbacsvc_add, hbacsvc_del = gen_add_del_lists( hbacsvc, res_find.get("memberservice_hbacsvc")) if hbacsvcgroup is not None: hbacsvcgroup_add, hbacsvcgroup_del = gen_add_del_lists( hbacsvcgroup, res_find.get("memberservice_hbacsvcgroup")) if user is not None: user_add, user_del = gen_add_del_lists( user, res_find.get("memberuser_user")) if group is not None: group_add, group_del = gen_add_del_lists( group, res_find.get("memberuser_group")) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No hbacrule '%s'" % name) # Generate add lists for host, hostgroup and # res_find to only try to add hosts and hostgroups # that not in hbacrule already if host: host_add = gen_add_list( host, res_find.get("memberhost_host")) if hostgroup: hostgroup_add = gen_add_list( hostgroup, res_find.get("memberhost_hostgroup")) # Generate add lists for hbacsvc, hbacsvcgroup and # res_find to only try to add hbacsvcs and hbacsvcgroups # that not in hbacrule already if hbacsvc: hbacsvc_add = gen_add_list( hbacsvc, res_find.get("memberservice_hbacsvc")) if hbacsvcgroup: hbacsvcgroup_add = gen_add_list( hbacsvcgroup, res_find.get("memberservice_hbacsvcgroup")) # Generate add lists for user, group and # res_find to only try to add users and groups # that not in hbacrule already if user: user_add = gen_add_list( user, res_find.get("memberuser_user")) if group: group_add = gen_add_list( group, res_find.get("memberuser_group")) elif state == "absent": if action == "hbacrule": if res_find is not None: commands.append([name, "hbacrule_del", {}]) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No hbacrule '%s'" % name) # Generate intersection lists for host, hostgroup and # res_find to only try to remove hosts and hostgroups # that are in hbacrule if host: if "memberhost_host" in res_find: host_del = gen_intersection_list( host, res_find["memberhost_host"]) if hostgroup: if "memberhost_hostgroup" in res_find: hostgroup_del = gen_intersection_list( hostgroup, res_find["memberhost_hostgroup"]) # Generate intersection lists for hbacsvc, hbacsvcgroup # and res_find to only try to remove hbacsvcs and # hbacsvcgroups that are in hbacrule if hbacsvc: if "memberservice_hbacsvc" in res_find: hbacsvc_del = gen_intersection_list( hbacsvc, res_find["memberservice_hbacsvc"]) if hbacsvcgroup: if "memberservice_hbacsvcgroup" in res_find: hbacsvcgroup_del = gen_intersection_list( hbacsvcgroup, res_find["memberservice_hbacsvcgroup"]) # Generate intersection lists for user, group and # res_find to only try to remove users and groups # that are in hbacrule if user: if "memberuser_user" in res_find: user_del = gen_intersection_list( user, res_find["memberuser_user"]) if group: if "memberuser_group" in res_find: group_del = gen_intersection_list( group, res_find["memberuser_group"]) elif state == "enabled": if res_find is None: ansible_module.fail_json(msg="No hbacrule '%s'" % name) # hbacrule_enable is not failing on an enabled hbacrule # Therefore it is needed to have a look at the ipaenabledflag # in res_find. if "ipaenabledflag" not in res_find or \ res_find["ipaenabledflag"][0] != "TRUE": commands.append([name, "hbacrule_enable", {}]) elif state == "disabled": if res_find is None: ansible_module.fail_json(msg="No hbacrule '%s'" % name) # hbacrule_disable is not failing on an disabled hbacrule # Therefore it is needed to have a look at the ipaenabledflag # in res_find. if "ipaenabledflag" not in res_find or \ res_find["ipaenabledflag"][0] != "FALSE": commands.append([name, "hbacrule_disable", {}]) else: ansible_module.fail_json(msg="Unkown state '%s'" % state) # Manage HBAC rule members. # Add hosts and hostgroups if len(host_add) > 0 or len(hostgroup_add) > 0: commands.append([ name, "hbacrule_add_host", { "host": host_add, "hostgroup": hostgroup_add, } ]) # Remove hosts and hostgroups if len(host_del) > 0 or len(hostgroup_del) > 0: commands.append([ name, "hbacrule_remove_host", { "host": host_del, "hostgroup": hostgroup_del, } ]) # Add hbacsvcs and hbacsvcgroups if len(hbacsvc_add) > 0 or len(hbacsvcgroup_add) > 0: commands.append([ name, "hbacrule_add_service", { "hbacsvc": hbacsvc_add, "hbacsvcgroup": hbacsvcgroup_add, } ]) # Remove hbacsvcs and hbacsvcgroups if len(hbacsvc_del) > 0 or len(hbacsvcgroup_del) > 0: commands.append([ name, "hbacrule_remove_service", { "hbacsvc": hbacsvc_del, "hbacsvcgroup": hbacsvcgroup_del, } ]) # Add users and groups if len(user_add) > 0 or len(group_add) > 0: commands.append([ name, "hbacrule_add_user", { "user": user_add, "group": group_add, } ]) # Remove users and groups if len(user_del) > 0 or len(group_del) > 0: commands.append([ name, "hbacrule_remove_user", { "user": user_del, "group": group_del, } ]) # Execute commands changed = ansible_module.execute_ipa_commands( commands, fail_on_member_errors=True) # Done ansible_module.exit_json(changed=changed, **exit_args)
def main(): ansible_module = IPAAnsibleModule( argument_spec=dict( # general name=dict(type="list", aliases=["cn"], default=None, required=True), # present description=dict(type="str", default=None), gid=dict(type="int", aliases=["gidnumber"], default=None), nonposix=dict(required=False, type='bool', default=None), external=dict(required=False, type='bool', default=None), posix=dict(required=False, type='bool', default=None), nomembers=dict(required=False, type='bool', default=None), user=dict(required=False, type='list', default=None), group=dict(required=False, type='list', default=None), service=dict(required=False, type='list', default=None), membermanager_user=dict(required=False, type='list', default=None), membermanager_group=dict(required=False, type='list', default=None), externalmember=dict( required=False, type='list', default=None, aliases=["ipaexternalmember", "external_member"]), action=dict(type="str", default="group", choices=["member", "group"]), # state state=dict(type="str", default="present", choices=["present", "absent"]), ), # It does not make sense to set posix, nonposix or external at the # same time mutually_exclusive=[['posix', 'nonposix', 'external']], supports_check_mode=True, ) ansible_module._ansible_debug = True # Get parameters # general names = ansible_module.params_get("name") # present description = ansible_module.params_get("description") gid = ansible_module.params_get("gid") nonposix = ansible_module.params_get("nonposix") external = ansible_module.params_get("external") posix = ansible_module.params_get("posix") nomembers = ansible_module.params_get("nomembers") user = ansible_module.params_get("user") group = ansible_module.params_get("group") # Services are not case sensitive service = ansible_module.params_get_lowercase("service") membermanager_user = ansible_module.params_get("membermanager_user") membermanager_group = ansible_module.params_get("membermanager_group") externalmember = ansible_module.params_get("externalmember") action = ansible_module.params_get("action") # state state = ansible_module.params_get("state") # Check parameters invalid = [] if state == "present": if len(names) != 1: ansible_module.fail_json( msg="Only one group can be added at a time.") if action == "member": invalid = [ "description", "gid", "posix", "nonposix", "external", "nomembers" ] if state == "absent": if len(names) < 1: ansible_module.fail_json(msg="No name given.") invalid = [ "description", "gid", "posix", "nonposix", "external", "nomembers" ] if action == "group": invalid.extend(["user", "group", "service", "externalmember"]) ansible_module.params_fail_used_invalid(invalid, state, action) if external is False: ansible_module.fail_json(msg="group can not be non-external") # Init changed = False exit_args = {} # If nonposix is used, set posix as not nonposix if nonposix is not None: posix = not nonposix # Connect to IPA API with ansible_module.ipa_connect(): has_add_member_service = ansible_module.ipa_command_param_exists( "group_add_member", "service") if service is not None and not has_add_member_service: ansible_module.fail_json( msg="Managing a service as part of a group is not supported " "by your IPA version") has_add_membermanager = ansible_module.ipa_command_exists( "group_add_member_manager") if ((membermanager_user is not None or membermanager_group is not None) and not has_add_membermanager): ansible_module.fail_json( msg="Managing a membermanager user or group is not supported " "by your IPA version") commands = [] for name in names: # Make sure group exists res_find = find_group(ansible_module, name) user_add, user_del = [], [] group_add, group_del = [], [] service_add, service_del = [], [] externalmember_add, externalmember_del = [], [] membermanager_user_add, membermanager_user_del = [], [] membermanager_group_add, membermanager_group_del = [], [] # Create command if state == "present": # Can't change an existing posix group check_objectclass_args(ansible_module, res_find, posix, external) # Generate args args = gen_args(description, gid, nomembers) if action == "group": # Found the group if res_find is not None: # For all settings in args, check if there are # different settings in the find result. # If yes: modify # Also if it is a modification from nonposix to posix # or nonposix to external. if not compare_args_ipa( ansible_module, args, res_find) or ( not is_posix_group(res_find) and not is_external_group(res_find) and (posix or external)): if posix: args['posix'] = True if external: args['external'] = True commands.append([name, "group_mod", args]) else: if posix is not None and not posix: args['nonposix'] = True if external: args['external'] = True commands.append([name, "group_add", args]) # Set res_find dict for next step res_find = {} # if we just created/modified the group, update res_find res_find.setdefault("objectclass", []) if external and not is_external_group(res_find): res_find["objectclass"].append("ipaexternalgroup") if posix and not is_posix_group(res_find): res_find["objectclass"].append("posixgroup") member_args = gen_member_args(user, group, service, externalmember) if not compare_args_ipa(ansible_module, member_args, res_find): # Generate addition and removal lists 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")) service_add, service_del = gen_add_del_lists( service, res_find.get("member_service")) (externalmember_add, externalmember_del) = gen_add_del_lists( externalmember, res_find.get("member_external")) membermanager_user_add, membermanager_user_del = \ gen_add_del_lists( membermanager_user, res_find.get("membermanager_user") ) membermanager_group_add, membermanager_group_del = \ gen_add_del_lists( membermanager_group, res_find.get("membermanager_group") ) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No group '%s'" % name) # Reduce add lists for member_user, member_group, # member_service and member_external to new entries # only that are not in res_find. user_add = gen_add_list(user, res_find.get("member_user")) group_add = gen_add_list(group, res_find.get("member_group")) service_add = gen_add_list(service, res_find.get("member_service")) externalmember_add = gen_add_list( externalmember, res_find.get("member_external")) membermanager_user_add = gen_add_list( membermanager_user, res_find.get("membermanager_user")) membermanager_group_add = gen_add_list( membermanager_group, res_find.get("membermanager_group")) elif state == "absent": if action == "group": if res_find is not None: commands.append([name, "group_del", {}]) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No group '%s'" % name) if not is_external_group(res_find) and externalmember: ansible_module.fail_json( msg="Cannot add external members to a " "non-external group.") user_del = gen_intersection_list( user, res_find.get("member_user")) group_del = gen_intersection_list( group, res_find.get("member_group")) service_del = gen_intersection_list( service, res_find.get("member_service")) externalmember_del = gen_intersection_list( externalmember, res_find.get("member_external")) membermanager_user_del = gen_intersection_list( membermanager_user, res_find.get("membermanager_user")) membermanager_group_del = gen_intersection_list( membermanager_group, res_find.get("membermanager_group")) else: ansible_module.fail_json(msg="Unkown state '%s'" % state) # manage members # setup member args for add/remove members. add_member_args = { "user": user_add, "group": group_add, } del_member_args = { "user": user_del, "group": group_del, } if has_add_member_service: add_member_args["service"] = service_add del_member_args["service"] = service_del if is_external_group(res_find): add_member_args["ipaexternalmember"] = \ externalmember_add del_member_args["ipaexternalmember"] = \ externalmember_del elif externalmember or external: ansible_module.fail_json( msg="Cannot add external members to a " "non-external group.") # Add members add_members = any( [user_add, group_add, service_add, externalmember_add]) if add_members: commands.append([name, "group_add_member", add_member_args]) # Remove members remove_members = any( [user_del, group_del, service_del, externalmember_del]) if remove_members: commands.append([name, "group_remove_member", del_member_args]) # manage membermanager members if has_add_membermanager: # Add membermanager users and groups if any([membermanager_user_add, membermanager_group_add]): commands.append([ name, "group_add_member_manager", { "user": membermanager_user_add, "group": membermanager_group_add, } ]) # Remove member manager if any([membermanager_user_del, membermanager_group_del]): commands.append([ name, "group_remove_member_manager", { "user": membermanager_user_del, "group": membermanager_group_del, } ]) # Execute commands changed = ansible_module.execute_ipa_commands( commands, fail_on_member_errors=True) # Done ansible_module.exit_json(changed=changed, **exit_args)