diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py index 4d1a77c37ed7feae8314fefd6b6543ed9f71c169..9bfad7f63ae0616cc69fe2333996cad41326224a 100644 --- a/plugins/module_utils/ansible_freeipa_module.py +++ b/plugins/module_utils/ansible_freeipa_module.py @@ -54,6 +54,7 @@ import tempfile import shutil import socket import base64 +import binascii import ast import time from datetime import datetime @@ -644,6 +645,7 @@ def encode_certificate(cert): Encode a certificate using base64. It also takes FreeIPA and Python versions into account. + This is used to convert the certificates returned by find and show. """ if isinstance(cert, (str, unicode, bytes)): encoded = base64.b64encode(cert) @@ -654,6 +656,33 @@ def encode_certificate(cert): return encoded +def convert_input_certificates(module, certs, state): + """ + Convert certificates. + + Remove all newlines and white spaces from the certificates. + This is used on input parameter certificates of modules. + """ + if certs is None: + return None + + _certs = [] + for cert in certs: + try: + _cert = base64.b64encode(base64.b64decode(cert)).decode("ascii") + except (TypeError, binascii.Error) as e: + # Idempotency: Do not fail for an invalid cert for state absent. + # The invalid certificate can not be set in FreeIPA. + if state == "absent": + continue + module.fail_json( + msg="Certificate %s: Base64 decoding failed: %s" % + (repr(cert), str(e))) + _certs.append(_cert) + + return _certs + + def load_cert_from_str(cert): cert = cert.strip() if not cert.startswith("-----BEGIN CERTIFICATE-----"): diff --git a/plugins/modules/ipahost.py b/plugins/modules/ipahost.py index 6600d81d09bfae47defc69c87545221a0f846551..24acaa36121100953590cfb4fa11e9a663888897 100644 --- a/plugins/modules/ipahost.py +++ b/plugins/modules/ipahost.py @@ -510,7 +510,8 @@ host: from ansible.module_utils.ansible_freeipa_module import \ IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \ encode_certificate, is_ipv4_addr, is_ipv6_addr, ipalib_errors, \ - gen_add_list, gen_intersection_list, normalize_sshpubkey + gen_add_list, gen_intersection_list, normalize_sshpubkey, \ + convert_input_certificates from ansible.module_utils import six if six.PY3: unicode = str @@ -682,13 +683,6 @@ def check_authind(module, auth_ind): "by your IPA version" % "','".join(_invalid)) -def convert_certificate(certificate): - if certificate is None: - return None - - return [cert.strip() for cert in certificate] - - # pylint: disable=unused-argument def result_handler(module, result, command, name, args, exit_args, single_host): @@ -894,7 +888,8 @@ def main(): auth_ind, requires_pre_auth, ok_as_delegate, ok_to_auth_as_delegate, force, reverse, ip_address, update_dns, update_password) - certificate = convert_certificate(certificate) + certificate = convert_input_certificates(ansible_module, certificate, + state) if sshpubkey is not None: sshpubkey = [str(normalize_sshpubkey(key)) for key in sshpubkey] @@ -982,7 +977,8 @@ def main(): ok_to_auth_as_delegate, force, reverse, ip_address, update_dns, update_password) - certificate = convert_certificate(certificate) + certificate = convert_input_certificates(ansible_module, + certificate, state) if sshpubkey is not None: sshpubkey = [str(normalize_sshpubkey(key)) for diff --git a/plugins/modules/ipaidoverrideuser.py b/plugins/modules/ipaidoverrideuser.py index 6714265f9ea0c8554de0a64027b3c890f29204d7..49412ebd908d660a17eb6a6b9fd20d530acf3e53 100644 --- a/plugins/modules/ipaidoverrideuser.py +++ b/plugins/modules/ipaidoverrideuser.py @@ -315,7 +315,7 @@ RETURN = """ from ansible.module_utils.ansible_freeipa_module import \ IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, gen_add_list, \ - gen_intersection_list, encode_certificate + gen_intersection_list, encode_certificate, convert_input_certificates from ansible.module_utils import six if six.PY3: @@ -479,8 +479,8 @@ def main(): ansible_module.params_fail_used_invalid(invalid, state, action) - if certificate is not None: - certificate = [cert.strip() for cert in certificate] + certificate = convert_input_certificates(ansible_module, certificate, + state) # Init diff --git a/plugins/modules/ipaservice.py b/plugins/modules/ipaservice.py index 6a2e5eb7ad18b36cf59a258c3ce9950fceb58766..c1e9309d88c54079674cda12f02b84fcf383cba8 100644 --- a/plugins/modules/ipaservice.py +++ b/plugins/modules/ipaservice.py @@ -378,7 +378,7 @@ RETURN = """ from ansible.module_utils.ansible_freeipa_module import \ IPAAnsibleModule, compare_args_ipa, encode_certificate, \ gen_add_del_lists, gen_add_list, gen_intersection_list, ipalib_errors, \ - api_get_realm, to_text + api_get_realm, to_text, convert_input_certificates from ansible.module_utils import six if six.PY3: unicode = str @@ -601,12 +601,6 @@ def main(): # service attributes principal = ansible_module.params_get("principal") certificate = ansible_module.params_get("certificate") - # Any leading or trailing whitespace is removed while adding the - # certificate with serive_add_cert. To be able to compare the results - # from service_show with the given certificates we have to remove the - # white space also. - if certificate is not None: - certificate = [cert.strip() for cert in certificate] pac_type = ansible_module.params_get( "pac_type", allow_empty_list_item=True) auth_ind = ansible_module.params_get( @@ -636,6 +630,8 @@ def main(): ansible_module.fail_json(msg="At least one name or services is " "required") check_parameters(ansible_module, state, action, names) + certificate = convert_input_certificates(ansible_module, certificate, + state) # Use services if names is None if services is not None: @@ -669,12 +665,8 @@ def main(): service_set.add(name) principal = service.get("principal") certificate = service.get("certificate") - # Any leading or trailing whitespace is removed while adding - # the certificate with serive_add_cert. To be able to compare - # the results from service_show with the given certificates - # we have to remove the white space also. - if certificate is not None: - certificate = [cert.strip() for cert in certificate] + certificate = convert_input_certificates(ansible_module, + certificate, state) pac_type = service.get("pac_type") auth_ind = service.get("auth_ind") check_authind(ansible_module, auth_ind) diff --git a/plugins/modules/ipauser.py b/plugins/modules/ipauser.py index 36372c4adeb2bfeb8e2e6fbc33792eedf68b5709..f78f23ed235ec1395082095c9c3269dc04e7141d 100644 --- a/plugins/modules/ipauser.py +++ b/plugins/modules/ipauser.py @@ -741,7 +741,8 @@ user: from ansible.module_utils.ansible_freeipa_module import \ IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, date_format, \ encode_certificate, load_cert_from_str, DN_x500_text, to_text, \ - ipalib_errors, gen_add_list, gen_intersection_list + ipalib_errors, gen_add_list, gen_intersection_list, \ + convert_input_certificates from ansible.module_utils import six if six.PY3: unicode = str @@ -961,13 +962,6 @@ def extend_emails(email, default_email_domain): return email -def convert_certificate(certificate): - if certificate is None: - return None - - return [cert.strip() for cert in certificate] - - def convert_certmapdata(certmapdata): if certmapdata is None: return None @@ -1260,7 +1254,8 @@ def main(): preserve, update_password, smb_logon_script, smb_profile_path, smb_home_dir, smb_home_drive, idp, idp_user_id, rename, ) - certificate = convert_certificate(certificate) + certificate = convert_input_certificates(ansible_module, certificate, + state) certmapdata = convert_certmapdata(certmapdata) # Init @@ -1371,7 +1366,8 @@ def main(): update_password, smb_logon_script, smb_profile_path, smb_home_dir, smb_home_drive, idp, idp_user_id, rename, ) - certificate = convert_certificate(certificate) + certificate = convert_input_certificates(ansible_module, + certificate, state) certmapdata = convert_certmapdata(certmapdata) # Check API specific parameters