Blob Blame History Raw
From 07469b2cc7bd1478836a1c755b301dbf9234d61a Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jcholast@redhat.com>
Date: Mon, 22 May 2017 08:15:14 +0000
Subject: [PATCH] httpinstance: wait until the service entry is replicated

Wait until the local HTTP service entry is replicated to the remote master
before requesting the server certificate.

This prevents a replication conflict between the service entry added
locally and service entry added remotely when requesting the certificate.

https://pagure.io/freeipa/issue/6867

Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
Reviewed-By: Martin Basti <mbasti@redhat.com>
---
 ipaserver/install/httpinstance.py          | 29 +++++++++++++++++++++++++++--
 ipaserver/install/server/install.py        |  4 ++--
 ipaserver/install/server/replicainstall.py |  5 +++--
 3 files changed, 32 insertions(+), 6 deletions(-)

diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index c76a1a4e484c5777ced92761916c1c586e8b2d5d..12fdddccc26b0c1132bcdca7fe2249a85997892e 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -32,9 +32,11 @@ import six
 from augeas import Augeas
 
 from ipalib.install import certmonger
+from ipapython import ipaldap
 from ipapython.certdb import (IPA_CA_TRUST_FLAGS,
                               EXTERNAL_CA_TRUST_FLAGS,
                               TRUSTED_PEER_TRUST_FLAGS)
+from ipaserver.install import replication
 from ipaserver.install import service
 from ipaserver.install import certs
 from ipaserver.install import installutils
@@ -127,12 +129,15 @@ class HTTPInstance(service.Service):
 
     subject_base = ipautil.dn_attribute_property('_subject_base')
 
-    def create_instance(self, realm, fqdn, domain_name, pkcs12_info=None,
+    def create_instance(self, realm, fqdn, domain_name, dm_password=None,
+                        pkcs12_info=None,
                         subject_base=None, auto_redirect=True, ca_file=None,
-                        ca_is_configured=None, promote=False):
+                        ca_is_configured=None, promote=False,
+                        master_fqdn=None):
         self.fqdn = fqdn
         self.realm = realm
         self.domain = domain_name
+        self.dm_password = dm_password
         self.suffix = ipautil.realm_to_suffix(self.realm)
         self.pkcs12_info = pkcs12_info
         self.dercert = None
@@ -148,6 +153,7 @@ class HTTPInstance(service.Service):
         if ca_is_configured is not None:
             self.ca_is_configured = ca_is_configured
         self.promote = promote
+        self.master_fqdn = master_fqdn
 
         self.step("stopping httpd", self.__stop)
         self.step("setting mod_nss port to 443", self.__set_mod_nss_port)
@@ -577,3 +583,22 @@ class HTTPInstance(service.Service):
         db = certs.CertDB(self.realm, nssdir=paths.HTTPD_ALIAS_DIR)
         db.track_server_cert(self.cert_nickname, self.principal,
                              db.passwd_fname, 'restart_httpd')
+
+    def request_service_keytab(self):
+        super(HTTPInstance, self).request_service_keytab()
+
+        if self.master_fqdn is not None:
+            service_dn = DN(('krbprincipalname', self.principal),
+                            api.env.container_service,
+                            self.suffix)
+
+            ldap_uri = ipaldap.get_ldap_uri(self.master_fqdn)
+            with ipaldap.LDAPClient(ldap_uri,
+                                    start_tls=not self.promote,
+                                    cacert=paths.IPA_CA_CRT) as remote_ldap:
+                if self.promote:
+                    remote_ldap.gssapi_bind()
+                else:
+                    remote_ldap.simple_bind(ipaldap.DIRMAN_DN,
+                                            self.dm_password)
+                replication.wait_for_entry(remote_ldap, service_dn, timeout=60)
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
index 03380b8d0e9150224b014a1a174d7ea81ccdcf00..9dcf903f4582740f007c049fae3ec247ddf52aef 100644
--- a/ipaserver/install/server/install.py
+++ b/ipaserver/install/server/install.py
@@ -830,13 +830,13 @@ def install(installer):
     http = httpinstance.HTTPInstance(fstore)
     if options.http_cert_files:
         http.create_instance(
-            realm_name, host_name, domain_name,
+            realm_name, host_name, domain_name, dm_password,
             pkcs12_info=http_pkcs12_info, subject_base=options.subject_base,
             auto_redirect=not options.no_ui_redirect,
             ca_is_configured=setup_ca)
     else:
         http.create_instance(
-            realm_name, host_name, domain_name,
+            realm_name, host_name, domain_name, dm_password,
             subject_base=options.subject_base,
             auto_redirect=not options.no_ui_redirect,
             ca_is_configured=setup_ca)
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index b30133ffa22d410452ae04624d49db209175bed9..20eaf98397101b49c751c325afc0591e0babcc18 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -163,9 +163,10 @@ def install_http(config, auto_redirect, ca_is_configured, ca_file,
     http = httpinstance.HTTPInstance()
     http.create_instance(
         config.realm_name, config.host_name, config.domain_name,
-        pkcs12_info, auto_redirect=auto_redirect, ca_file=ca_file,
+        config.dirman_password, pkcs12_info,
+        auto_redirect=auto_redirect, ca_file=ca_file,
         ca_is_configured=ca_is_configured, promote=promote,
-        subject_base=config.subject_base)
+        subject_base=config.subject_base, master_fqdn=config.master_host_name)
 
     return http
 
-- 
2.9.4