From e6f8f10790fc4e632f7b258622d44ff4f99e1824 Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Thu, 21 Jun 2018 13:36:51 +0200
Subject: [PATCH] ipareplica: 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.
- custodia instance needed for ca and kra
- Use of create_ipa_conf with changed setting in setup_http for install_http,
  reverted back afterwards.
---
 module_utils/ansible_ipa_replica.py           | 16 ++++++++--
 .../ipareplica/library/ipareplica_prepare.py  |  4 ++-
 .../ipareplica/library/ipareplica_setup_ca.py | 12 +++++++-
 .../library/ipareplica_setup_custodia.py      | 21 ++++++++++----
 .../library/ipareplica_setup_dns.py           |  6 ++--
 .../ipareplica/library/ipareplica_setup_ds.py |  6 ++--
 .../library/ipareplica_setup_http.py          | 29 ++++++++++++++++++-
 .../library/ipareplica_setup_kra.py           | 12 +++++++-
 roles/ipareplica/tasks/install.yml            |  3 +-
 9 files changed, 90 insertions(+), 19 deletions(-)

diff --git a/module_utils/ansible_ipa_replica.py b/module_utils/ansible_ipa_replica.py
index d26f9d27..3b1fbf73 100644
--- a/module_utils/ansible_ipa_replica.py
+++ b/module_utils/ansible_ipa_replica.py
@@ -59,7 +59,6 @@ if NUM_VERSION >= 40600:
     import six
 
     from ipaclient.install.ipachangeconf import IPAChangeConf
-    import ipaclient.install.ntpconf
     from ipalib.install import certstore, sysrestore
     from ipalib.install.kinit import kinit_keytab
     from ipapython import ipaldap, ipautil, kernel_keyring
@@ -78,8 +77,7 @@ if NUM_VERSION >= 40600:
     from ipaserver.install import (
         adtrust, bindinstance, ca, certs, dns, dsinstance, httpinstance,
         installutils, kra, krbinstance,
-        ntpinstance, otpdinstance, custodiainstance, service,
-        upgradeinstance)
+        otpdinstance, custodiainstance, service, upgradeinstance)
     from ipaserver.install.installutils import (
         create_replica_config, ReplicaConfig, load_pkcs12, is_ipa_configured)
     from ipaserver.install.replication import (
@@ -103,6 +101,18 @@ if NUM_VERSION >= 40600:
     if six.PY3:
         unicode = str
 
+    try:
+        from ipaclient.install import timeconf
+        time_service = "chronyd"
+        ntpinstance = None
+    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"
+
 else:
     # IPA version < 4.6
 
diff --git a/roles/ipareplica/library/ipareplica_prepare.py b/roles/ipareplica/library/ipareplica_prepare.py
index ab9313a3..d3c71999 100644
--- a/roles/ipareplica/library/ipareplica_prepare.py
+++ b/roles/ipareplica/library/ipareplica_prepare.py
@@ -265,7 +265,9 @@ def main():
                 # do not use ensure_enrolled, it uses redirect_output
                 # ensure_enrolled(installer)
 
-                args = [paths.IPA_CLIENT_INSTALL, "--unattended", "--no-ntp"]
+                args = [paths.IPA_CLIENT_INSTALL, "--unattended"]
+                if NUM_VERSION < 40690:
+                    args.append("--no-ntp")
                 stdin = None
                 nolog = []
 
diff --git a/roles/ipareplica/library/ipareplica_setup_ca.py b/roles/ipareplica/library/ipareplica_setup_ca.py
index b322da58..f4de7592 100644
--- a/roles/ipareplica/library/ipareplica_setup_ca.py
+++ b/roles/ipareplica/library/ipareplica_setup_ca.py
@@ -189,6 +189,7 @@ def main():
     config.master_host_name = config_master_host_name
     config.ca_host_name = config_ca_host_name
     config.ips = config_ips
+    config.promote = options.promote
 
     remote_api = gen_remote_api(config.master_host_name, paths.ETC_IPA)
     options._remote_api = remote_api
@@ -208,7 +209,16 @@ def main():
         options.domain_name = config.domain_name
         options.host_name = config.host_name
         options.dm_password = config.dirman_password
-        ca.install(False, config, options)
+        if NUM_VERSION < 40690:
+            ca.install(False, config, options)
+        else:
+            if ca_enabled:
+                mode = custodiainstance.CustodiaModes.CA_PEER
+            else:
+                mode = custodiainstance.CustodiaModes.MASTER_PEER
+            custodia = custodiainstance.get_custodia_instance(config, mode)
+
+            ca.install(False, config, options, custodia=custodia)
 
     # done #
 
diff --git a/roles/ipareplica/library/ipareplica_setup_custodia.py b/roles/ipareplica/library/ipareplica_setup_custodia.py
index 628eb495..37b11f1f 100644
--- a/roles/ipareplica/library/ipareplica_setup_custodia.py
+++ b/roles/ipareplica/library/ipareplica_setup_custodia.py
@@ -148,6 +148,7 @@ def main():
     api_bootstrap_finalize(env)
     config = gen_ReplicaConfig()
     config.dirman_password = dirman_password
+    config.promote = installer.promote
 
     remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
     #installer._remote_api = remote_api
@@ -163,13 +164,21 @@ def main():
     with redirect_stdout(ansible_log):
         ansible_log.debug("-- INSTALL_CUSTODIA --")
 
-        custodia = custodiainstance.CustodiaInstance(config.host_name,
-                                                     config.realm_name)
-        if promote:
-            ansible_log.debug("-- CUSTODIA CREATE_REPLICA --")
-            custodia.create_replica(config.master_host_name)
+        if NUM_VERSION < 40690:
+            custodia = custodiainstance.CustodiaInstance(config.host_name,
+                                                         config.realm_name)
+            if promote:
+                ansible_log.debug("-- CUSTODIA CREATE_REPLICA --")
+                custodia.create_replica(config.master_host_name)
+            else:
+                ansible_log.debug("-- CUSTODIA CREATE_INSTANCE --")
+                custodia.create_instance()
         else:
-            ansible_log.debug("-- CUSTODIA CREATE_INSTANCE --")
+            if ca_enabled:
+                mode = custodiainstance.CustodiaModes.CA_PEER
+            else:
+                mode = custodiainstance.CustodiaModes.MASTER_PEER
+            custodia = custodiainstance.get_custodia_instance(config, mode)
             custodia.create_instance()
 
     # done #
diff --git a/roles/ipareplica/library/ipareplica_setup_dns.py b/roles/ipareplica/library/ipareplica_setup_dns.py
index 6d6701a7..10675698 100644
--- a/roles/ipareplica/library/ipareplica_setup_dns.py
+++ b/roles/ipareplica/library/ipareplica_setup_dns.py
@@ -52,7 +52,7 @@ options:
   _top_dir:
     description: 
     required: yes
-  config_setup_ca:
+  setup_ca:
     description: 
     required: yes
   config_master_host_name:
@@ -82,7 +82,7 @@ def main():
             ### additional ###
             ccache=dict(required=True),
             _top_dir = dict(required=True),
-            config_setup_ca=dict(required=True),
+            setup_ca=dict(required=True),
             config_master_host_name=dict(required=True),
         ),
         supports_check_mode = True,
