def find_service(module, name, netbiosname): _args = { "all": True, } # Search for a SMB/cifs service. if netbiosname is not None: _result = api_command(module, "service_find", to_text(netbiosname), _args) for _res_find in _result.get('result', []): for uid in _res_find.get('uid', []): if uid.startswith("%s$@" % netbiosname): return _res_find try: _result = api_command(module, "service_show", to_text(name), _args) except ipalib.errors.NotFound: return None if "result" in _result: _res = _result["result"] certs = _res.get("usercertificate") if certs is not None: _res["usercertificate"] = [ encode_certificate(cert) for cert in certs ] return _res else: return None
def find_service(module, name): _args = { "all": True, } _result = api_command(module, "service_find", to_text(name), _args) if len(_result["result"]) > 1: module.fail_json( msg="There is more than one service '%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 find_service(module, name): _args = { "all": True, } try: _result = api_command(module, "service_show", to_text(name), _args) except ipalib_errors.NotFound: return None if "result" in _result: _res = _result["result"] certs = _res.get("usercertificate") if certs is not None: _res["usercertificate"] = [ encode_certificate(cert) for cert in certs ] return _res return None
def main(): ansible_module = init_ansible_module() # Get parameters # general names = ansible_module.params_get("name") # service attributes principal = ansible_module.params_get("principal") certificate = ansible_module.params_get("certificate") pac_type = ansible_module.params_get("pac_type", allow_empty_string=True) auth_ind = ansible_module.params_get("auth_ind", allow_empty_string=True) skip_host_check = ansible_module.params_get("skip_host_check") force = ansible_module.params_get("force") requires_pre_auth = ansible_module.params_get("requires_pre_auth") ok_as_delegate = ansible_module.params_get("ok_as_delegate") ok_to_auth_as_delegate = ansible_module.params_get( "ok_to_auth_as_delegate") smb = ansible_module.params_get("smb") netbiosname = ansible_module.params_get("netbiosname") host = ansible_module.params_get("host") delete_continue = ansible_module.params_get("delete_continue") # action action = ansible_module.params_get("action") # state state = ansible_module.params_get("state") # check parameters check_parameters(ansible_module, state, action, names) # Init changed = False exit_args = {} # Connect to IPA API with ansible_module.ipa_connect(): has_skip_host_check = ansible_module.ipa_command_param_exists( "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 = [] keytab_members = ["user", "group", "host", "hostgroup"] for name in names: res_find = find_service(ansible_module, name) res_principals = [] keytab = { "retrieve": { "allow": {k: [] for k in keytab_members}, "disallow": {k: [] for k in keytab_members}, }, "create": { "allow": {k: [] for k in keytab_members}, "disallow": {k: [] for k in keytab_members}, }, } certificate_add, certificate_del = [], [] host_add, host_del = [], [] principal_add, principal_del = [], [] if principal and res_find: # When comparing principals to the existing ones, # the REALM is needded, and are added here for those # that do not have it. principal = [ p if "@" in p else "%s@%s" % (p, api_get_realm()) for p in principal ] principal = list(set(principal)) # Create list of existing principal aliases as strings # to compare with provided ones. canonicalname = { to_text(p) for p in res_find.get("krbcanonicalname", []) } res_principals = [ to_text(elem) for elem in res_find.get("krbprincipalname", []) ] res_principals = list(set(res_principals) - canonicalname) if state == "present": 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 smb: if res_find is None: _name = "cifs/" + name res_find = find_service(ansible_module, _name) if res_find is None: _args = gen_args_smb(netbiosname, ok_as_delegate, ok_to_auth_as_delegate) commands.append( [name, 'service_add_smb', _args]) res_find = {} # service_add_smb will prefix 'name' with # "cifs/", so we will need to change it here, # so that service_mod, if called later, works. name = _name if res_find is None: commands.append([name, 'service_add', args]) # Use an empty res_find to manage members res_find = {} else: for remove in ['skip_host_check', 'force']: if remove in args: del args[remove] if ("ipakrbauthzdata" in args and (args.get("ipakrbauthzdata", [""]) == res_find.get( "ipakrbauthzdata", [""]))): del args["ipakrbauthzdata"] if ("krbprincipalauthind" in args and (args.get("krbprincipalauthind", [""]) == res_find.get("krbprincipalauthind", [""]))): del args["krbprincipalauthind"] if not compare_args_ipa(ansible_module, args, res_find): commands.append([name, "service_mod", args]) # Manage members 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_principals) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No service '%s'" % name) certificate_add = gen_add_list( certificate, res_find.get("usercertificate")) host_add = gen_add_list(host, res_find.get('managedby_host')) principal_add = gen_add_list(principal, res_principals) # get keytab management lists for any 'action'. for perm in ["create", "retrieve"]: oper = "write" if perm == "create" else "read" for key in ["user", "group", "host", "hostgroup"]: add_list, del_list = (gen_add_del_lists( ansible_module.params_get("allow_%s_keytab_%s" % (perm, key)), res_find.get('ipaallowedtoperform_%s_keys_%s' % (oper, key)))) keytab[perm]["allow"][key] = add_list # Only remove members if action is 'service' if action == "service": keytab[perm]["disallow"][key] = del_list elif state == "absent": if action == "service": if res_find is not None: args = {'continue': delete_continue} commands.append([name, 'service_del', args]) elif action == "member": if res_find is None: ansible_module.fail_json(msg="No service '%s'" % name) principal_del = gen_intersection_list( principal, res_principals) certificate_del = gen_intersection_list( certificate, res_find.get("usercertificate")) host_del = gen_intersection_list( host, res_find.get("managedby_host")) for perm in ["create", "retrieve"]: oper = "write" if perm == "create" else "read" for key in ["user", "group", "host", "hostgroup"]: res_param = ('ipaallowedtoperform_%s_keys_%s' % (oper, key)) module_params = ansible_module.params_get( "allow_%s_keytab_%s" % (perm, key)) existing = res_find.get(res_param) del_list = (gen_intersection_list( module_params, existing)) keytab[perm]["disallow"][key] = del_list 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)) # Members are not managed when disabling service. # Continue with next 'name'. continue else: ansible_module.fail_json(msg="Unkown state '%s'" % state) # Manage members if principal_add: commands.append([ name, "service_add_principal", { "krbprincipalname": principal_add } ]) if principal_del: commands.append([ name, "service_remove_principal", { "krbprincipalname": principal_del } ]) if certificate_add: commands.append([ name, "service_add_cert", { "usercertificate": certificate_add } ]) if certificate_del: commands.append([ name, "service_remove_cert", { "usercertificate": certificate_del } ]) if host_add: commands.append([name, "service_add_host", {"host": host_add}]) if host_del: commands.append( [name, "service_remove_host", { "host": host_del }]) # manage keytab permissions. for perm in ["create", "retrieve"]: for mode in ["allow", "disallow"]: for key in ["user", "group", "host", "hostgroup"]: if keytab[perm][mode][key]: commands.append([ name, "service_%s_%s_keytab" % (mode, perm), keytab[perm][mode] ]) break # Check mode exit if ansible_module.check_mode: ansible_module.exit_json(changed=len(commands) > 0, **exit_args) # Execute commands changed = ansible_module.execute_ipa_commands( commands, fail_on_member_errors=True) # Done ansible_module.exit_json(changed=changed, **exit_args)