diff --git a/plugins/modules/ipaservice.py b/plugins/modules/ipaservice.py index b69a95cb75b357d9af8aaf3d8c20961d4984b5b8..3f30bd23aa0bae6938a1c26bb6bd18f3a272abd5 100644 --- a/plugins/modules/ipaservice.py +++ b/plugins/modules/ipaservice.py @@ -224,7 +224,8 @@ RETURN = """ from ansible.module_utils.ansible_freeipa_module import \ IPAAnsibleModule, compare_args_ipa, encode_certificate, \ - gen_add_del_lists, ipalib_errors + gen_add_del_lists, gen_add_list, gen_intersection_list, ipalib_errors, \ + api_get_realm, to_text def find_service(module, name): @@ -492,6 +493,30 @@ def main(): for name in names: res_find = find_service(ansible_module, name) + res_principals = [] + + 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": @@ -576,8 +601,8 @@ def main(): 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")) + principal_add, principal_del = \ + gen_add_del_lists(principal, res_principals) (allow_create_keytab_user_add, allow_create_keytab_user_del) = \ @@ -646,7 +671,7 @@ def main(): certificate_del = [] host_add = host or [] host_del = [] - principal_add = principal or [] + principal_add = gen_add_list(principal, res_principals) principal_del = [] allow_create_keytab_user_add = \ @@ -674,21 +699,12 @@ def main(): allow_retrieve_keytab_hostgroup or [] allow_retrieve_keytab_hostgroup_del = [] - # Add principals - for _principal in principal_add: + if principal_add: commands.append([name, "service_add_principal", - { - "krbprincipalname": - _principal, - }]) - - # Remove principals - for _principal in principal_del: + {"krbprincipalname": principal_add}]) + if principal_del: commands.append([name, "service_remove_principal", - { - "krbprincipalname": - _principal, - }]) + {"krbprincipalname": principal_del}]) for _certificate in certificate_add: commands.append([name, "service_add_cert", @@ -776,13 +792,12 @@ def main(): 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, - }]) + principal_del = gen_intersection_list( + principal, res_principals) + if principal_del: + commands.append([name, "service_remove_principal", + {"krbprincipalname": principal_del}]) + # Remove certificates if certificate is not None: existing = res_find.get('usercertificate', []) diff --git a/tests/service/test_service_without_skip_host_check.yml b/tests/service/test_service_without_skip_host_check.yml index 0dc0fe451ef1de23f24976344a10b8bf89cabb8b..763a56aafbedd0f26df5b99b27fe425f55662ac4 100644 --- a/tests/service/test_service_without_skip_host_check.yml +++ b/tests/service/test_service_without_skip_host_check.yml @@ -347,6 +347,118 @@ register: result failed_when: result.changed or result.failed + # tests for upstream issue #663 + - name: Ensure service is present with principal alias. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: "asvc/{{ host1_fqdn }}" + register: result + failed_when: result.failed or not result.changed + + - name: Ensure service is present with principal alias, again. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: "asvc/{{ host1_fqdn }}" + register: result + failed_when: result.failed or result.changed + + - name: Ensure service is present with different principal alias. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: "HTTP/{{ host1_fqdn }}" + force: yes + register: result + failed_when: result.failed or not result.changed + + - name: Ensure service is presennt with different principal alias, again. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: "HTTP/{{ host1_fqdn }}" + force: yes + register: result + failed_when: result.failed or result.changed + + - name: Ensure service member principal alias is present. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: "asvc/{{ host1_fqdn }}" + action: member + register: result + failed_when: result.failed or not result.changed + + - name: Ensure service member principal alias is present, again. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: "asvc/{{ host1_fqdn }}" + action: member + register: result + failed_when: result.failed or result.changed + + - name: Ensure service member principal alias is absent. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: "asvc/{{ host1_fqdn }}" + action: member + state: absent + register: result + failed_when: result.failed or not result.changed + + - name: Ensure service member principal alias is absent, again. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: "asvc/{{ host1_fqdn }}" + action: member + state: absent + register: result + failed_when: result.failed or result.changed + + - name: Ensure service is present with multiple principal aliases. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: + - "HTTP/{{ host1_fqdn }}" + - "asvc/{{ host1_fqdn }}" + register: result + failed_when: result.failed or not result.changed + + - name: Ensure service is present with multiple principal aliases, again. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + principal: + - "HTTP/{{ host1_fqdn }}" + - "asvc/{{ host1_fqdn }}" + register: result + failed_when: result.failed or result.changed + + - name: Ensure service is with multiple principal aliases is absent. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + continue: yes + state: absent + register: result + failed_when: result.failed or not result.changed + + - name: Ensure service is with multiple principal aliases is absent, again. + ipaservice: + ipaadmin_password: SomeADMINpassword + name: "mysvc/{{ host1_fqdn }}" + continue: yes + state: absent + register: result + failed_when: result.failed or result.changed + # end of tests for upstream issue #663 + # cleanup - name: Cleanup test environment include_tasks: env_cleanup.yml