diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py index 0af0d63e..30e0dce8 100644 --- a/plugins/module_utils/ansible_freeipa_module.py +++ b/plugins/module_utils/ansible_freeipa_module.py @@ -42,6 +42,7 @@ import tempfile import shutil import socket import base64 +import ast from datetime import datetime from contextlib import contextmanager from ansible.module_utils.basic import AnsibleModule @@ -1169,6 +1170,32 @@ class IPAAnsibleModule(AnsibleModule): """ return api_check_param(command, name) + def ipa_command_invalid_param_choices(self, command, name, value): + """ + Return invalid parameter choices for IPA command. + + Parameters + ---------- + command: string + The IPA API command to test. + name: string + The parameter name to check. + value: string + The parameter value to verify. + + """ + if command not in api.Command: + self.fail_json(msg="The command '%s' does not exist." % command) + if name not in api.Command[command].params: + self.fail_json(msg="The command '%s' does not have a parameter " + "named '%s'." % (command, name)) + if not hasattr(api.Command[command].params[name], "cli_metavar"): + self.fail_json(msg="The parameter '%s' of the command '%s' does " + "not have choices." % (name, command)) + _choices = ast.literal_eval( + api.Command[command].params[name].cli_metavar) + return (set(value or []) - set([""])) - set(_choices) + @staticmethod def ipa_check_version(oper, requested_version): """ diff --git a/plugins/modules/ipaconfig.py b/plugins/modules/ipaconfig.py index 7e784925..37c06fad 100644 --- a/plugins/modules/ipaconfig.py +++ b/plugins/modules/ipaconfig.py @@ -160,7 +160,8 @@ options: required: false type: list elements: str - choices: ["password", "radius", "otp", "disabled", ""] + choices: ["password", "radius", "otp", "pkinit", "hardened", "idp", + "disabled", ""] aliases: ["ipauserauthtype"] ca_renewal_master_server: description: Renewal master for IPA certificate authority. @@ -425,6 +426,7 @@ def main(): choices=["MS-PAC", "PAD", "nfs:NONE", ""]), user_auth_type=dict(type="list", elements="str", required=False, choices=["password", "radius", "otp", + "pkinit", "hardened", "idp", "disabled", ""], aliases=["ipauserauthtype"]), ca_renewal_master_server=dict(type="str", required=False), @@ -525,6 +527,15 @@ def main(): result = config_show(ansible_module) if params: + # Verify ipauserauthtype(s) + if "ipauserauthtype" in params and params["ipauserauthtype"]: + _invalid = ansible_module.ipa_command_invalid_param_choices( + "config_mod", "ipauserauthtype", params["ipauserauthtype"]) + if _invalid: + ansible_module.fail_json( + msg="The use of userauthtype '%s' is not " + "supported by your IPA version" % "','".join(_invalid)) + enable_sid = params.get("enable_sid") sid_is_enabled = has_enable_sid and is_enable_sid(ansible_module) diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py index 8b45ebaa..e5e2f465 100644 --- a/plugins/modules/ipahost.py +++ b/plugins/modules/ipahost.py @@ -184,7 +184,7 @@ options: type: list elements: str aliases: ["krbprincipalauthind"] - choices: ["radius", "otp", "pkinit", "hardened", ""] + choices: ["radius", "otp", "pkinit", "hardened", "idp", ""] required: false requires_pre_auth: description: Pre-authentication is required for the service @@ -356,7 +356,7 @@ options: type: list elements: str aliases: ["krbprincipalauthind"] - choices: ["radius", "otp", "pkinit", "hardened", ""] + choices: ["radius", "otp", "pkinit", "hardened", "idp", ""] required: false requires_pre_auth: description: Pre-authentication is required for the service @@ -667,6 +667,15 @@ def check_parameters( # pylint: disable=unused-argument module.params_fail_used_invalid(invalid, state, action) +def check_authind(module, auth_ind): + _invalid = module.ipa_command_invalid_param_choices( + "host_add", "krbprincipalauthind", auth_ind) + if _invalid: + module.fail_json( + msg="The use of krbprincipalauthind '%s' is not supported " + "by your IPA version" % "','".join(_invalid)) + + # pylint: disable=unused-argument def result_handler(module, result, command, name, args, errors, exit_args, single_host): @@ -776,7 +785,8 @@ def main(): default=None), auth_ind=dict(type='list', elements="str", aliases=["krbprincipalauthind"], default=None, - choices=['radius', 'otp', 'pkinit', 'hardened', '']), + choices=["radius", "otp", "pkinit", "hardened", "idp", + ""]), requires_pre_auth=dict(type="bool", aliases=["ipakrbrequirespreauth"], default=None), ok_as_delegate=dict(type="bool", aliases=["ipakrbokasdelegate"], @@ -919,6 +929,8 @@ def main(): # Check version specific settings + check_authind(ansible_module, auth_ind) + server_realm = ansible_module.ipa_get_realm() commands = [] @@ -961,6 +973,7 @@ def main(): sshpubkey = host.get("sshpubkey") userclass = host.get("userclass") auth_ind = host.get("auth_ind") + check_authind(ansible_module, auth_ind) requires_pre_auth = host.get("requires_pre_auth") ok_as_delegate = host.get("ok_as_delegate") ok_to_auth_as_delegate = host.get("ok_to_auth_as_delegate") diff --git a/plugins/modules/ipaservice.py b/plugins/modules/ipaservice.py index 209a0311..0409b0b7 100644 --- a/plugins/modules/ipaservice.py +++ b/plugins/modules/ipaservice.py @@ -74,7 +74,7 @@ options: type: list elements: str required: false - choices: ["otp", "radius", "pkinit", "hardened", ""] + choices: ["otp", "radius", "pkinit", "hardened", "idp", ""] aliases: ["krbprincipalauthind"] skip_host_check: description: Skip checking if host object exists. @@ -185,7 +185,7 @@ options: type: list elements: str required: false - choices: ["otp", "radius", "pkinit", "hardened", ""] + choices: ["otp", "radius", "pkinit", "hardened", "idp", ""] aliases: ["krbprincipalauthind"] skip_host_check: description: Skip checking if host object exists. @@ -491,6 +491,15 @@ def check_parameters(module, state, action, names): module.params_fail_used_invalid(invalid, state, action) +def check_authind(module, auth_ind): + _invalid = module.ipa_command_invalid_param_choices( + "service_add", "krbprincipalauthind", auth_ind) + if _invalid: + module.fail_json( + msg="The use of krbprincipalauthind '%s' is not supported " + "by your IPA version" % "','".join(_invalid)) + + def init_ansible_module(): service_spec = dict( # service attributesstr @@ -506,7 +515,8 @@ def init_ansible_module(): choices=["MS-PAC", "PAD", "NONE", ""]), auth_ind=dict(type="list", elements="str", aliases=["krbprincipalauthind"], - choices=["otp", "radius", "pkinit", "hardened", ""]), + choices=["otp", "radius", "pkinit", "hardened", "idp", + ""]), skip_host_check=dict(type="bool"), force=dict(type="bool"), requires_pre_auth=dict( @@ -642,6 +652,7 @@ def main(): 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") + check_authind(ansible_module, auth_ind) commands = [] keytab_members = ["user", "group", "host", "hostgroup"] @@ -664,6 +675,7 @@ def main(): certificate = [cert.strip() for cert in certificate] pac_type = service.get("pac_type") auth_ind = service.get("auth_ind") + check_authind(ansible_module, auth_ind) skip_host_check = service.get("skip_host_check") if skip_host_check and not has_skip_host_check: ansible_module.fail_json( diff --git a/plugins/modules/ipauser.py b/plugins/modules/ipauser.py index c4961cc1..6059829c 100644 --- a/plugins/modules/ipauser.py +++ b/plugins/modules/ipauser.py @@ -208,7 +208,7 @@ options: Use empty string to reset userauthtype to the initial value. type: list elements: str - choices: ['password', 'radius', 'otp', ''] + choices: ["password", "radius", "otp", "pkinit", "hardened", "idp", ""] required: false aliases: ["ipauserauthtype"] userclass: @@ -465,7 +465,7 @@ options: Use empty string to reset userauthtype to the initial value. type: list elements: str - choices: ['password', 'radius', 'otp', ''] + choices: ["password", "radius", "otp", "pkinit", "hardened", "idp", ""] required: false aliases: ["ipauserauthtype"] userclass: @@ -888,6 +888,15 @@ def check_parameters( # pylint: disable=unused-argument module.fail_json(msg="certmapdata: subject is missing") +def check_userauthtype(module, userauthtype): + _invalid = module.ipa_command_invalid_param_choices( + "user_add", "ipauserauthtype", userauthtype) + if _invalid: + module.fail_json( + msg="The use of userauthtype '%s' is not supported " + "by your IPA version" % "','".join(_invalid)) + + def extend_emails(email, default_email_domain): if email is not None: return ["%s@%s" % (_email, default_email_domain) @@ -1023,7 +1032,8 @@ def main(): default=None), userauthtype=dict(type='list', elements="str", aliases=["ipauserauthtype"], default=None, - choices=['password', 'radius', 'otp', '']), + choices=["password", "radius", "otp", "pkinit", + "hardened", "idp", ""]), userclass=dict(type="list", elements="str", aliases=["class"], default=None), radius=dict(type="str", aliases=["ipatokenradiusconfiglink"], @@ -1213,6 +1223,10 @@ def main(): server_realm = ansible_module.ipa_get_realm() + # Check API specific parameters + + check_userauthtype(ansible_module, userauthtype) + # Default email domain result = ansible_module.ipa_command_no_name("config_show", {}) @@ -1303,6 +1317,10 @@ def main(): smb_home_dir, smb_home_drive) certmapdata = convert_certmapdata(certmapdata) + # Check API specific parameters + + check_userauthtype(ansible_module, userauthtype) + # Extend email addresses email = extend_emails(email, default_email_domain)