From 9decad4e4f308e9d3e21f969adfed5518f48eab1 Mon Sep 17 00:00:00 2001 From: Thomas Woerner <twoerner@redhat.com> Date: Tue, 22 Feb 2022 16:17:53 +0100 Subject: [PATCH] ipaservice: Set allow_empty_string for auth_ind and pac_type The parameters auth_ind and pac_type are allowing to use "" to reset to the default value. The new check in params_get is not allowing to use empty strings in lists, therefore allow_empty_string=True had to be added to the call. A test has been added to verify that the empty strings are supported and working. An idempotency issue with pac_type has been found with the test and fixed additionally. --- README-service.md | 4 +- plugins/modules/ipaservice.py | 19 ++- .../test_service_empty_string_params.yml | 110 ++++++++++++++++++ 3 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 tests/service/test_service_empty_string_params.yml diff --git a/README-service.md b/README-service.md index 666c1893..c0cd3272 100644 --- a/README-service.md +++ b/README-service.md @@ -293,8 +293,8 @@ Variable | Description | Required `ipaapi_ldap_cache` | Use LDAP cache for IPA connection. The bool setting defaults to yes. (bool) | no `name` \| `service` | The list of service name strings. | yes `certificate` \| `usercertificate` | Base-64 encoded service certificate. | no -`pac_type` \| `ipakrbauthzdata` | Supported PAC type. It can be one of `MS-PAC`, `PAD`, or `NONE`. | no -`auth_ind` \| `krbprincipalauthind` | Defines an allow list for Authentication Indicators. It can be any of `otp`, `radius`, `pkinit`, or `hardened`. | no +`pac_type` \| `ipakrbauthzdata` | Supported PAC type. It can be one of `MS-PAC`, `PAD`, or `NONE`. Use empty string to reset pac_type to the initial value. | no +`auth_ind` \| `krbprincipalauthind` | Defines an allow list for Authentication Indicators. It can be any of `otp`, `radius`, `pkinit` or `hardened`. Use empty string to reset auth_ind to the initial value. | no `requires_pre_auth` \| `ipakrbrequirespreauth` | Pre-authentication is required for the service. Default to true. (bool) | no `ok_as_delegate` \| `ipakrbokasdelegate` | Client credentials may be delegated to the service. Default to false. (bool) | no `ok_to_auth_as_delegate` \| `ipakrboktoauthasdelegate` | The service is allowed to authenticate on behalf of a client. Default to false. (bool) | no diff --git a/plugins/modules/ipaservice.py b/plugins/modules/ipaservice.py index bc737712..989ab9a0 100644 --- a/plugins/modules/ipaservice.py +++ b/plugins/modules/ipaservice.py @@ -50,13 +50,13 @@ options: pac_type: description: Supported PAC type. required: false - choices: ["MS-PAC", "PAD", "NONE"] + choices: ["MS-PAC", "PAD", "NONE", ""] type: list aliases: ["pac_type", "ipakrbauthzdata"] auth_ind: description: Defines a whitelist for Authentication Indicators. required: false - choices: ["otp", "radius", "pkinit", "hardened"] + choices: ["otp", "radius", "pkinit", "hardened", ""] aliases: ["krbprincipalauthind"] skip_host_check: description: Skip checking if host object exists. @@ -356,7 +356,7 @@ def init_ansible_module(): smb=dict(type="bool", required=False), netbiosname=dict(type="str", required=False), pac_type=dict(type="list", aliases=["ipakrbauthzdata"], - choices=["MS-PAC", "PAD", "NONE"]), + choices=["MS-PAC", "PAD", "NONE", ""]), auth_ind=dict(type="list", aliases=["krbprincipalauthind"], choices=["otp", "radius", "pkinit", "hardened", ""]), @@ -420,8 +420,8 @@ def main(): # service attributes principal = ansible_module.params_get("principal") certificate = ansible_module.params_get("certificate") - pac_type = ansible_module.params_get("pac_type") - auth_ind = ansible_module.params_get("auth_ind") + 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") @@ -537,6 +537,15 @@ def main(): 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 ( diff --git a/tests/service/test_service_empty_string_params.yml b/tests/service/test_service_empty_string_params.yml new file mode 100644 index 00000000..1831e496 --- /dev/null +++ b/tests/service/test_service_empty_string_params.yml @@ -0,0 +1,110 @@ +--- +- name: Test service + hosts: "{{ ipa_test_host | default('ipaserver') }}" + become: yes + gather_facts: yes + + tasks: + + # CLEANUP TEST ITEMS + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is absent. + ipaservice: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: "test-service/{{ ansible_facts['fqdn'] }}" + continue: yes + state: absent + + # CREATE TEST ITEMS + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "test-service/{{ ansible_facts['fqdn'] }}" + register: result + failed_when: not result.changed or result.failed + + # TESTS + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with pac_type MS-PAC and PAD + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "test-service/{{ ansible_facts['fqdn'] }}" + pac_type: + - MS-PAC + - PAD + register: result + failed_when: not result.changed or result.failed + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with pac_type MS-PAC and PAD, again + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "test-service/{{ ansible_facts['fqdn'] }}" + pac_type: + - MS-PAC + - PAD + register: result + failed_when: result.changed or result.failed + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with empty pac_type + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "test-service/{{ ansible_facts['fqdn'] }}" + pac_type: "" + register: result + failed_when: not result.changed or result.failed + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with empty pac_type, again + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "test-service/{{ ansible_facts['fqdn'] }}" + pac_type: "" + register: result + failed_when: result.changed or result.failed + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with auth_ind otp and radius + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "test-service/{{ ansible_facts['fqdn'] }}" + auth_ind: + - otp + - radius + register: result + failed_when: not result.changed or result.failed + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with auth_ind otp and radius, again + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "test-service/{{ ansible_facts['fqdn'] }}" + auth_ind: + - otp + - radius + register: result + failed_when: result.changed or result.failed + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with empty auth_ind + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "test-service/{{ ansible_facts['fqdn'] }}" + auth_ind: "" + register: result + failed_when: not result.changed or result.failed + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is present with empty auth_ind, again + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "test-service/{{ ansible_facts['fqdn'] }}" + auth_ind: "" + register: result + failed_when: result.changed or result.failed + + # CLEANUP TEST ITEMS + + - name: Ensure service "test-service/{{ ansible_facts['fqdn'] }}" is absent. + ipaservice: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: "test-service/{{ ansible_facts['fqdn'] }}" + continue: yes + state: absent -- GitLab