@@ -105,7 +105,7 @@ def main():
     ccache = ansible_module.params.get('ccache')
     os.environ['KRB5CCNAME'] = ccache
     options._top_dir = ansible_module.params.get('_top_dir')
-    config_setup_ca = ansible_module.params.get('config_setup_ca')
+    options.setup_ca = ansible_module.params.get('setup_ca')
     config_master_host_name = ansible_module.params.get('config_master_host_name')
 
     # init #
diff --git a/roles/ipareplica/library/ipareplica_setup_ds.py b/roles/ipareplica/library/ipareplica_setup_ds.py
index 24b976aa..02a11c76 100644
--- a/roles/ipareplica/library/ipareplica_setup_ds.py
+++ b/roles/ipareplica/library/ipareplica_setup_ds.py
@@ -289,6 +289,7 @@ def main():
     config.master_host_name = config_master_host_name
     config.ca_host_name = config_ca_host_name
     config.ips = config_ips
+    config.promote = installer.promote
 
     remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
     installer._remote_api = remote_api
@@ -324,8 +325,9 @@ def main():
         install_dns_records(config, options, remote_api)
 
         ansible_log.debug("-- NTP LDAP ENABLE --")
-        ntpinstance.ntp_ldap_enable(config.host_name, ds.suffix,
-                                    remote_api.env.realm)
+        if ntpinstance is not None:
+            ntpinstance.ntp_ldap_enable(config.host_name, ds.suffix,
+                                        remote_api.env.realm)
     finally:
         if conn.isconnected():
             ansible_log.debug("-- DISCONNECT --")
diff --git a/roles/ipareplica/library/ipareplica_setup_http.py b/roles/ipareplica/library/ipareplica_setup_http.py
index ff6450a3..98afd1b0 100644
--- a/roles/ipareplica/library/ipareplica_setup_http.py
+++ b/roles/ipareplica/library/ipareplica_setup_http.py
@@ -97,6 +97,7 @@ def main():
             #### certificate system ###
             subject_base=dict(required=True),
             config_master_host_name=dict(required=True),
+            config_ca_host_name=dict(required=True),
             ccache=dict(required=True),
             _ca_enabled=dict(required=False, type='bool'),
             _ca_file=dict(required=False),
@@ -123,6 +124,7 @@ def main():
         options.subject_base = DN(options.subject_base)
     ### additional ###
     master_host_name = ansible_module.params.get('config_master_host_name')
