From cfbdd83a64585107db5400682d4cf2232593f6ce Mon Sep 17 00:00:00 2001 From: Thomas Woerner Date: Tue, 18 Jul 2023 15:46:56 +0200 Subject: [PATCH 1/5] ansible_freeipa_module: New ipa_command_invalid_param_choices method New IPAAnsibleModule.ipa_command_invalid_param_choices method to return invalid parameter choices for an IPA command. This is needed to verify for example if userauthtype and authind are supporting the idp value. --- .../module_utils/ansible_freeipa_module.py | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) 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): """ From c089c010e6b31341af7c4abc2ec2feb418dd12e2 Mon Sep 17 00:00:00 2001 From: Thomas Woerner Date: Tue, 18 Jul 2023 15:55:14 +0200 Subject: [PATCH 2/5] ipaconfig: Add choices pkinit, hardened and idp to user_auth_type The parameter user_auth_type has been updated in FreeIPA. The choices pkinit, hardened and idp have been missing and are now added. An additional check was added to verify that the values of the user_auth_type list are valid for the used IPA version. --- plugins/modules/ipaconfig.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) 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) From 3ed0c229c4ce264162a7848f587e8e96a8049f89 Mon Sep 17 00:00:00 2001 From: Thomas Woerner Date: Tue, 18 Jul 2023 16:02:13 +0200 Subject: [PATCH 3/5] ipahost: Add choice idp to auth_ind The parameter auth_ind has been updated in FreeIPA. The choice idp have been missing and is now added. An additional check was added to verify that the values of the auth_ind list are valid for the used IPA version. --- plugins/modules/ipahost.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) 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") From 62d34d0a22c8b6406de1c4234b6b18c689e887c9 Mon Sep 17 00:00:00 2001 From: Thomas Woerner Date: Tue, 18 Jul 2023 16:05:13 +0200 Subject: [PATCH 4/5] ipaservice: Add choice idp to auth_ind The parameter auth_ind has been updated in FreeIPA. The choice idp have been missing and is now added. An additional check was added to verify that the values of the auth_ind list are valid for the used IPA version. --- plugins/modules/ipaservice.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) 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( From c4b273c8960fb61fe40781177d76559fcef81d82 Mon Sep 17 00:00:00 2001 From: Thomas Woerner Date: Tue, 18 Jul 2023 16:06:33 +0200 Subject: [PATCH 5/5] ipauser: Add choices pkinit, hardened and idp to user_auth_type The parameter user_auth_type has been updated in FreeIPA. The choices pkinit, hardened and idp have been missing and are now added. An additional check was added to verify that the values of the user_auth_type list are valid for the used IPA version. --- plugins/modules/ipauser.py | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) 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)