From 14f975b41116f636b04b9a999a0ef99f442eb9ff Mon Sep 17 00:00:00 2001 From: Thomas Woerner <twoerner@redhat.com> Date: Thu, 21 Jun 2018 13:18:11 +0200 Subject: [PATCH] ipaserver: Add support for 4.7 (4.6.90-pre2) With IPA 4.7 bigger changes have been introduced Changes: - Use of timeconf and chrony instead of ntpconf and ntpd. - New IPAChangeConf (not used in ipaserver modules) - New check_ldap_conf form ipaclient.install.client - custodia instance needed for ca and kra - no_ntp defaults to yes for client installation part - A new option ntp_pool has been introduced (set to None). --- module_utils/ansible_ipa_server.py | 23 +++++++-- roles/ipaserver/library/ipaserver_prepare.py | 2 +- roles/ipaserver/library/ipaserver_setup_ca.py | 22 +++++++-- roles/ipaserver/library/ipaserver_setup_ds.py | 2 +- .../ipaserver/library/ipaserver_setup_kra.py | 9 +++- .../ipaserver/library/ipaserver_setup_ntp.py | 28 ++++++++--- roles/ipaserver/library/ipaserver_test.py | 48 ++++++++----------- roles/ipaserver/tasks/install.yml | 16 ++++--- 8 files changed, 99 insertions(+), 51 deletions(-) diff --git a/module_utils/ansible_ipa_server.py b/module_utils/ansible_ipa_server.py index 8e8f9b5c..d059f3ab 100644 --- a/module_utils/ansible_ipa_server.py +++ b/module_utils/ansible_ipa_server.py @@ -51,12 +51,14 @@ if NUM_VERSION >= 40500: import six + if NUM_VERSION >= 40690: + from ipaclient.install.ipachangeconf import IPAChangeConf from ipalib.install import certmonger, sysrestore from ipapython import ipautil if NUM_VERSION < 40600: from ipapython.ipa_log_manager import root_logger from ipapython.ipautil import ( - format_netloc, ipa_generate_password, run, user_input) + ipa_generate_password, run, user_input) from ipapython.admintool import ScriptError from ipaplatform import services from ipaplatform.paths import paths @@ -70,11 +72,21 @@ if NUM_VERSION >= 40500: no_matching_interface_for_ip_address_warning, ) from ipapython.dnsutil import check_zone_overlap - from ipaclient.install import ntpconf + try: + from ipaclient.install import timeconf + from ipaclient.install.client import sync_time + time_service = "chronyd" + except ImportError: + try: + from ipaclient.install import ntpconf as timeconf + except ImportError: + from ipaclient import ntpconf as timeconf + from ipaserver.install import ntpinstance + time_service = "ntpd" from ipaserver.install import ( adtrust, bindinstance, ca, dns, dsinstance, httpinstance, installutils, kra, krbinstance, - ntpinstance, otpdinstance, custodiainstance, replication, service, + otpdinstance, custodiainstance, replication, service, sysupgrade) adtrust_imported = True kra_imported = True @@ -105,6 +117,11 @@ if NUM_VERSION >= 40500: except ImportError: _server_trust_ad_installed = False + try: + from ipaclient.install.client import check_ldap_conf + except ImportError: + check_ldap_conf = None + else: # IPA version < 4.5 diff --git a/roles/ipaserver/library/ipaserver_prepare.py b/roles/ipaserver/library/ipaserver_prepare.py index 9437ce0d..51ad8b86 100644 --- a/roles/ipaserver/library/ipaserver_prepare.py +++ b/roles/ipaserver/library/ipaserver_prepare.py @@ -200,7 +200,7 @@ def main(): fd.write("realm=%s\n" % options.realm_name) fd.write("domain=%s\n" % options.domain_name) fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % \ - format_netloc(options.host_name)) + ipautil.format_netloc(options.host_name)) fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % \ installutils.realm_to_serverid(options.realm_name)) if options.setup_ca: diff --git a/roles/ipaserver/library/ipaserver_setup_ca.py b/roles/ipaserver/library/ipaserver_setup_ca.py index c1ff47a5..c1615471 100644 --- a/roles/ipaserver/library/ipaserver_setup_ca.py +++ b/roles/ipaserver/library/ipaserver_setup_ca.py @@ -170,6 +170,8 @@ def main(): # init ################################################################# + options.promote = False # first master, no promotion + fstore = sysrestore.FileStore(paths.SYSRESTORE) api_Backend_ldap2(options.host_name, options.setup_ca, connect=True) @@ -186,6 +188,11 @@ def main(): # setup CA ############################################################## with redirect_stdout(ansible_log): + if NUM_VERSION >= 40604: + custodia = custodiainstance.get_custodia_instance( + options, custodiainstance.CustodiaModes.MASTER_PEER) + custodia.create_instance() + if options.setup_ca: if not options.external_cert_files and options.external_ca: # stage 1 of external CA installation @@ -193,7 +200,10 @@ def main(): if n in options.__dict__} write_cache(cache_vars) - ca.install_step_0(False, None, options) + if NUM_VERSION >= 40604: + ca.install_step_0(False, None, options, custodia=custodia) + else: + ca.install_step_0(False, None, options) else: # Put the CA cert where other instances expect it x509.write_certificate(options._http_ca_cert, paths.IPA_CA_CRT) @@ -210,13 +220,15 @@ def main(): x509.write_certificate(options._http_ca_cert, paths.CA_BUNDLE_PEM) os.chmod(paths.CA_BUNDLE_PEM, 0o444) - with redirect_stdout(ansible_log): # we now need to enable ssl on the ds ds.enable_ssl() - if options.setup_ca: - with redirect_stdout(ansible_log): - ca.install_step_1(False, None, options) + if options.setup_ca: + with redirect_stdout(ansible_log): + if NUM_VERSION >= 40604: + ca.install_step_1(False, None, options, custodia=custodia) + else: + ca.install_step_1(False, None, options) ansible_module.exit_json(changed=True) diff --git a/roles/ipaserver/library/ipaserver_setup_ds.py b/roles/ipaserver/library/ipaserver_setup_ds.py index 062fd39c..f4aa9cba 100644 --- a/roles/ipaserver/library/ipaserver_setup_ds.py +++ b/roles/ipaserver/library/ipaserver_setup_ds.py @@ -151,7 +151,7 @@ def main(): ca_subject=options.ca_subject, hbac_allow=not options.no_hbac_allow, setup_pkinit=not options.no_pkinit) - if not options.dirsrv_cert_files: + if not options.dirsrv_cert_files and NUM_VERSION < 40690: ntpinstance.ntp_ldap_enable(options.host_name, ds.suffix, options.realm_name) diff --git a/roles/ipaserver/library/ipaserver_setup_kra.py b/roles/ipaserver/library/ipaserver_setup_kra.py index 3958d7aa..2982a73c 100644 --- a/roles/ipaserver/library/ipaserver_setup_kra.py +++ b/roles/ipaserver/library/ipaserver_setup_kra.py @@ -80,7 +80,14 @@ def main(): # setup kra ##################################################### with redirect_stdout(ansible_log): - kra.install(api, None, options) + if NUM_VERSION >= 40604: + custodia = custodiainstance.get_custodia_instance( + options, custodiainstance.CustodiaModes.MASTER_PEER) + custodia.create_instance() + + kra.install(api, None, options, custodia=custodia) + else: + kra.install(api, None, options) # done ########################################################## diff --git a/roles/ipaserver/library/ipaserver_setup_ntp.py b/roles/ipaserver/library/ipaserver_setup_ntp.py index 3de34ca9..9626c5bb 100644 --- a/roles/ipaserver/library/ipaserver_setup_ntp.py +++ b/roles/ipaserver/library/ipaserver_setup_ntp.py @@ -64,12 +64,28 @@ def main(): # setup NTP ##################################################### - ntpconf.force_ntpd(sstore) - ntp = ntpinstance.NTPInstance(fstore) - ntp.set_output(ansible_log) - with redirect_stdout(ansible_log): - if not ntp.is_configured(): - ntp.create_instance() + if time_service == "chronyd": + # We have to sync time before certificate handling on master. + # As chrony configuration is moved from client here, unconfiguration of + # chrony will be handled here in uninstall() method as well by invoking + # the ipa-server-install --uninstall + ansible_module.log("Synchronizing time") + options.ntp_servers = None + options.ntp_pool = None + if sync_time(options, fstore, sstore): + ansible_module.log("Time synchronization was successful.") + else: + ansible_module.warn("IPA was unable to sync time with chrony!") + ansible_module.warn("Time synchronization is required for IPA " + "to work correctly") + else: + # Configure ntpd + timeconf.force_ntpd(sstore) + ntp = ntpinstance.NTPInstance(fstore) + ntp.set_output(ansible_log) + with redirect_stdout(ansible_log): + if not ntp.is_configured(): + ntp.create_instance() # done ########################################################## diff --git a/roles/ipaserver/library/ipaserver_test.py b/roles/ipaserver/library/ipaserver_test.py index 975df0da..a519e63d 100644 --- a/roles/ipaserver/library/ipaserver_test.py +++ b/roles/ipaserver/library/ipaserver_test.py @@ -506,6 +506,8 @@ def main(): tasks.check_ipv6_stack_enabled() tasks.check_selinux_status() + if check_ldap_conf is not None: + check_ldap_conf() _installation_cleanup = True if not options.external_ca and not options.external_cert_files and \ @@ -515,17 +517,18 @@ def main(): if not options.no_ntp: try: - ntpconf.check_timedate_services() - except ntpconf.NTPConflictingService as e: + timeconf.check_timedate_services() + except timeconf.NTPConflictingService as e: ansible_module.log("Conflicting time&date synchronization service '%s'" - " will be disabled in favor of ntpd" % \ - e.conflicting_service) - except ntpconf.NTPConfigurationError: + " will be disabled in favor of %s" % \ + (e.conflicting_service, time_service)) + except timeconf.NTPConfigurationError: pass - # Check to see if httpd is already configured to listen on 443 - if httpinstance.httpd_443_configured(): - ansible_module.fail_json(msg="httpd is already configured to listen on 443.") + if hasattr(httpinstance, "httpd_443_configured"): + # Check to see if httpd is already configured to listen on 443 + if httpinstance.httpd_443_configured(): + ansible_module.fail_json(msg="httpd is already configured to listen on 443.") if not options.external_cert_files: # Make sure the 389-ds ports are available @@ -534,20 +537,6 @@ def main(): except ScriptError as e: ansible_module.fail_json(msg=e) - if not options.no_ntp: - try: - ntpconf.check_timedate_services() - except ntpconf.NTPConflictingService as e: - ansible_module.warn( - "Conflicting time&date synchronization service " - "'%s' will be disabled" % e.conflicting_service) - except ntpconf.NTPConfigurationError: - pass - - # Check to see if httpd is already configured to listen on 443 - if httpinstance.httpd_443_configured(): - ansible_module.fail_json(msg="httpd is already configured to listen on 443.") - # check bind packages are installed if options.setup_dns: # Don't require an external DNS to say who we are if we are @@ -560,12 +549,9 @@ def main(): else: options.host_default = get_fqdn() - _host_name_overridden = False try: verify_fqdn(options.host_default, options.no_host_dns) options.host_name = options.host_default - if options.host_default != get_fqdn(): - _host_name_overridden = True except BadHostError as e: ansible_module.fail_json(msg=e) options.host_name = options.host_name.lower() @@ -581,6 +567,11 @@ def main(): if not options.realm_name: options.realm_name = options.domain_name options.realm_name = options.realm_name.upper() + if NUM_VERSION >= 40690: + try: + validate_domain_name(options.realm_name, entity="realm") + except ValueError as e: + raise ScriptError("Invalid realm name: {}".format(unicode(e))) if not options.setup_adtrust: # If domain name and realm does not match, IPA server will not be able @@ -686,7 +677,7 @@ def main(): fd.write("basedn=%s\n" % ipautil.realm_to_suffix(options.realm_name)) fd.write("realm=%s\n" % options.realm_name) fd.write("domain=%s\n" % options.domain_name) - fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % format_netloc(options.host_name)) + fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % ipautil.format_netloc(options.host_name)) fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % installutils.realm_to_serverid(options.realm_name)) if options.setup_ca: @@ -744,6 +735,9 @@ def main(): except OSError: ansible_module.fail_json(msg="Could not remove %s" % ipa_tempdir) + # Always set _host_name_overridden + options._host_name_overridden = bool(options.host_name) + # done ################################################################## ansible_module.exit_json(changed=True, @@ -753,7 +747,7 @@ def main(): realm=options.realm_name, ip_addresses=[ str(ip) for ip in ip_addresses ], hostname=options.host_name, - _hostname_overridden=_host_name_overridden, + _hostname_overridden=options._host_name_overridden, no_host_dns=options.no_host_dns, ### server ### setup_adtrust=options.setup_adtrust, diff --git a/roles/ipaserver/tasks/install.yml b/roles/ipaserver/tasks/install.yml index 1bfaf6e0..d88f7994 100644 --- a/roles/ipaserver/tasks/install.yml +++ b/roles/ipaserver/tasks/install.yml @@ -125,8 +125,9 @@ setup_adtrust: "{{ result_ipaserver_test.setup_adtrust }}" setup_kra: "{{ result_ipaserver_test.setup_kra }}" setup_dns: "{{ ipaserver_setup_dns }}" - #no_pkinit: "{{ result_ipaserver_test.no_pkinit }}" ### certificate system ### + # external_ca + # external_cert_files subject_base: "{{ result_ipaserver_test.subject_base }}" ca_subject: "{{ result_ipaserver_test.ca_subject }}" ### dns ### @@ -138,6 +139,11 @@ no_forwarders: "{{ ipaserver_no_forwarders }}" auto_forwarders: "{{ ipaserver_auto_forwarders }}" no_dnssec_validation: "{{ result_ipaserver_test.no_dnssec_validation }}" + ### ad trust ### + # enable_compat + # netbios_name + # rid_base + # secondary_rid_base ### additional ### setup_ca: "{{ result_ipaserver_test.setup_ca }}" _hostname_overridden: "{{ result_ipaserver_test._hostname_overridden }}" @@ -329,13 +335,9 @@ ipaclient_on_master: yes ipaclient_domain: "{{ result_ipaserver_test.domain }}" ipaclient_realm: "{{ result_ipaserver_test.realm }}" - ipaclient_server: "{{ result_ipaserver_test.hostname }}" + ipaclient_servers: [ "{{ result_ipaserver_test.hostname }}" ] ipaclient_hostname: "{{ result_ipaserver_test.hostname }}" - #ipaclient_no_dns_sshfp: "{{ ipaclient_no_dns_sshfp }}" - #ipaclient_ssh_trust_dns: "{{ ipaclient_ssh_trust_dns }}" - #ipaclient_no_ssh: "{{ ipaclient_no_ssh }}" - #ipaclient_no_sshd: "{{ ipaclient_no_sshd }}" - #ipaclient_mkhomedir: "{{ ipaclient_mkhomedir }}" + ipaclient_no_ntp: "{{ 'true' if result_ipaserver_test.ipa_python_version >= 40690 else 'false' }}" #- name: Install - Setup client # command: > -- GitLab