diff --git a/roles/ipaserver/library/ipaserver_set_ds_password.py b/roles/ipaserver/library/ipaserver_set_ds_password.py index 007730241ed22b3d63bf728b588e89880cde7e4e..4b5b3b35ee3994aca8d69dc609bd82af16e4e309 100644 --- a/roles/ipaserver/library/ipaserver_set_ds_password.py +++ b/roles/ipaserver/library/ipaserver_set_ds_password.py @@ -127,7 +127,7 @@ def main(): no_hbac_allow=dict(required=False, type='bool', default=False), no_pkinit=dict(required=False, type='bool', default=False), dirsrv_config_file=dict(required=False), - _dirsrv_pkcs12_info=dict(required=False), + _dirsrv_pkcs12_info=dict(required=False, type='list'), # ssl certificate dirsrv_cert_files=dict(required=False, type='list', default=[]), subject_base=dict(required=False), diff --git a/roles/ipaserver/library/ipaserver_setup_ca.py b/roles/ipaserver/library/ipaserver_setup_ca.py index faaf66018a7cbffcde3ead96d53fac88af258473..6a5cfcce45d2f9772603c6aaae9b9c153dbd1fe8 100644 --- a/roles/ipaserver/library/ipaserver_setup_ca.py +++ b/roles/ipaserver/library/ipaserver_setup_ca.py @@ -163,7 +163,7 @@ from ansible.module_utils.ansible_ipa_server import ( AnsibleModuleLog, setup_logging, options, sysrestore, paths, ansible_module_get_parsed_ip_addresses, api_Backend_ldap2, redirect_stdout, ca, installutils, ds_init_info, - custodiainstance, write_cache, x509 + custodiainstance, write_cache, x509, decode_certificate ) @@ -191,7 +191,7 @@ def main(): no_pkinit=dict(required=False, type='bool', default=False), dirsrv_config_file=dict(required=False), dirsrv_cert_files=dict(required=False, type='list'), - _dirsrv_pkcs12_info=dict(required=False), + _dirsrv_pkcs12_info=dict(required=False, type='list'), # certificate system external_ca=dict(required=False, type='bool', default=False), external_ca_type=dict(required=False), @@ -265,8 +265,8 @@ def main(): # additional options.domainlevel = ansible_module.params.get('domainlevel') options._http_ca_cert = ansible_module.params.get('_http_ca_cert') - # tions._update_hosts_file = ansible_module.params.get( - # 'update_hosts_file') + if options._http_ca_cert is not None: + options._http_ca_cert = decode_certificate(options._http_ca_cert) # init ################################################################# diff --git a/roles/ipaserver/library/ipaserver_setup_ds.py b/roles/ipaserver/library/ipaserver_setup_ds.py index fc49d62a246bcd23b12e7bdade8a3c0243244f00..3fc9d50ad2ceb3a6ba02d4f232b3021f97395346 100644 --- a/roles/ipaserver/library/ipaserver_setup_ds.py +++ b/roles/ipaserver/library/ipaserver_setup_ds.py @@ -126,7 +126,7 @@ def main(): dirsrv_config_file=dict(required=False), # ssl certificate dirsrv_cert_files=dict(required=False, type='list', default=[]), - _dirsrv_pkcs12_info=dict(required=False), + _dirsrv_pkcs12_info=dict(required=False, type='list'), # certificate system external_cert_files=dict(required=False, type='list', default=[]), subject_base=dict(required=False), diff --git a/roles/ipaserver/library/ipaserver_setup_http.py b/roles/ipaserver/library/ipaserver_setup_http.py index f5479f5d152250a565fef71841aa21c02092ff54..4d9a54d6585f634c6850b5af321e1b85434da6fa 100644 --- a/roles/ipaserver/library/ipaserver_setup_http.py +++ b/roles/ipaserver/library/ipaserver_setup_http.py @@ -199,8 +199,8 @@ def main(): # _update_hosts_file=dict(required=False, type='bool', # default=False), - _dirsrv_pkcs12_info=dict(required=False), - _http_pkcs12_info=dict(required=False), + _dirsrv_pkcs12_info=dict(required=False, type='list'), + _http_pkcs12_info=dict(required=False, type='list'), ), ) diff --git a/roles/ipaserver/library/ipaserver_setup_krb.py b/roles/ipaserver/library/ipaserver_setup_krb.py index d86714672cff3864943aacaacb02a27ebcb212e2..1101d8d0cdf178583857b5deadac5179abccd351 100644 --- a/roles/ipaserver/library/ipaserver_setup_krb.py +++ b/roles/ipaserver/library/ipaserver_setup_krb.py @@ -160,7 +160,7 @@ def main(): no_reverse=dict(required=False, type='bool', default=False), auto_forwarders=dict(required=False, type='bool', default=False), - _pkinit_pkcs12_info=dict(required=False), + _pkinit_pkcs12_info=dict(required=False, type='list'), ), ) diff --git a/roles/ipaserver/library/ipaserver_test.py b/roles/ipaserver/library/ipaserver_test.py index 71afabcf6e7ee4b18ef0eb631e77af26da7ff9b7..4ac100c91d053f3ce188d38fa1fced725102c072 100644 --- a/roles/ipaserver/library/ipaserver_test.py +++ b/roles/ipaserver/library/ipaserver_test.py @@ -209,6 +209,7 @@ import sys import six import inspect import random +from shutil import copyfile from ansible.module_utils.basic import AnsibleModule from ansible.module_utils._text import to_native @@ -219,7 +220,8 @@ from ansible.module_utils.ansible_ipa_server import ( NUM_VERSION, is_ipa_configured, sysrestore, paths, bindinstance, read_cache, ca, tasks, check_ldap_conf, timeconf, httpinstance, check_dirsrv, ScriptError, get_fqdn, verify_fqdn, BadHostError, - validate_domain_name, load_pkcs12, IPA_PYTHON_VERSION + validate_domain_name, load_pkcs12, IPA_PYTHON_VERSION, + encode_certificate ) if six.PY3: @@ -252,7 +254,7 @@ def main(): dirsrv_config_file=dict(required=False), # ssl certificate dirsrv_cert_files=dict(required=False, type='list', default=None), - http_cert_files=dict(required=False, type='list', defaullt=None), + http_cert_files=dict(required=False, type='list', default=None), pkinit_cert_files=dict(required=False, type='list', default=None), dirsrv_pin=dict(required=False), http_pin=dict(required=False), @@ -1013,6 +1015,21 @@ def main(): # done ################################################################## + # Copy pkcs12_files to make them persistent till deployment is done + # and encode certificates for ansible compatibility + if http_pkcs12_info is not None: + copyfile(http_pkcs12_file.name, "/etc/ipa/.tmp_pkcs12_http") + http_pkcs12_info = ("/etc/ipa/.tmp_pkcs12_http", http_pin) + http_ca_cert = encode_certificate(http_ca_cert) + if dirsrv_pkcs12_info is not None: + copyfile(dirsrv_pkcs12_file.name, "/etc/ipa/.tmp_pkcs12_dirsrv") + dirsrv_pkcs12_info = ("/etc/ipa/.tmp_pkcs12_dirsrv", dirsrv_pin) + dirsrv_ca_cert = encode_certificate(dirsrv_ca_cert) + if pkinit_pkcs12_info is not None: + copyfile(pkinit_pkcs12_file.name, "/etc/ipa/.tmp_pkcs12_pkinit") + pkinit_pkcs12_info = ("/etc/ipa/.tmp_pkcs12_pkinit", pkinit_pin) + pkinit_ca_cert = encode_certificate(pkinit_ca_cert) + ansible_module.exit_json(changed=False, ipa_python_version=IPA_PYTHON_VERSION, # basic diff --git a/roles/ipaserver/module_utils/ansible_ipa_server.py b/roles/ipaserver/module_utils/ansible_ipa_server.py index 244bc75d2ad99b524b18e17f31d68e337a939c8c..d934751389a33dfc8290e7e4133a36655bef0fd7 100644 --- a/roles/ipaserver/module_utils/ansible_ipa_server.py +++ b/roles/ipaserver/module_utils/ansible_ipa_server.py @@ -37,11 +37,13 @@ __all__ = ["IPAChangeConf", "certmonger", "sysrestore", "root_logger", "validate_dm_password", "read_cache", "write_cache", "adtrustinstance", "IPAAPI_USER", "sync_time", "PKIIniLoader", "default_subject_base", "default_ca_subject_dn", - "check_ldap_conf"] + "check_ldap_conf", "encode_certificate", "decode_certificate"] import sys import logging from contextlib import contextmanager as contextlib_contextmanager +import six +import base64 from ipapython.version import NUM_VERSION, VERSION @@ -137,6 +139,17 @@ if NUM_VERSION >= 40500: except ImportError: check_ldap_conf = None + try: + from ipalib.x509 import Encoding + except ImportError: + from cryptography.hazmat.primitives.serialization import Encoding + + try: + from ipalib.x509 import load_pem_x509_certificate + except ImportError: + from ipalib.x509 import load_certificate + load_pem_x509_certificate = None + else: # IPA version < 4.5 @@ -322,3 +335,41 @@ def ansible_module_get_parsed_ip_addresses(ansible_module, ansible_module.fail_json(msg="Invalid IP Address %s: %s" % (ip, e)) ip_addrs.append(ip_parsed) return ip_addrs + + +def encode_certificate(cert): + """ + Encode a certificate using base64. + + It also takes FreeIPA and Python versions into account. + """ + if isinstance(cert, (str, bytes)): + encoded = base64.b64encode(cert) + else: + encoded = base64.b64encode(cert.public_bytes(Encoding.DER)) + if not six.PY2: + encoded = encoded.decode('ascii') + return encoded + + +def decode_certificate(cert): + """ + Decode a certificate using base64. + + It also takes FreeIPA versions into account and returns a IPACertificate + for newer IPA versions. + """ + if hasattr(x509, "IPACertificate"): + cert = cert.strip() + if not cert.startswith("-----BEGIN CERTIFICATE-----"): + cert = "-----BEGIN CERTIFICATE-----\n" + cert + if not cert.endswith("-----END CERTIFICATE-----"): + cert += "\n-----END CERTIFICATE-----" + + if load_pem_x509_certificate is not None: + cert = load_pem_x509_certificate(cert.encode('utf-8')) + else: + cert = load_certificate(cert.encode('utf-8')) + else: + cert = base64.b64decode(cert) + return cert diff --git a/roles/ipaserver/tasks/install.yml b/roles/ipaserver/tasks/install.yml index 85df9a7dd92610a133be9dffc92aef4629837cfe..30f9da2102e074b9317397d9ad7fabf77a3fa380 100644 --- a/roles/ipaserver/tasks/install.yml +++ b/roles/ipaserver/tasks/install.yml @@ -286,6 +286,7 @@ reverse_zones: "{{ result_ipaserver_prepare.reverse_zones }}" no_reverse: "{{ ipaserver_no_reverse }}" auto_forwarders: "{{ ipaserver_auto_forwarders }}" + _http_ca_cert: "{{ result_ipaserver_test._http_ca_cert }}" register: result_ipaserver_setup_ca - name: Copy /root/ipa.csr to "{{ inventory_hostname }}-ipa.csr" @@ -448,6 +449,16 @@ when: not result_ipaserver_setup_ca.csr_generated | bool + always: + - name: Cleanup temporary files + file: + path: "{{ item }}" + state: absent + with_items: + - "/etc/ipa/.tmp_pkcs12_dirsrv" + - "/etc/ipa/.tmp_pkcs12_http" + - "/etc/ipa/.tmp_pkcs12_pkinit" + when: not ansible_check_mode and not (not result_ipaserver_test.changed and (result_ipaserver_test.client_already_configured is defined or diff --git a/tests/ca-less/generate-certificates.sh b/tests/ca-less/generate-certificates.sh index 59b12cdf6b943ebdf01813ba3c7f66e7fd44bf59..e96d323ae4a932883d2bc574d1e1cea3305d9b1e 100755 --- a/tests/ca-less/generate-certificates.sh +++ b/tests/ca-less/generate-certificates.sh @@ -150,4 +150,4 @@ case "$1" in *) echo $"Usage: $0 {create|delete}" ;; -esac \ No newline at end of file +esac diff --git a/tests/ca-less/install_server_without_ca.yml b/tests/ca-less/install_server_without_ca.yml index ecb609c4fd17593e0352a5b2c37c28465266e394..d076f4b2a19df4e7d6ce8bee8a4b7ecc6d5cb10a 100644 --- a/tests/ca-less/install_server_without_ca.yml +++ b/tests/ca-less/install_server_without_ca.yml @@ -7,7 +7,11 @@ - name: Run generate-certificates.sh command: > /bin/bash +<<<<<<< HEAD generate-certificates.sh create +======= + generate-certificates.sh +>>>>>>> t-woerner/server_ca_less "{{ groups.ipaserver[0] }}" "{{ ipaserver_domain | default(groups.ipaserver[0].split('.')[1:] | join ('.')) }}" args: @@ -59,7 +63,11 @@ - name: Copy p12 certificates copy: +<<<<<<< HEAD src: "{{ playbook_dir }}/certificates/{{ item }}/{{ groups.ipaserver[0] }}/cert.p12" +======= + src: "{{ playbook_dir }}/certificates/{{ item }}/ipaserver/cert.p12" +>>>>>>> t-woerner/server_ca_less dest: "/root/ca-less-test/{{ item }}.p12" owner: root group: root