+    ca_host_name = ansible_module.params.get('config_master_host_name')
     ccache = ansible_module.params.get('ccache')
     os.environ['KRB5CCNAME'] = ccache
     #os.environ['KRB5CCNAME'] = ansible_module.params.get('installer_ccache')
@@ -146,8 +148,12 @@ def main():
                                          constants.DEFAULT_CONFIG)
     api_bootstrap_finalize(env)
     config = gen_ReplicaConfig()
-    config.dirman_password = dirman_password
     config.subject_base = options.subject_base
+    config.dirman_password = dirman_password
+    config.setup_ca = options.setup_ca
+    #config.master_host_name = master_host_name
+    config.ca_host_name = ca_host_name
+    config.promote = installer.promote
 
     remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
     #installer._remote_api = remote_api
@@ -164,6 +170,24 @@ def main():
     with redirect_stdout(ansible_log):
         ansible_log.debug("-- INSTALL_HTTP --")
 
+        # We need to point to the master when certmonger asks for
+        # HTTP certificate.
+        # During http installation, the HTTP/hostname principal is created
+        # locally then the installer waits for the entry to appear on the
+        # master selected for the installation.
+        # In a later step, the installer requests a SSL certificate through
+        # Certmonger (and the op adds the principal if it does not exist yet).
+        # If xmlrpc_uri points to the soon-to-be replica,
+        # the httpd service is not ready yet to handle certmonger requests
+        # and certmonger tries to find another master. The master can be
+        # different from the one selected for the installation, and it is
+        # possible that the principal has not been replicated yet. This
+        # may lead to a replication conflict.
+        # This is why we need to force the use of the same master by
+        # setting xmlrpc_uri
+        create_ipa_conf(fstore, config, ca_enabled,
+                        master=config.master_host_name)
+
         install_http(
             config,
             auto_redirect=not options.no_ui_redirect,
@@ -172,6 +196,9 @@ def main():
             ca_is_configured=ca_enabled,
             ca_file=cafile)
 
+        # Need to point back to ourself after the cert for HTTP is obtained
+        create_ipa_conf(fstore, config, ca_enabled)
+
     # done #
 
     ansible_module.exit_json(changed=True)
diff --git a/roles/ipareplica/library/ipareplica_setup_kra.py b/roles/ipareplica/library/ipareplica_setup_kra.py
index 5a96fd9f..b585cb17 100644
--- a/roles/ipareplica/library/ipareplica_setup_kra.py
+++ b/roles/ipareplica/library/ipareplica_setup_kra.py
@@ -205,6 +205,7 @@ def main():
     api_bootstrap_finalize(env)
     config = gen_ReplicaConfig()
     config.subject_base = options.subject_base
+    config.promote = installer.promote
 
     remote_api = gen_remote_api(master_host_name, paths.ETC_IPA)
     installer._remote_api = remote_api
@@ -215,7 +216,16 @@ def main():
     with redirect_stdout(ansible_log):
         ansible_log.debug("-- INSTALL KRA --")
 
-        kra.install(api, config, options)
+        if NUM_VERSION < 40690:
+            kra.install(api, config, options)
+        else:
+            if ca_enabled:
+                mode = custodiainstance.CustodiaModes.CA_PEER
+            else:
+                mode = custodiainstance.CustodiaModes.MASTER_PEER
+            custodia = custodiainstance.get_custodia_instance(config, mode)
+
+            kra.install(api, config, options, custodia=custodia)
 
     # done #
 
diff --git a/roles/ipareplica/tasks/install.yml b/roles/ipareplica/tasks/install.yml
index de5576fb..47c44800 100644
--- a/roles/ipareplica/tasks/install.yml
+++ b/roles/ipareplica/tasks/install.yml
@@ -373,6 +373,7 @@
       subject_base: "{{ result_ipareplica_prepare.subject_base }}"
       ### additional ###
       config_master_host_name: "{{ result_ipareplica_install_ca_certs.config_master_host_name }}"
+      config_ca_host_name: "{{ result_ipareplica_prepare.config_ca_host_name }}"
       ccache: "{{ result_ipareplica_prepare.ccache }}"
       _ca_enabled: "{{ result_ipareplica_prepare._ca_enabled }}"
       _ca_file: "{{ result_ipareplica_prepare._ca_file }}"
@@ -586,7 +587,7 @@
       ### additional ###
       ccache: "{{ result_ipareplica_prepare.ccache }}"
       _top_dir: "{{ result_ipareplica_prepare._top_dir }}"
-      config_setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
+      setup_ca: "{{ result_ipareplica_prepare.config_setup_ca }}"
       config_master_host_name: "{{ result_ipareplica_prepare.config_master_host_name }}"
 
   - name: Install - Setup adtrust
-- 
GitLab