def main(): ansible_module = AnsibleModule( argument_spec=dict( # general ipaadmin_principal=dict(type="str", default="admin"), ipaadmin_password=dict(type="str", required=False, no_log=True), 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), host=dict(required=False, type='list', default=None), hostgroup=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), rename=dict(required=False, type='str', default=None, aliases=["new_name"]), action=dict(type="str", default="hostgroup", choices=["member", "hostgroup"]), # state state=dict(type="str", default="present", choices=["present", "absent", "renamed"]), ), supports_check_mode=True, ) ansible_module._ansible_debug = True # Get parameters # general ipaadmin_principal = module_params_get(ansible_module, "ipaadmin_principal") ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password") names = module_params_get(ansible_module, "name") # present description = module_params_get(ansible_module, "description") nomembers = module_params_get(ansible_module, "nomembers") host = module_params_get(ansible_module, "host") hostgroup = module_params_get(ansible_module, "hostgroup") membermanager_user = module_params_get(ansible_module, "membermanager_user") membermanager_group = module_params_get(ansible_module, "membermanager_group") rename = module_params_get(ansible_module, "rename") action = module_params_get(ansible_module, "action") # state state = module_params_get(ansible_module, "state") # Check parameters if state == "present": if len(names) != 1: ansible_module.fail_json( msg="Only one hostgroup can be added at a time.") invalid = ["rename"] if action == "member": invalid.extend(["description", "nomembers"]) for x in invalid: if vars()[x] is not None: ansible_module.fail_json( msg="Argument '%s' can not be used with action " "'%s'" % (x, action)) if state == "renamed": if len(names) != 1: ansible_module.fail_json( msg="Only one hostgroup can be added at a time.") if action == "member": ansible_module.fail_json( msg="Action '%s' can not be used with state '%s'" % (action, state)) invalid = [ "description", "nomembers", "host", "hostgroup", "membermanager_user", "membermanager_group" ] for x in invalid: if vars()[x] is not None: ansible_module.fail_json( msg="Argument '%s' can not be used with state '%s'" % (x, state)) if state == "absent": if len(names) < 1: ansible_module.fail_json(msg="No name given.") invalid = ["description", "nomembers", "rename"] if action == "hostgroup": invalid.extend(["host", "hostgroup"]) for x in invalid: if vars()[x] is not None: ansible_module.fail_json( msg="Argument '%s' can not be used with state '%s'" % (x, state)) # Init changed = False exit_args = {} ccache_dir = None ccache_name = None try: if not valid_creds(ansible_module, ipaadmin_principal): ccache_dir, ccache_name = temp_kinit(ipaadmin_principal, ipaadmin_password) api_connect() has_add_membermanager = api_check_command( "hostgroup_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") has_mod_rename = api_check_param("hostgroup_mod", "rename") if not has_mod_rename and rename is not None: ansible_module.fail_json( msg="Renaming hostgroups is not supported by your IPA version") commands = [] for name in names: # Make sure hostgroup exists res_find = find_hostgroup(ansible_module, name) # Create command if state == "present": # Generate args args = gen_args(description, nomembers, rename) if action == "hostgroup": # Found the hostgroup 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, "hostgroup_mod", args]) else: commands.append([name, "hostgroup_add", args]) # Set res_find to empty dict for next step res_find = {} member_args = gen_member_args(host, hostgroup) if not compare_args_ipa(ansible_module, member_args, res_find): # Generate addition and removal lists 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")) # Add members if len(host_add) > 0 or len(hostgroup_add) > 0: commands.append([ name, "hostgroup_add_member", { "host": host_add, "hostgroup": hostgroup_add, } ]) # Remove members if len(host_del) > 0 or len(hostgroup_del) > 0: commands.append([ name, "hostgroup_remove_member", { "host": host_del, "hostgroup": hostgroup_del, } ]) 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") ) if has_add_membermanager: # Add membermanager users and groups if len(membermanager_user_add) > 0 or \ len(membermanager_group_add) > 0: commands.append([ name, "hostgroup_add_member_manager", { "user": membermanager_user_add, "group": membermanager_group_add, } ]) # Remove member manager if len(membermanager_user_del) > 0 or \ len(membermanager_group_del) > 0: commands.append([ name, "hostgroup_remove_member_manager", { "user": membermanager_user_del, "group": membermanager_group_del, } ]) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No hostgroup '%s'" % name) # Ensure members are present commands.append([ name, "hostgroup_add_member", { "host": host, "hostgroup": hostgroup, } ]) if has_add_membermanager: # Add membermanager users and groups if membermanager_user is not None or \ membermanager_group is not None: commands.append([ name, "hostgroup_add_member_manager", { "user": membermanager_user, "group": membermanager_group, } ]) elif state == "renamed": if res_find is not None: if rename != name: commands.append( [name, "hostgroup_mod", { "rename": rename }]) else: # If a hostgroup with the desired name exists, do nothing. new_find = find_hostgroup(ansible_module, rename) if new_find is None: # Fail only if the either hostsgroups do not exist. ansible_module.fail_json( msg="Attribute `rename` can not be used, unless " "hostgroup exists.") elif state == "absent": if action == "hostgroup": if res_find is not None: commands.append([name, "hostgroup_del", {}]) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No hostgroup '%s'" % name) # Ensure members are absent commands.append([ name, "hostgroup_remove_member", { "host": host, "hostgroup": hostgroup, } ]) if has_add_membermanager: # Remove membermanager users and groups if membermanager_user is not None or \ membermanager_group is not None: commands.append([ name, "hostgroup_remove_member_manager", { "user": membermanager_user, "group": membermanager_group, } ]) else: ansible_module.fail_json(msg="Unkown state '%s'" % state) # Check mode exit if ansible_module.check_mode: ansible_module.exit_json(changed=len(commands) > 0, **exit_args) # Execute commands for name, command, args in commands: try: result = api_command(ansible_module, command, name, args) if "completed" in result: if result["completed"] > 0: changed = True else: changed = True except Exception as e: ansible_module.fail_json(msg="%s: %s: %s" % (command, name, str(e))) # Get all errors # All "already a member" and "not a member" failures in the # result are ignored. All others are reported. errors = [] for failed_item in result.get("failed", []): failed = result["failed"][failed_item] for member_type in failed: for member, failure in failed[member_type]: if "already a member" in failure \ or "not a member" in failure: continue errors.append("%s: %s %s: %s" % (command, member_type, member, failure)) if len(errors) > 0: ansible_module.fail_json(msg=", ".join(errors)) except Exception as e: ansible_module.fail_json(msg=str(e)) finally: temp_kdestroy(ccache_dir, ccache_name) # Done ansible_module.exit_json(changed=changed, **exit_args)
def main(): ansible_module = init_ansible_module() # Get parameters # general ipaadmin_principal = module_params_get(ansible_module, "ipaadmin_principal") ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password") names = module_params_get(ansible_module, "name") # service attributes principal = module_params_get(ansible_module, "principal") certificate = module_params_get(ansible_module, "certificate") pac_type = module_params_get(ansible_module, "pac_type") auth_ind = module_params_get(ansible_module, "auth_ind") skip_host_check = module_params_get(ansible_module, "skip_host_check") force = module_params_get(ansible_module, "force") requires_pre_auth = module_params_get(ansible_module, "requires_pre_auth") ok_as_delegate = module_params_get(ansible_module, "ok_as_delegate") ok_to_auth_as_delegate = module_params_get(ansible_module, "ok_to_auth_as_delegate") smb = module_params_get(ansible_module, "smb") netbiosname = module_params_get(ansible_module, "netbiosname") host = module_params_get(ansible_module, "host") allow_create_keytab_user = module_params_get(ansible_module, "allow_create_keytab_user") allow_create_keytab_group = module_params_get(ansible_module, "allow_create_keytab_group") allow_create_keytab_host = module_params_get(ansible_module, "allow_create_keytab_host") allow_create_keytab_hostgroup = module_params_get( ansible_module, "allow_create_keytab_hostgroup") allow_retrieve_keytab_user = module_params_get( ansible_module, "allow_retrieve_keytab_user") allow_retrieve_keytab_group = module_params_get( ansible_module, "allow_retrieve_keytab_group") allow_retrieve_keytab_host = module_params_get( ansible_module, "allow_retrieve_keytab_host") allow_retrieve_keytab_hostgroup = module_params_get( ansible_module, "allow_retrieve_keytab_hostgroup") delete_continue = module_params_get(ansible_module, "delete_continue") # action action = module_params_get(ansible_module, "action") # state state = module_params_get(ansible_module, "state") # check parameters check_parameters(ansible_module, state, action, names, vars()) # Init changed = False exit_args = {} ccache_dir = None ccache_name = None try: if not valid_creds(ansible_module, ipaadmin_principal): ccache_dir, ccache_name = temp_kinit(ipaadmin_principal, ipaadmin_password) api_connect() has_skip_host_check = api_check_param("service_add", "skip_host_check") if skip_host_check and not has_skip_host_check: ansible_module.fail_json( msg="Skipping host check is not supported by your IPA version") commands = [] for name in names: res_find = find_service(ansible_module, name, netbiosname) if state == "present": # if service exists, 'smb' cannot be used. if action == "service": args = gen_args(pac_type, auth_ind, skip_host_check, force, requires_pre_auth, ok_as_delegate, ok_to_auth_as_delegate) if not has_skip_host_check and 'skip_host_check' in args: del args['skip_host_check'] if res_find is None: if smb: if netbiosname is not None: args['ipantflatname'] = netbiosname commands.append([name, 'service_add_smb', args]) else: commands.append([name, 'service_add', args]) certificate_add = certificate or [] certificate_del = [] host_add = host or [] 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 = [] else: for remove in ['skip_host_check', 'force']: if remove in args: del args[remove] if not compare_args_ipa(ansible_module, args, res_find): commands.append([name, "service_mod", args]) certificate_add, certificate_del = gen_add_del_lists( certificate, res_find.get("usercertificate")) host_add, host_del = gen_add_del_lists( host, res_find.get('managedby_host', [])) principal_add, principal_del = gen_add_del_lists( principal, res_find.get("principal")) (allow_create_keytab_user_add, allow_create_keytab_user_del) = \ gen_add_del_lists( allow_create_keytab_user, res_find.get( 'ipaallowedtoperform_write_keys_user', [])) (allow_retrieve_keytab_user_add, allow_retrieve_keytab_user_del) = \ gen_add_del_lists( allow_retrieve_keytab_user, res_find.get( 'ipaallowedtoperform_read_keys_user', [])) (allow_create_keytab_group_add, allow_create_keytab_group_del) = \ gen_add_del_lists( allow_create_keytab_group, res_find.get( 'ipaallowedtoperform_write_keys_group', [])) (allow_retrieve_keytab_group_add, allow_retrieve_keytab_group_del) = \ gen_add_del_lists( allow_retrieve_keytab_group, res_find.get( 'ipaallowedtoperform_read_keys_group', [])) (allow_create_keytab_host_add, allow_create_keytab_host_del) = \ gen_add_del_lists( allow_create_keytab_host, res_find.get( 'ipaallowedtoperform_write_keys_host', [])) (allow_retrieve_keytab_host_add, allow_retrieve_keytab_host_del) = \ gen_add_del_lists( allow_retrieve_keytab_host, res_find.get( 'ipaallowedtoperform_read_keys_host', [])) (allow_create_keytab_hostgroup_add, allow_create_keytab_hostgroup_del) = \ gen_add_del_lists( allow_create_keytab_hostgroup, res_find.get( 'ipaallowedtoperform_write_keys_hostgroup', [])) (allow_retrieve_keytab_hostgroup_add, allow_retrieve_keytab_hostgroup_del) = \ gen_add_del_lists( allow_retrieve_keytab_hostgroup, res_find.get( 'ipaallowedtoperform_read_keys_hostgroup', [])) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No service '%s'" % name) existing = res_find.get('usercertificate', []) if certificate is None: certificate_add = [] else: certificate_add = [ c for c in certificate if c not in existing ] certificate_del = [] host_add = host or [] 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 = [] # Add principals for _principal in principal_add: commands.append([ name, "service_add_principal", { "krbprincipalname": _principal, } ]) # Remove principals for _principal in principal_del: commands.append([ name, "service_remove_principal", { "krbprincipalname": _principal, } ]) for _certificate in certificate_add: commands.append([ name, "service_add_cert", { "usercertificate": _certificate, } ]) # Remove certificates for _certificate in certificate_del: commands.append([ name, "service_remove_cert", { "usercertificate": _certificate, } ]) # Add hosts. if host is not None and len(host) > 0 and len(host_add) > 0: commands.append( [name, "service_add_host", { "host": host_add }]) # Remove hosts if host is not None and len(host) > 0 and len(host_del) > 0: commands.append( [name, "service_remove_host", { "host": host_del }]) # Allow create keytab if len(allow_create_keytab_user_add) > 0 or \ len(allow_create_keytab_group_add) > 0 or \ len(allow_create_keytab_host_add) > 0 or \ len(allow_create_keytab_hostgroup_add) > 0: commands.append([ name, "service_allow_create_keytab", { 'user': allow_create_keytab_user_add, 'group': allow_create_keytab_group_add, 'host': allow_create_keytab_host_add, 'hostgroup': allow_create_keytab_hostgroup_add } ]) # Disallow create keytab if len(allow_create_keytab_user_del) > 0 or \ len(allow_create_keytab_group_del) > 0 or \ len(allow_create_keytab_host_del) > 0 or \ len(allow_create_keytab_hostgroup_del) > 0: commands.append([ name, "service_disallow_create_keytab", { 'user': allow_create_keytab_user_del, 'group': allow_create_keytab_group_del, 'host': allow_create_keytab_host_del, 'hostgroup': allow_create_keytab_hostgroup_del } ]) # Allow retrieve keytab if len(allow_retrieve_keytab_user_add) > 0 or \ len(allow_retrieve_keytab_group_add) > 0 or \ len(allow_retrieve_keytab_host_add) > 0 or \ len(allow_retrieve_keytab_hostgroup_add) > 0: commands.append([ name, "service_allow_retrieve_keytab", { 'user': allow_retrieve_keytab_user_add, 'group': allow_retrieve_keytab_group_add, 'host': allow_retrieve_keytab_host_add, 'hostgroup': allow_retrieve_keytab_hostgroup_add } ]) # Disllow retrieve keytab if len(allow_retrieve_keytab_user_del) > 0 or \ len(allow_retrieve_keytab_group_del) > 0 or \ len(allow_retrieve_keytab_host_del) > 0 or \ len(allow_retrieve_keytab_hostgroup_del) > 0: commands.append([ name, "service_disallow_retrieve_keytab", { 'user': allow_retrieve_keytab_user_del, 'group': allow_retrieve_keytab_group_del, 'host': allow_retrieve_keytab_host_del, 'hostgroup': allow_retrieve_keytab_hostgroup_del } ]) elif state == "absent": if action == "service": if res_find is not None: args = {'continue': True if delete_continue else False} commands.append([name, 'service_del', args]) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No service '%s'" % name) # Remove principals if principal is not None: for _principal in principal: commands.append([ name, "service_remove_principal", { "krbprincipalname": _principal, } ]) # Remove certificates if certificate is not None: existing = res_find.get('usercertificate', []) for _certificate in certificate: if _certificate in existing: commands.append([ name, "service_remove_cert", { "usercertificate": _certificate, } ]) # Add hosts if host is not None: commands.append( [name, "service_remove_host", { "host": host }]) # Allow create keytab if allow_create_keytab_user is not None or \ allow_create_keytab_group is not None or \ allow_create_keytab_host is not None or \ allow_create_keytab_hostgroup is not None: commands.append([ name, "service_disallow_create_keytab", { 'user': allow_create_keytab_user, 'group': allow_create_keytab_group, 'host': allow_create_keytab_host, 'hostgroup': allow_create_keytab_hostgroup } ]) # Allow retriev keytab if allow_retrieve_keytab_user is not None or \ allow_retrieve_keytab_group is not None or \ allow_retrieve_keytab_host is not None or \ allow_retrieve_keytab_hostgroup is not None: commands.append([ name, "service_disallow_retrieve_keytab", { 'user': allow_retrieve_keytab_user, 'group': allow_retrieve_keytab_group, 'host': allow_retrieve_keytab_host, 'hostgroup': allow_retrieve_keytab_hostgroup } ]) elif state == "disabled": if action == "service": if res_find is not None: has_cert = bool(res_find.get('usercertificate')) has_keytab = res_find.get('has_keytab', False) if has_cert or has_keytab: commands.append([name, 'service_disable', {}]) else: ansible_module.fail_json( msg="Invalid action '%s' for state '%s'" % (action, state)) else: ansible_module.fail_json(msg="Unkown state '%s'" % state) # Check mode exit if ansible_module.check_mode: ansible_module.exit_json(changed=len(commands) > 0, **exit_args) # Execute commands errors = [] for name, command, args in commands: try: result = api_command(ansible_module, command, name, args) if "completed" in result: if result["completed"] > 0: changed = True else: changed = True except Exception as ex: ansible_module.fail_json(msg="%s: %s: %s" % (command, name, str(ex))) # Get all errors # All "already a member" and "not a member" failures in the # result are ignored. All others are reported. if "failed" in result and len(result["failed"]) > 0: for item in result["failed"]: failed_item = result["failed"][item] for member_type in failed_item: for member, failure in failed_item[member_type]: if "already a member" in failure \ or "not a member" in failure: continue errors.append( "%s: %s %s: %s" % (command, member_type, member, failure)) if len(errors) > 0: ansible_module.fail_json(msg=", ".join(errors)) except Exception as ex: ansible_module.fail_json(msg=str(ex)) finally: temp_kdestroy(ccache_dir, ccache_name) # Done ansible_module.exit_json(changed=changed, **exit_args)
def main(): ansible_module = AnsibleModule( argument_spec=dict( # general ipaadmin_principal=dict(type="str", default="admin"), ipaadmin_password=dict(type="str", required=False, no_log=True), 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), 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), action=dict(type="str", default="group", choices=["member", "group"]), # state state=dict(type="str", default="present", choices=["present", "absent"]), ), supports_check_mode=True, ) ansible_module._ansible_debug = True # Get parameters # general ipaadmin_principal = module_params_get( ansible_module, "ipaadmin_principal", ) ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password") names = module_params_get(ansible_module, "name") # present description = module_params_get(ansible_module, "description") gid = module_params_get(ansible_module, "gid") nonposix = module_params_get(ansible_module, "nonposix") external = module_params_get(ansible_module, "external") nomembers = module_params_get(ansible_module, "nomembers") user = module_params_get(ansible_module, "user") group = module_params_get(ansible_module, "group") service = module_params_get(ansible_module, "service") action = module_params_get(ansible_module, "action") # state state = module_params_get(ansible_module, "state") # Check parameters 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", "nonposix", "external", "nomembers" ] for x in invalid: if vars()[x] is not None: ansible_module.fail_json( msg="Argument '%s' can not be used with action " "'%s'" % (x, action)) if state == "absent": if len(names) < 1: ansible_module.fail_json(msg="No name given.") invalid = ["description", "gid", "nonposix", "external", "nomembers"] if action == "group": invalid.extend(["user", "group", "service"]) for x in invalid: if vars()[x] is not None: ansible_module.fail_json( msg="Argument '%s' can not be used with state '%s'" % (x, state)) # Init changed = False exit_args = {} ccache_dir = None ccache_name = None try: if not valid_creds(ansible_module, ipaadmin_principal): ccache_dir, ccache_name = temp_kinit(ipaadmin_principal, ipaadmin_password) api_connect() has_add_member_service = api_check_param("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") commands = [] for name in names: # Make sure group exists res_find = find_group(ansible_module, name) # Create command if state == "present": # Generate args args = gen_args(description, gid, nonposix, external, nomembers) if action == "group": # Found the group 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, "group_mod", args]) else: commands.append([name, "group_add", args]) # Set res_find to empty dict for next step res_find = {} member_args = gen_member_args(user, group, service) if not compare_args_ipa(ansible_module, member_args, res_find): # Generate addition and removal lists 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 [])) service_add = list( set(service or []) - set(res_find.get("member_service", []))) service_del = list( set(res_find.get("member_service", [])) - set(service or [])) if has_add_member_service: # Add members if len(user_add) > 0 or len(group_add) > 0 or \ len(service_add) > 0: commands.append([ name, "group_add_member", { "user": user_add, "group": group_add, "service": service_add, } ]) # Remove members if len(user_del) > 0 or len(group_del) > 0 or \ len(service_del) > 0: commands.append([ name, "group_remove_member", { "user": user_del, "group": group_del, "service": service_del, } ]) else: # Add members if len(user_add) > 0 or len(group_add) > 0: commands.append([ name, "group_add_member", { "user": user_add, "group": group_add, } ]) # Remove members if len(user_del) > 0 or len(group_del) > 0: commands.append([ name, "group_remove_member", { "user": user_del, "group": group_del, } ]) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No group '%s'" % name) if has_add_member_service: commands.append([ name, "group_add_member", { "user": user, "group": group, "service": service, } ]) else: commands.append([ name, "group_add_member", { "user": user, "group": 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) commands.append([ name, "group_remove_member", { "user": user, "group": group, "service": service, } ]) else: ansible_module.fail_json(msg="Unkown state '%s'" % state) # Execute commands for name, command, args in commands: try: result = api_command(ansible_module, command, name, args) if "completed" in result: if result["completed"] > 0: changed = True else: changed = True except Exception as e: ansible_module.fail_json(msg="%s: %s: %s" % (command, name, str(e))) # Get all errors # All "already a member" and "not a member" failures in the # result are ignored. All others are reported. errors = [] if "failed" in result and len(result["failed"]) > 0: for item in result["failed"]: failed_item = result["failed"][item] for member_type in failed_item: for member, failure in failed_item[member_type]: if "already a member" in failure \ or "not a member" in failure: continue errors.append( "%s: %s %s: %s" % (command, member_type, member, failure)) if len(errors) > 0: ansible_module.fail_json(msg=", ".join(errors)) except Exception as e: ansible_module.fail_json(msg=str(e)) finally: temp_kdestroy(ccache_dir, ccache_name) # Done ansible_module.exit_json(changed=changed, **exit_args)
def main(): ansible_module = AnsibleModule( argument_spec=dict( # general ipaadmin_principal=dict(type="str", default="admin"), ipaadmin_password=dict(type="str", required=False, no_log=True), 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"]), ), mutually_exclusive=[['posix', 'nonposix']], supports_check_mode=True, ) ansible_module._ansible_debug = True # Get parameters # general ipaadmin_principal = module_params_get( ansible_module, "ipaadmin_principal", ) ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password") names = module_params_get(ansible_module, "name") # present description = module_params_get(ansible_module, "description") gid = module_params_get(ansible_module, "gid") nonposix = module_params_get(ansible_module, "nonposix") external = module_params_get(ansible_module, "external") posix = module_params_get(ansible_module, "posix") nomembers = module_params_get(ansible_module, "nomembers") user = module_params_get(ansible_module, "user") group = module_params_get(ansible_module, "group") service = module_params_get(ansible_module, "service") membermanager_user = module_params_get(ansible_module, "membermanager_user") membermanager_group = module_params_get(ansible_module, "membermanager_group") externalmember = module_params_get(ansible_module, "externalmember") action = module_params_get(ansible_module, "action") # state state = module_params_get(ansible_module, "state") # Check parameters 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" ] for x in invalid: if vars()[x] is not None: ansible_module.fail_json( msg="Argument '%s' can not be used with action " "'%s'" % (x, action)) 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"]) for x in invalid: if vars()[x] is not None: ansible_module.fail_json( msg="Argument '%s' can not be used with state '%s'" % (x, state)) # Init changed = False exit_args = {} ccache_dir = None ccache_name = None try: if not valid_creds(ansible_module, ipaadmin_principal): ccache_dir, ccache_name = temp_kinit(ipaadmin_principal, ipaadmin_password) api_connect() has_add_member_service = api_check_param("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 = api_check_command("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) # Create command if state == "present": # Can't change an existing posix group check_objectclass_args(ansible_module, res_find, nonposix, 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 is args, check if there are # different settings in the find result. # If yes: modify if should_modify_group(ansible_module, res_find, args, nonposix, posix, external): if (posix or (nonposix is not None and not nonposix)): args['posix'] = True if external: args['external'] = True commands.append([name, "group_mod", args]) else: if nonposix or (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")) # 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]) 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") ) if has_add_membermanager: # Add membermanager users and groups if len(membermanager_user_add) > 0 or \ len(membermanager_group_add) > 0: commands.append([ name, "group_add_member_manager", { "user": membermanager_user_add, "group": membermanager_group_add, } ]) # Remove member manager if len(membermanager_user_del) > 0 or \ len(membermanager_group_del) > 0: commands.append([ name, "group_remove_member_manager", { "user": membermanager_user_del, "group": membermanager_group_del, } ]) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No group '%s'" % name) add_member_args = { "user": user, "group": group, } if has_add_member_service: add_member_args["service"] = service if is_external_group(res_find): add_member_args["ipaexternalmember"] = externalmember elif externalmember: ansible_module.fail_json( msg="Cannot add external members to a " "non-external group.") if any([user, group, service, externalmember]): commands.append( [name, "group_add_member", add_member_args]) if has_add_membermanager: # Add membermanager users and groups if membermanager_user is not None or \ membermanager_group is not None: commands.append([ name, "group_add_member_manager", { "user": membermanager_user, "group": 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) del_member_args = { "user": user, "group": group, } if has_add_member_service: del_member_args["service"] = service if is_external_group(res_find): del_member_args["ipaexternalmember"] = externalmember elif externalmember: ansible_module.fail_json( msg="Cannot add external members to a " "non-external group.") if any([user, group, service, externalmember]): commands.append( [name, "group_remove_member", del_member_args]) if has_add_membermanager: # Remove membermanager users and groups if membermanager_user is not None or \ membermanager_group is not None: commands.append([ name, "group_remove_member_manager", { "user": membermanager_user, "group": membermanager_group, } ]) else: ansible_module.fail_json(msg="Unkown state '%s'" % state) # Check mode exit if ansible_module.check_mode: ansible_module.exit_json(changed=len(commands) > 0, **exit_args) # Execute commands for name, command, args in commands: try: result = api_command(ansible_module, command, name, args) if "completed" in result: if result["completed"] > 0: changed = True else: changed = True except Exception as e: ansible_module.fail_json(msg="%s: %s: %s" % (command, name, str(e))) # Get all errors # All "already a member" and "not a member" failures in the # result are ignored. All others are reported. errors = [] for failed_item in result.get("failed", []): failed = result["failed"][failed_item] for member_type in failed: for member, failure in failed[member_type]: if "already a member" in failure \ or "not a member" in failure: continue errors.append("%s: %s %s: %s" % (command, member_type, member, failure)) if len(errors) > 0: ansible_module.fail_json(msg=", ".join(errors)) except Exception as e: ansible_module.fail_json(msg=str(e)) finally: temp_kdestroy(ccache_dir, ccache_name) # Done ansible_module.exit_json(changed=changed, **exit_args)