diff --git a/SOURCES/0220-ipa-otptoken-import-Make-PBKDF2-refer-to-the-pkcs5-n.patch b/SOURCES/0220-ipa-otptoken-import-Make-PBKDF2-refer-to-the-pkcs5-n.patch
new file mode 100644
index 0000000..b56a901
--- /dev/null
+++ b/SOURCES/0220-ipa-otptoken-import-Make-PBKDF2-refer-to-the-pkcs5-n.patch
@@ -0,0 +1,84 @@
+From 92f450a4b6eacb7950e5414d40d9949076cb096e Mon Sep 17 00:00:00 2001
+From: Nathaniel McCallum <npmccallum@redhat.com>
+Date: Tue, 20 Jun 2017 10:31:15 -0400
+Subject: [PATCH] ipa-otptoken-import: Make PBKDF2 refer to the pkcs5 namespace
+
+For some unknown reason, when I wrote the ipa-otptoken-import script
+I used bad input data which had the PBKDF2 parameters in the wrong
+XML namespace. I have corrected this input data to match RFC 6030.
+
+https://pagure.io/freeipa/issue/7035
+
+Signed-off-by: Nathaniel McCallum <npmccallum@redhat.com>
+Reviewed-By: Martin Basti <mbasti@redhat.com>
+Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
+---
+ ipaserver/install/ipa_otptoken_import.py      | 15 ++++++---------
+ ipatests/test_ipaserver/data/pskc-figure7.xml | 16 ++++++++--------
+ 2 files changed, 14 insertions(+), 17 deletions(-)
+
+diff --git a/ipaserver/install/ipa_otptoken_import.py b/ipaserver/install/ipa_otptoken_import.py
+index 2580e2cfc97f4960af68a5eae407a7ebe3c7a257..31225e96b55c20bd78e9a8650848a28cf9feef63 100644
+--- a/ipaserver/install/ipa_otptoken_import.py
++++ b/ipaserver/install/ipa_otptoken_import.py
+@@ -52,6 +52,7 @@ class ValidationError(Exception):
+ 
+ def fetchAll(element, xpath, conv=lambda x: x):
+     return [conv(e) for e in element.xpath(xpath, namespaces={
++        "pkcs5": "http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#",
+         "pskc": "urn:ietf:params:xml:ns:keyprov:pskc",
+         "xenc11": "http://www.w3.org/2009/xmlenc11#",
+         "xenc": "http://www.w3.org/2001/04/xmlenc#",
+@@ -175,18 +176,14 @@ class XMLKeyDerivation(six.with_metaclass(abc.ABCMeta, object)):
+ 
+ class PBKDF2KeyDerivation(XMLKeyDerivation):
+     def __init__(self, enckey):
+-        params = fetch(enckey, "./xenc11:DerivedKey/xenc11:KeyDerivationMethod/xenc11:PBKDF2-params")
++        params = fetch(enckey, "./xenc11:DerivedKey/xenc11:KeyDerivationMethod/pkcs5:PBKDF2-params")
+         if params is None:
+             raise ValueError("XML file is missing PBKDF2 parameters!")
+ 
+-        salt = fetch(
+-            params, "./xenc11:Salt/xenc11:Specified/text()", base64.b64decode)
+-        itrs = fetch(
+-            params, "./xenc11:IterationCount/text()", int)
+-        klen = fetch(
+-            params, "./xenc11:KeyLength/text()", int)
+-        hmod = fetch(
+-            params, "./xenc11:PRF/@Algorithm", convertHMACType, hashes.SHA1)
++        salt = fetch(params, "./Salt/Specified/text()", base64.b64decode)
++        itrs = fetch(params, "./IterationCount/text()", int)
++        klen = fetch(params, "./KeyLength/text()", int)
++        hmod = fetch(params, "./PRF/@Algorithm", convertHMACType, hashes.SHA1)
+
+         if salt is None:
+             raise ValueError("XML file is missing PBKDF2 salt!")
+diff --git a/ipatests/test_ipaserver/data/pskc-figure7.xml b/ipatests/test_ipaserver/data/pskc-figure7.xml
+index 1fb04fc319d7572d9d25ff34a0ce3378a939dfc6..808e272a5469a1c9eb4087ed53e0907bb80b39ad 100644
+--- a/ipatests/test_ipaserver/data/pskc-figure7.xml
++++ b/ipatests/test_ipaserver/data/pskc-figure7.xml
+@@ -8,14 +8,14 @@
+     <xenc11:DerivedKey>
+       <xenc11:KeyDerivationMethod
+ 	  Algorithm="http://www.rsasecurity.com/rsalabs/pkcs/schemas/pkcs-5v2-0#pbkdf2">
+-        <xenc11:PBKDF2-params>
+-          <xenc11:Salt>
+-            <xenc11:Specified>Ej7/PEpyEpw=</xenc11:Specified>
+-          </xenc11:Salt>
+-          <xenc11:IterationCount>1000</xenc11:IterationCount>
+-          <xenc11:KeyLength>16</xenc11:KeyLength>
+-          <xenc11:PRF/>
+-        </xenc11:PBKDF2-params>
++        <pkcs5:PBKDF2-params>
++          <Salt>
++            <Specified>Ej7/PEpyEpw=</Specified>
++          </Salt>
++          <IterationCount>1000</IterationCount>
++          <KeyLength>16</KeyLength>
++          <PRF/>
++        </pkcs5:PBKDF2-params>
+       </xenc11:KeyDerivationMethod>
+       <xenc:ReferenceList>
+         <xenc:DataReference URI="#ED"/>
+--
+2.13.5
\ No newline at end of file
diff --git a/SOURCES/0221-Adds-whoami-DS-plugin-in-case-that-plugin-is-missing.patch b/SOURCES/0221-Adds-whoami-DS-plugin-in-case-that-plugin-is-missing.patch
new file mode 100644
index 0000000..e247dd1
--- /dev/null
+++ b/SOURCES/0221-Adds-whoami-DS-plugin-in-case-that-plugin-is-missing.patch
@@ -0,0 +1,59 @@
+From d06b29772609d14dccfe0d556fdb83140fcb2b3f Mon Sep 17 00:00:00 2001
+From: Pavel Vomacka <pvomacka@redhat.com>
+Date: Mon, 28 Aug 2017 10:51:53 +0200
+Subject: [PATCH] Adds whoami DS plugin in case that plugin is missing
+
+When first installation of IPA has been done when whoami
+plugin was not enabled in DS by default and then IPA was
+upgraded to newer versions, then after upgrade to IPA 4.5
+WebUI stops working. This is caused by new requirement on
+whoami DS plugin which is used to obtain information about
+logged in entity.
+
+This fix adds the whoami plugin during update in case that the plugin
+is not enabled.
+
+https://pagure.io/freeipa/issue/7126
+
+Reviewed-By: Tibor Dudlak <tdudlak@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+---
+ install/updates/20-whoami.update | 14 ++++++++++++++
+ install/updates/Makefile.am      |  1 +
+ 2 files changed, 15 insertions(+)
+ create mode 100644 install/updates/20-whoami.update
+
+diff --git a/install/updates/20-whoami.update b/install/updates/20-whoami.update
+new file mode 100644
+index 0000000000000000000000000000000000000000..ed2c6cbd772ec1c2b664e450463bb64d61b1ceab
+--- /dev/null
++++ b/install/updates/20-whoami.update
+@@ -0,0 +1,14 @@
++dn: cn=whoami,cn=plugins,cn=config
++default:objectClass: top
++default:objectClass: nsSlapdPlugin
++default:objectClass: extensibleObject
++default:cn: whoami
++default:nsslapd-plugin-depends-on-type: database
++default:nsslapd-pluginDescription: whoami extended operation plugin
++default:nsslapd-pluginEnabled: on
++default:nsslapd-pluginId: whoami-plugin
++default:nsslapd-pluginInitfunc: whoami_init
++default:nsslapd-pluginPath: libwhoami-plugin
++default:nsslapd-pluginType: extendedop
++default:nsslapd-pluginVendor: 389 Project
++default:nsslapd-pluginVersion: 1.0
+diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am
+index e18d01127b592a6c7941729d6160d10fb2d3e76c..ae3d3e0528929a30922f0395d7092654dd753a64 100644
+--- a/install/updates/Makefile.am
++++ b/install/updates/Makefile.am
+@@ -24,6 +24,7 @@ app_DATA =				\
+ 	20-idoverride_index.update	\
+ 	20-uuid.update  \
+ 	20-default_password_policy.update \
++	20-whoami.update	\
+ 	21-replicas_container.update	\
+ 	21-ca_renewal_container.update	\
+ 	21-certstore_container.update	\
+--
+2.13.5
\ No newline at end of file
diff --git a/SOURCES/0222-Fix-ipa-config-mod-ca-renewal-master.patch b/SOURCES/0222-Fix-ipa-config-mod-ca-renewal-master.patch
new file mode 100644
index 0000000..b4778ba
--- /dev/null
+++ b/SOURCES/0222-Fix-ipa-config-mod-ca-renewal-master.patch
@@ -0,0 +1,88 @@
+From 9a8352637aeb32ddffd83f4477695ec290da8429 Mon Sep 17 00:00:00 2001
+From: Florence Blanc-Renaud <flo@redhat.com>
+Date: Wed, 23 Aug 2017 16:31:18 +0200
+Subject: [PATCH] Fix ipa config-mod --ca-renewal-master
+
+commit bddb90f38a3505a2768862d2f814c5e749a7dcde added the support for
+multivalued server attributes (for pkinit_server_server), but this
+introduced an API change where the setter and getter of ServerAttribute
+are expecting list of values.
+
+When a SingleValuedServerAttribute is used, we need to convert one elem
+into a list containing this elem and vice-versa, so that the ipa config-mod
+and ipa config_show APIs are not modified.
+
+https://pagure.io/freeipa/issue/7120
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
+---
+ ipaserver/plugins/serverroles.py            | 16 +++++++++++++++-
+ ipatests/test_ipaserver/test_serverroles.py |  4 ++--
+ 2 files changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/ipaserver/plugins/serverroles.py b/ipaserver/plugins/serverroles.py
+index e81635c3315cc3fca84450f43fb7df883aae57d9..04e21090657197b9267f2ffc05048399a7ce3d38 100644
+--- a/ipaserver/plugins/serverroles.py
++++ b/ipaserver/plugins/serverroles.py
+@@ -46,6 +46,7 @@ from ipalib import errors, _
+ from ipalib.backend import Backend
+ from ipalib.plugable import Registry
+ from ipaserver.servroles import (attribute_instances, ENABLED, role_instances)
++from ipaserver.servroles import SingleValuedServerAttribute
+ 
+ 
+ if six.PY3:
+@@ -136,13 +137,26 @@ class serverroles(Backend):
+ 
+         for name, attr in assoc_attributes.items():
+             attr_value = attr.get(self.api)
+-            result.update({name: attr_value})
++
++            if attr_value:
++                # attr can be a SingleValuedServerAttribute
++                # in this case, the API expects a value, not a list of values
++                if isinstance(attr, SingleValuedServerAttribute):
++                    attr_value = attr_value[0]
++                result.update({name: attr_value})
+ 
+         return result
+ 
+     def config_update(self, **attrs_values):
+         for attr, value in attrs_values.items():
+             try:
++                # when the attribute is single valued, it will be stored
++                # in a SingleValuedServerAttribute. The set method expects
++                # a list containing a single value.
++                # We need to convert value to a list containing value
++                if isinstance(self.attributes[attr],
++                              SingleValuedServerAttribute):
++                    value = [value]
+                 self.attributes[attr].set(self.api, value)
+             except KeyError:
+                 raise errors.NotFound(
+diff --git a/ipatests/test_ipaserver/test_serverroles.py b/ipatests/test_ipaserver/test_serverroles.py
+index 985c750b64f109e0a83686f31ddb3b8d4171072d..e8967517d0c65fb6e3daebf220cae7df38bfe044 100644
+--- a/ipatests/test_ipaserver/test_serverroles.py
++++ b/ipatests/test_ipaserver/test_serverroles.py
+@@ -715,7 +715,7 @@ class TestServerAttributes(object):
+         non_ca_fqdn = mock_masters.get_fqdn('trust-controller-dns')
+ 
+         with pytest.raises(errors.ValidationError):
+-            self.config_update(mock_api, **{attr_name: [non_ca_fqdn]})
++            self.config_update(mock_api, **{attr_name: non_ca_fqdn})
+ 
+     def test_set_unknown_attribute_on_master_raises_notfound(
+             self, mock_api, mock_masters):
+@@ -732,7 +732,7 @@ class TestServerAttributes(object):
+         original_renewal_master = self.config_retrieve(
+             role_name, mock_api)[attr_name]
+ 
+-        other_ca_server = [mock_masters.get_fqdn('trust-controller-ca')]
++        other_ca_server = mock_masters.get_fqdn('trust-controller-ca')
+ 
+         for host in (other_ca_server, original_renewal_master):
+             self.config_update(mock_api, **{attr_name: host})
+-- 
+2.13.5
+
diff --git a/SOURCES/0223-Backport-PR-988-to-ipa-4-5-Fix-Certificate-renewal-w.patch b/SOURCES/0223-Backport-PR-988-to-ipa-4-5-Fix-Certificate-renewal-w.patch
new file mode 100644
index 0000000..db614e2
--- /dev/null
+++ b/SOURCES/0223-Backport-PR-988-to-ipa-4-5-Fix-Certificate-renewal-w.patch
@@ -0,0 +1,60 @@
+From 21b0fdb48179e6060eff0ecb11ce6522983ccc00 Mon Sep 17 00:00:00 2001
+From: Florence Blanc-Renaud <flo@redhat.com>
+Date: Fri, 18 Aug 2017 18:02:57 +0200
+Subject: [PATCH] Backport PR 988 to ipa-4-5 Fix Certificate renewal (with ext
+ ca)
+
+Fix certificate renewal scripts that use IPACertificate object:
+- renew_ca_cert adds the C flag to the trust flags and needs to
+be adapted to IPACertificate object
+- ipa-cacert-manage: fix python3 encoding issue
+
+https://pagure.io/freeipa/issue/7106
+
+Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
+Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
+---
+ install/restart_scripts/renew_ca_cert  | 7 ++++++-
+ ipaserver/install/ipa_cacert_manage.py | 2 +-
+ 2 files changed, 7 insertions(+), 2 deletions(-)
+
+diff --git a/install/restart_scripts/renew_ca_cert b/install/restart_scripts/renew_ca_cert
+index bb31defc0e2bdca044e68ae067f42fb3bd41a57f..3bbf003bad47a189fd26df19e6ab137fcbb67ed0 100644
+--- a/install/restart_scripts/renew_ca_cert
++++ b/install/restart_scripts/renew_ca_cert
+@@ -35,6 +35,7 @@ from ipaserver.install import certs, cainstance, installutils
+ from ipaserver.plugins.ldap2 import ldap2
+ from ipaplatform import services
+ from ipaplatform.paths import paths
++from ipapython.certdb import TrustFlags
+
+
+ def _main():
+@@ -180,7 +181,11 @@ def _main():
+                 # Pass Dogtag's self-tests
+                 for ca_nick in db.find_root_cert(nickname)[-2:-1]:
+                     ca_flags = dict(cc[1:] for cc in ca_certs)[ca_nick]
+-                    db.trust_root_cert(ca_nick, 'C' + ca_flags)
++                    usages = ca_flags.usages or set()
++                    ca_flags_modified = TrustFlags(ca_flags.has_key,
++                        True, True,
++                        usages | {x509.EKU_SERVER_AUTH})
++                    db.trust_root_cert(ca_nick, ca_flags_modified)
+             finally:
+                 if conn is not None and conn.isconnected():
+                     conn.disconnect()
+diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
+index e88e8b63ae94759ac835f3b3b31b0735d68a67b0..fcbf09155a3abc9ce9481aa2519ed39aaa6aa9bb 100644
+--- a/ipaserver/install/ipa_cacert_manage.py
++++ b/ipaserver/install/ipa_cacert_manage.py
+@@ -218,7 +218,7 @@ class CACertManage(admintool.AdminTool):
+         cert_file, ca_file = installutils.load_external_cert(
+             options.external_cert_files, DN(old_cert_obj.subject))
+ 
+-        with open(cert_file.name) as f:
++        with open(cert_file.name, 'rb') as f:
+             new_cert_data = f.read()
+         new_cert_der = x509.normalize_certificate(new_cert_data)
+         new_cert_obj = x509.load_certificate(new_cert_der, x509.DER)
+--
+2.13.5
\ No newline at end of file
diff --git a/SOURCES/0224-Backport-PR-1008-to-ipa-4-5-Fix-ipa-server-upgrade-T.patch b/SOURCES/0224-Backport-PR-1008-to-ipa-4-5-Fix-ipa-server-upgrade-T.patch
new file mode 100644
index 0000000..7de886b
--- /dev/null
+++ b/SOURCES/0224-Backport-PR-1008-to-ipa-4-5-Fix-ipa-server-upgrade-T.patch
@@ -0,0 +1,213 @@
+From c9fb09190ac243bcf45622693944d7e6785141b4 Mon Sep 17 00:00:00 2001
+From: Florence Blanc-Renaud <flo@redhat.com>
+Date: Mon, 28 Aug 2017 10:50:58 +0200
+Subject: [PATCH] Backport PR 1008 to ipa-4-5 Fix ipa-server-upgrade: This
+ entry already exists
+
+ipa-server-upgrade fails when running the ipaload_cacrt plugin. The plugin
+finds all CA certificates in /etc/httpd/alias and uploads them in LDAP
+below cn=certificates,cn=ipa,cn=etc,$BASEDN.
+The issue happens because there is already an entry in LDAP for IPA CA, but
+with a different DN. The nickname in /etc/httpd/alias can differ from
+$DOMAIN IPA CA.
+
+To avoid the issue:
+1/ during upgrade, run a new plugin that removes duplicates and restarts ldap
+(to make sure that uniqueness attr plugin is working after the new plugin)
+2/ modify upload_cacert plugin so that it is using $DOMAIN IPA CA instead of
+cn=$nickname,cn=ipa,cn=etc,$BASEDN when uploading IPA CA.
+
+https://pagure.io/freeipa/issue/7125
+
+Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
+---
+ install/updates/90-post_upgrade_plugins.update     |  1 +
+ ipalib/install/certstore.py                        | 19 +++++
+ .../plugins/update_fix_duplicate_cacrt_in_ldap.py  | 84 ++++++++++++++++++++++
+ ipaserver/install/plugins/upload_cacrt.py          | 19 ++++-
+ 4 files changed, 120 insertions(+), 3 deletions(-)
+ create mode 100644 ipaserver/install/plugins/update_fix_duplicate_cacrt_in_ldap.py
+
+diff --git a/install/updates/90-post_upgrade_plugins.update b/install/updates/90-post_upgrade_plugins.update
+index 8477199e07d6729d5847e58bfa67d061bd1410c2..bbc3e29422fc0f139c2ca68a7033863e4c25f8cf 100644
+--- a/install/updates/90-post_upgrade_plugins.update
++++ b/install/updates/90-post_upgrade_plugins.update
+@@ -15,6 +15,7 @@ plugin: update_ca_renewal_master
+ plugin: update_idrange_type
+ plugin: update_pacs
+ plugin: update_service_principalalias
++plugin: update_fix_duplicate_cacrt_in_ldap
+ plugin: update_upload_cacrt
+ # update_ra_cert_store has to be executed after update_ca_renewal_master
+ plugin: update_ra_cert_store
+diff --git a/ipalib/install/certstore.py b/ipalib/install/certstore.py
+index bc2079fb12873444cbe6796eebfdfcfebd0e284d..76181fe47de585974f3fb33ec586f5c576adebb5 100644
+--- a/ipalib/install/certstore.py
++++ b/ipalib/install/certstore.py
+@@ -27,6 +27,7 @@ from pyasn1.error import PyAsn1Error
+ from ipapython.dn import DN
+ from ipapython.certdb import get_ca_nickname, TrustFlags
+ from ipalib import errors, x509
++from ipalib.constants import IPA_CA_CN
+ 
+ def _parse_cert(dercert):
+     try:
+@@ -381,3 +382,21 @@ def get_ca_certs_nss(ldap, base_dn, compat_realm, compat_ipa_ca,
+         nss_certs.append((cert, nickname, trust_flags))
+ 
+     return nss_certs
++
++
++def get_ca_subject(ldap, container_ca, base_dn):
++    """
++    Look for the IPA CA certificate subject.
++    """
++    dn = DN(('cn', IPA_CA_CN), container_ca, base_dn)
++    try:
++        cacert_subject = ldap.get_entry(dn)['ipacasubjectdn'][0]
++    except errors.NotFound:
++        # if the entry doesn't exist, we are dealing with a pre-v4.4
++        # installation, where the default CA subject was always based
++        # on the subject_base.
++        attrs = ldap.get_ipa_config()
++        subject_base = attrs.get('ipacertificatesubjectbase')[0]
++        cacert_subject = DN(('CN', 'Certificate Authority'), subject_base)
++
++    return cacert_subject
+diff --git a/ipaserver/install/plugins/update_fix_duplicate_cacrt_in_ldap.py b/ipaserver/install/plugins/update_fix_duplicate_cacrt_in_ldap.py
+new file mode 100644
+index 0000000000000000000000000000000000000000..cd4f13a8eb6b5bc9e04fcdd407907497528f8be1
+--- /dev/null
++++ b/ipaserver/install/plugins/update_fix_duplicate_cacrt_in_ldap.py
+@@ -0,0 +1,84 @@
++# Authors:
++#   Florence Blanc-Renaud <flo@redhat.com>
++#
++# Copyright (C) 2017  Red Hat
++# see file 'COPYING' for use and warranty information
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation, either version 3 of the License, or
++# (at your option) any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program.  If not, see <http://www.gnu.org/licenses/>.
++
++import logging
++
++from ipalib import Registry, errors
++from ipalib import Updater
++from ipalib.install import certstore
++from ipapython.dn import DN
++from ipapython.certdb import get_ca_nickname
++
++logger = logging.getLogger(__name__)
++
++register = Registry()
++
++
++@register()
++class update_fix_duplicate_cacrt_in_ldap(Updater):
++    """
++    When multiple entries exist for IPA CA cert in ldap, remove the duplicate
++
++    After this plugin, ds needs to be restarted. This ensures that
++    the attribute uniqueness plugin is working and prevents
++    other plugins from adding duplicates.
++    """
++
++    def execute(self, **options):
++        # If CA is disabled, no need to check for duplicates of IPA CA
++        ca_enabled = self.api.Command.ca_is_enabled()['result']
++        if not ca_enabled:
++            return True, []
++
++        # Look for the IPA CA cert subject
++        ldap = self.api.Backend.ldap2
++        cacert_subject = certstore.get_ca_subject(
++            ldap,
++            self.api.env.container_ca,
++            self.api.env.basedn)
++
++        # Find if there are other certificates with the same subject
++        # They are duplicates resulting of BZ 1480102
++        base_dn = DN(('cn', 'certificates'), ('cn', 'ipa'), ('cn', 'etc'),
++                     self.api.env.basedn)
++        try:
++            filter = ldap.make_filter({'ipaCertSubject': cacert_subject})
++            result, _truncated = ldap.find_entries(
++                base_dn=base_dn,
++                filter=filter,
++                attrs_list=[])
++        except errors.NotFound:
++            # No duplicate, we're good
++            logger.debug("No duplicates for IPA CA in LDAP")
++            return True, []
++
++        logger.debug("Found %d entrie(s) for IPA CA in LDAP", len(result))
++        cacert_dn = DN(('cn', get_ca_nickname(self.api.env.realm)), base_dn)
++        for entry in result:
++            if entry.dn == cacert_dn:
++                continue
++            # Remove the duplicate
++            try:
++                ldap.delete_entry(entry)
++                logger.debug("Removed the duplicate %s", entry.dn)
++            except Exception as e:
++                logger.warning("Failed to remove the duplicate %s: %s",
++                               entry.dn, e)
++
++        return True, []
+diff --git a/ipaserver/install/plugins/upload_cacrt.py b/ipaserver/install/plugins/upload_cacrt.py
+index a1957ca5b675b86f0df36dc820ee31305f54f863..985b74c06e80a3620eb6454c0bd9c7590b04184d 100644
+--- a/ipaserver/install/plugins/upload_cacrt.py
++++ b/ipaserver/install/plugins/upload_cacrt.py
+@@ -20,7 +20,7 @@
+ from ipalib.install import certstore
+ from ipaplatform.paths import paths
+ from ipaserver.install import certs
+-from ipalib import Registry, errors
++from ipalib import Registry, errors, x509
+ from ipalib import Updater
+ from ipapython import certdb
+ from ipapython.dn import DN
+@@ -41,6 +41,10 @@ class update_upload_cacrt(Updater):
+         ca_enabled = self.api.Command.ca_is_enabled()['result']
+         if ca_enabled:
+             ca_nickname = certdb.get_ca_nickname(self.api.env.realm)
++            ca_subject = certstore.get_ca_subject(
++                self.api.Backend.ldap2,
++                self.api.env.container_ca,
++                self.api.env.basedn)
+         else:
+             ca_nickname = None
+             server_certs = db.find_server_certs()
+@@ -54,9 +58,18 @@ class update_upload_cacrt(Updater):
+         for nickname, trust_flags in db.list_certs():
+             if trust_flags.has_key:
+                 continue
+-            if nickname == ca_nickname and ca_enabled:
+-                trust_flags = certdb.IPA_CA_TRUST_FLAGS
+             cert = db.get_cert_from_db(nickname, pem=False)
++            subject = DN(
++                x509.load_certificate(cert, datatype=x509.DER).subject)
++            if ca_enabled and subject == ca_subject:
++                # When ca is enabled, we can have the IPA CA cert stored
++                # in the nss db with a different nickname (for instance
++                # when the server was installed with --subject to
++                # customize the CA cert subject), but it must always be
++                # stored in LDAP with the DN cn=$DOMAIN IPA CA
++                # This is why we check the subject instead of the nickname here
++                nickname = ca_nickname
++                trust_flags = certdb.IPA_CA_TRUST_FLAGS
+             trust, _ca, eku = certstore.trust_flags_to_key_policy(trust_flags)
+ 
+             dn = DN(('cn', nickname), ('cn', 'certificates'), ('cn', 'ipa'),
+--
+2.13.5
\ No newline at end of file
diff --git a/SOURCES/0225-Fixing-how-sssd.conf-is-updated-when-promoting-a-cli.patch b/SOURCES/0225-Fixing-how-sssd.conf-is-updated-when-promoting-a-cli.patch
new file mode 100644
index 0000000..28455ee
--- /dev/null
+++ b/SOURCES/0225-Fixing-how-sssd.conf-is-updated-when-promoting-a-cli.patch
@@ -0,0 +1,92 @@
+From c8fcaa5dc792e7b87c8f21c7c322ddfabe219980 Mon Sep 17 00:00:00 2001
+From: Felipe Volpone <fbarreto@redhat.com>
+Date: Wed, 13 Sep 2017 09:26:41 -0300
+Subject: [PATCH] Fixing how sssd.conf is updated when promoting a client to
+ replica
+
+When promoting a client to a replica we have to change sssd.conf,
+deleting _srv_ part from 'ipa_server' property and setting
+'ipa_server_mode' to true.
+
+Previously, the wrong domain could be updated since the ipa_domain
+variable was not being used properly.
+
+https://pagure.io/freeipa/issue/7127
+
+Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+---
+ ipaserver/install/server/replicainstall.py | 27 ++++++++++++---------------
+ ipaserver/install/server/upgrade.py        |  4 ++++
+ 2 files changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
+index 814925de152809808f726c60ae7f35a24bc32a4a..326daf708f091d9d2c56ad399e46aef659dbba2e 100644
+--- a/ipaserver/install/server/replicainstall.py
++++ b/ipaserver/install/server/replicainstall.py
+@@ -432,30 +432,27 @@ def promote_sssd(host_name):
+     sssdconfig.import_config()
+     domains = sssdconfig.list_active_domains()
+
+-    ipa_domain = None
+-
+     for name in domains:
+         domain = sssdconfig.get_domain(name)
+         try:
+             hostname = domain.get_option('ipa_hostname')
+             if hostname == host_name:
+-                ipa_domain = domain
++                break
+         except SSSDConfig.NoOptionError:
+             continue
+-
+-    if ipa_domain is None:
+-        raise RuntimeError("Couldn't find IPA domain in sssd.conf")
+     else:
+-        domain.set_option('ipa_server', host_name)
+-        domain.set_option('ipa_server_mode', True)
+-        sssdconfig.save_domain(domain)
+-        sssdconfig.write()
++        raise RuntimeError("Couldn't find IPA domain in sssd.conf")
+
+-        sssd = services.service('sssd', api)
+-        try:
+-            sssd.restart()
+-        except CalledProcessError:
+-            root_logger.warning("SSSD service restart was unsuccessful.")
++    domain.set_option('ipa_server', host_name)
++    domain.set_option('ipa_server_mode', True)
++    sssdconfig.save_domain(domain)
++    sssdconfig.write()
++
++    sssd = services.service('sssd', api)
++    try:
++        sssd.restart()
++    except CalledProcessError:
++        root_logger.warning("SSSD service restart was unsuccessful.")
+
+
+ def promote_openldap_conf(hostname, master):
+diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
+index 732776f2cf513a4bb11d8f3f0dfaac78217e460f..109e922e3a3ea25f882fdd81765788a3881e87bd 100644
+--- a/ipaserver/install/server/upgrade.py
++++ b/ipaserver/install/server/upgrade.py
+@@ -1816,11 +1816,15 @@ def upgrade_configuration():
+         cainstance.ensure_ipa_authority_entry()
+
+     set_sssd_domain_option('ipa_server_mode', 'True')
++    set_sssd_domain_option('ipa_server', api.env.host)
+ 
+     sssdconfig = SSSDConfig.SSSDConfig()
+     sssdconfig.import_config()
+     sssd_enable_service(sssdconfig, 'ifp')
+ 
++    sssd = services.service('sssd', api)
++    sssd.restart()
++
+     krb = krbinstance.KrbInstance(fstore)
+     krb.fqdn = fqdn
+     krb.realm = api.env.realm
+--
+2.13.5
\ No newline at end of file
diff --git a/SOURCES/0226-Backport-4-5-Fix-ipa-server-upgrade-with-server-cert.patch b/SOURCES/0226-Backport-4-5-Fix-ipa-server-upgrade-with-server-cert.patch
new file mode 100644
index 0000000..27b8c70
--- /dev/null
+++ b/SOURCES/0226-Backport-4-5-Fix-ipa-server-upgrade-with-server-cert.patch
@@ -0,0 +1,199 @@
+From 8c576e8c3640b84869abacc43a74aa250df5a8e9 Mon Sep 17 00:00:00 2001
+From: Florence Blanc-Renaud <flo@redhat.com>
+Date: Tue, 5 Sep 2017 16:17:31 +0200
+Subject: [PATCH] Backport 4-5: Fix ipa-server-upgrade with server cert
+ tracking
+
+ipa-server-upgrade fails with Server-Cert not found, when trying to
+track httpd/ldap server certificates. There are 2 issues in the upgrade:
+- the certificates should be tracked only if they were issued by IPA CA
+(it is possible to have CA configured but 3rd part certs)
+- the certificate nickname can be different from Server-Cert
+
+The fix provides methods to find the server crt nickname for http and ldap,
+and a method to check if the server certs are issued by IPA and need to be
+tracked by certmonger.
+
+https://pagure.io/freeipa/issue/7141
+
+Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
+Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
+---
+ ipaserver/install/certs.py          | 27 ++++++++++++++++++++++
+ ipaserver/install/dsinstance.py     | 45 +++++++++++++++++++++++++++++++++----
+ ipaserver/install/httpinstance.py   | 16 ++++++++++---
+ ipaserver/install/server/upgrade.py |  4 ++--
+ 4 files changed, 83 insertions(+), 9 deletions(-)
+
+diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
+index 02c479d92511fcf4043e7d6798c85cf8256c3299..de96318db51b03f2515814d574cfebf1b242b6a6 100644
+--- a/ipaserver/install/certs.py
++++ b/ipaserver/install/certs.py
+@@ -42,6 +42,7 @@ from ipapython.certdb import get_ca_nickname, find_cert_from_txt, NSSDatabase
+ from ipapython.dn import DN
+ from ipalib import pkcs10, x509, api
+ from ipalib.errors import CertificateOperationError
++from ipalib.install import certstore
+ from ipalib.text import _
+ from ipaplatform.paths import paths
+
+@@ -669,6 +670,32 @@ class CertDB(object):
+                                              subject=host,
+                                              passwd_fname=self.passwd_fname)
+
++    def is_ipa_issued_cert(self, api, nickname):
++        """
++        Return True if the certificate contained in the CertDB with the
++        provided nickname has been issued by IPA.
++
++        Note that this method can only be executed if api has been initialized
++        """
++        # This method needs to compare the cert issuer (from the NSS DB
++        # and the subject from the CA (from LDAP), because nicknames are not
++        # always aligned.
++
++        cacert_subject = certstore.get_ca_subject(
++            api.Backend.ldap2,
++            api.env.container_ca,
++            api.env.basedn)
++
++        # The cert can be issued directly by IPA. In this case, the cert
++        # issuer is IPA CA subject.
++        cert = self.get_cert_from_db(nickname)
++        if cert is None:
++            raise RuntimeError("Could not find the cert %s in %s"
++                               % (nickname, self.secdir))
++        issuer = DN(x509.load_certificate(cert).issuer)
++
++        return issuer == cacert_subject
++
+
+ class _CrossProcessLock(object):
+     _DATETIME_FORMAT = '%Y%m%d%H%M%S%f'
+diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
+index 39248edb285ee4d792b4500d83d88b24f5732d10..c9db8ac28c3ca10539b745ca09f4d8aaece02e0c 100644
+--- a/ipaserver/install/dsinstance.py
++++ b/ipaserver/install/dsinstance.py
+@@ -1028,22 +1028,59 @@ class DsInstance(service.Service):
+                 root_logger.error(
+                     'Unable to restart DS instance %s: %s', ds_instance, e)
+
++    def get_server_cert_nickname(self, serverid=None):
++        """
++        Retrieve the nickname of the server cert used by dirsrv.
++
++        The method directly reads the dse.ldif to find the attribute
++        nsSSLPersonalitySSL of cn=RSA,cn=encryption,cn=config because
++        LDAP is not always accessible when we need to get the nickname
++        (for instance during uninstall).
++        """
++        if serverid is None:
++            serverid = self.get_state("serverid")
++        if serverid is not None:
++            dirname = config_dirname(serverid)
++            config_file = os.path.join(dirname, "dse.ldif")
++            rsa_dn = "cn=RSA,cn=encryption,cn=config"
++            with open(config_file, "r") as in_file:
++                parser = upgradeinstance.GetEntryFromLDIF(
++                    in_file,
++                    entries_dn=[rsa_dn])
++                parser.parse()
++                try:
++                    config_entry = parser.get_results()[rsa_dn]
++                    nickname = config_entry["nsSSLPersonalitySSL"][0]
++                    return nickname.decode('utf-8')
++                except (KeyError, IndexError):
++                    root_logger.error("Unable to find server cert nickname in "
++                                      "%s", config_file)
++
++        root_logger.debug("Falling back to nickname Server-Cert")
++        return 'Server-Cert'
++
+     def stop_tracking_certificates(self, serverid=None):
+         if serverid is None:
+             serverid = self.get_state("serverid")
+         if not serverid is None:
++            nickname = self.get_server_cert_nickname(serverid)
+             # drop the trailing / off the config_dirname so the directory
+             # will match what is in certmonger
+             dirname = config_dirname(serverid)[:-1]
+             dsdb = certs.CertDB(self.realm, nssdir=dirname)
+-            dsdb.untrack_server_cert(self.nickname)
++            dsdb.untrack_server_cert(nickname)
+
+     def start_tracking_certificates(self, serverid):
++        nickname = self.get_server_cert_nickname(serverid)
+         dirname = config_dirname(serverid)[:-1]
+         dsdb = certs.CertDB(self.realm, nssdir=dirname)
+-        dsdb.track_server_cert(self.nickname, self.principal,
+-                               dsdb.passwd_fname,
+-                               'restart_dirsrv %s' % serverid)
++        if dsdb.is_ipa_issued_cert(api, nickname):
++            dsdb.track_server_cert(nickname, self.principal,
++                                   dsdb.passwd_fname,
++                                   'restart_dirsrv %s' % serverid)
++        else:
++            root_logger.debug("Will not track DS server certificate %s as it "
++                              "is not issued by IPA", nickname)
+
+     # we could probably move this function into the service.Service
+     # class - it's very generic - all we need is a way to get an
+diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
+index f637b97db8f21ddbc00c4f70e18e836d300b2f33..e55edebc5d4e45d7cb4cb66d28a270e6d6a56e33 100644
+--- a/ipaserver/install/httpinstance.py
++++ b/ipaserver/install/httpinstance.py
+@@ -266,6 +266,11 @@ class HTTPInstance(service.Service):
+         installutils.set_directive(
+             paths.HTTPD_NSS_CONF, 'NSSNickname', quoted_nickname, quotes=False)
+
++    def get_mod_nss_nickname(self):
++        cert = installutils.get_directive(paths.HTTPD_NSS_CONF, 'NSSNickname')
++        nickname = installutils.unquote_directive_value(cert, quote_char="'")
++        return nickname
++
+     def set_mod_nss_protocol(self):
+         installutils.set_directive(paths.HTTPD_NSS_CONF, 'NSSProtocol', 'TLSv1.0,TLSv1.1,TLSv1.2', False)
+
+@@ -582,12 +587,17 @@ class HTTPInstance(service.Service):
+
+     def stop_tracking_certificates(self):
+         db = certs.CertDB(api.env.realm, nssdir=paths.HTTPD_ALIAS_DIR)
+-        db.untrack_server_cert(self.cert_nickname)
++        db.untrack_server_cert(self.get_mod_nss_nickname())
+
+     def start_tracking_certificates(self):
+         db = certs.CertDB(self.realm, nssdir=paths.HTTPD_ALIAS_DIR)
+-        db.track_server_cert(self.cert_nickname, self.principal,
+-                             db.passwd_fname, 'restart_httpd')
++        nickname = self.get_mod_nss_nickname()
++        if db.is_ipa_issued_cert(api, nickname):
++            db.track_server_cert(nickname, self.principal,
++                                 db.passwd_fname, 'restart_httpd')
++        else:
++            root_logger.debug("Will not track HTTP server cert %s as it is "
++                              "not issued by IPA", nickname)
+
+     def request_service_keytab(self):
+         super(HTTPInstance, self).request_service_keytab()
+diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
+index 109e922e3a3ea25f882fdd81765788a3881e87bd..0947766c076251e7608241803d3a1eabee65ae11 100644
+--- a/ipaserver/install/server/upgrade.py
++++ b/ipaserver/install/server/upgrade.py
+@@ -957,13 +957,13 @@ def certificate_renewal_update(ca, ds, http):
+         },
+         {
+             'cert-database': paths.HTTPD_ALIAS_DIR,
+-            'cert-nickname': 'Server-Cert',
++            'cert-nickname': http.get_mod_nss_nickname(),
+             'ca': 'IPA',
+             'cert-postsave-command': template % 'restart_httpd',
+         },
+         {
+             'cert-database': dsinstance.config_dirname(serverid),
+-            'cert-nickname': 'Server-Cert',
++            'cert-nickname': ds.get_server_cert_nickname(serverid),
+             'ca': 'IPA',
+             'cert-postsave-command':
+                 '%s %s' % (template % 'restart_dirsrv', serverid),
+--
+2.13.5
\ No newline at end of file
diff --git a/SOURCES/0227-Always-check-peer-has-keys-before-connecting.patch b/SOURCES/0227-Always-check-peer-has-keys-before-connecting.patch
new file mode 100644
index 0000000..684f4a0
--- /dev/null
+++ b/SOURCES/0227-Always-check-peer-has-keys-before-connecting.patch
@@ -0,0 +1,73 @@
+From 82e860ae81b9e34fc6a326be4183f37a21ac1564 Mon Sep 17 00:00:00 2001
+From: Simo Sorce <simo@redhat.com>
+Date: Fri, 23 Jun 2017 04:48:41 -0400
+Subject: [PATCH] Always check peer has keys before connecting
+
+When pulling the DM password we may have the same issues reported in
+ticket #6838 for CA keys.
+This commit makes sure we always check the peer has keys before any
+client operation.
+
+Ticket #6838
+
+Signed-off-by: Simo Sorce <simo@redhat.com>
+Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
+Reviewed-By: Michal Reznik <mreznik@redhat.com>
+---
+ ipaserver/install/custodiainstance.py | 20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py
+index 390576bc0c0edfb7d8f8895eca9df30079526aa8..bc3cea7063dff183c85b4f6e8ced7567f691001d 100644
+--- a/ipaserver/install/custodiainstance.py
++++ b/ipaserver/install/custodiainstance.py
+@@ -13,7 +13,6 @@ from ipaserver.install import ldapupdate
+ from ipaserver.install import sysupgrade
+ from base64 import b64decode
+ from jwcrypto.common import json_decode
+-import functools
+ import shutil
+ import os
+ import stat
+@@ -31,13 +30,6 @@ class CustodiaInstance(SimpleServiceInstance):
+         self.ldap_uri = None
+         self.fqdn = host_name
+         self.realm = realm
+-        self.__CustodiaClient = functools.partial(
+-            CustodiaClient,
+-            client_service='host@%s' % self.fqdn,
+-            keyfile=self.server_keys,
+-            keytab=paths.KRB5_KEYTAB,
+-            realm=realm,
+-        )
+
+     def __config_file(self):
+         template_file = os.path.basename(self.config_file) + '.template'
+@@ -144,6 +136,14 @@ class CustodiaInstance(SimpleServiceInstance):
+                     raise RuntimeError("Timed out trying to obtain keys.")
+                 time.sleep(1)
+
++    def __CustodiaClient(self, server):
++        # Before we attempt to fetch keys from this host, make sure our public
++        # keys have been replicated there.
++        self.__wait_keys(server)
++
++        return CustodiaClient('host@%s' % self.fqdn, self.server_keys,
++                              paths.KRB5_KEYTAB, server, realm=self.realm)
++
+     def __get_keys(self, ca_host, cacerts_file, cacerts_pwd, data):
+         # Fecth all needed certs one by one, then combine them in a single
+         # p12 file
+@@ -151,10 +151,6 @@ class CustodiaInstance(SimpleServiceInstance):
+         prefix = data['prefix']
+         certlist = data['list']
+
+-        # Before we attempt to fetch keys from this host, make sure our public
+-        # keys have been replicated there.
+-        self.__wait_keys(ca_host)
+-
+         cli = self.__CustodiaClient(server=ca_host)
+
+         # Temporary nssdb
+--
+2.13.5
\ No newline at end of file
diff --git a/SOURCES/0228-Make-sure-upgrade-also-checks-for-IPv6-stack.patch b/SOURCES/0228-Make-sure-upgrade-also-checks-for-IPv6-stack.patch
new file mode 100644
index 0000000..600401d
--- /dev/null
+++ b/SOURCES/0228-Make-sure-upgrade-also-checks-for-IPv6-stack.patch
@@ -0,0 +1,61 @@
+From 010f6405288b1ca519d684d85ca25ce86de60b66 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Tue, 19 Sep 2017 12:06:39 +0300
+Subject: [PATCH] Make sure upgrade also checks for IPv6 stack
+
+ - Add check for IPv6 stack to upgrade process
+ - Change IPv6 checker to also check that localhost resolves to ::1
+
+Part of fixes https://pagure.io/freeipa/issue/7083
+
+Reviewed-By: Tomas Krizek <tkrizek@redhat.com>
+---
+ ipaplatform/redhat/tasks.py         | 19 ++++++++++++++++---
+ ipaserver/install/server/upgrade.py |  1 +
+ 2 files changed, 17 insertions(+), 3 deletions(-)
+
+diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py
+index 07efebab97eabcf2dc39bd345920a1c7be56e9f5..94d1863c5cc20ec6c2399f339ce19498976553bc 100644
+--- a/ipaplatform/redhat/tasks.py
++++ b/ipaplatform/redhat/tasks.py
+@@ -153,9 +153,22 @@ class RedHatTaskNamespace(BaseTaskNamespace):
+         """
+         if not os.path.exists(paths.IF_INET6):
+             raise RuntimeError(
+-                "IPv6 kernel module has to be enabled. If you do not wish to "
+-                "use IPv6, please disable it on the interfaces in "
+-                "sysctl.conf and enable the IPv6 kernel module.")
++                "IPv6 stack has to be enabled in the kernel and some "
++                "interface has to have ::1 address assigned. Typically "
++                "this is 'lo' interface. If you do not wish to use IPv6 "
++                "globally, disable it on the specific interfaces in "
++                "sysctl.conf except 'lo' interface.")
++
++        try:
++            localhost6 = ipautil.CheckedIPAddress('::1', allow_loopback=True)
++            if localhost6.get_matching_interface() is None:
++                raise ValueError("no interface for ::1 address found")
++        except ValueError:
++            raise RuntimeError(
++                 "IPv6 stack is enabled in the kernel but there is no "
++                 "interface that has ::1 address assigned. Add ::1 address "
++                 "resolution to 'lo' interface. You might need to enable IPv6 "
++                 "on the interface 'lo' in sysctl.conf.")
+ 
+     def restore_pre_ipa_client_configuration(self, fstore, statestore,
+                                              was_sssd_installed,
+diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
+index 0947766c076251e7608241803d3a1eabee65ae11..1c4b2357d5d016b8a7501f46380d5e0a61dc21a0 100644
+--- a/ipaserver/install/server/upgrade.py
++++ b/ipaserver/install/server/upgrade.py
+@@ -1860,6 +1860,7 @@ def upgrade_configuration():
+ def upgrade_check(options):
+     try:
+         installutils.check_server_configuration()
++        tasks.check_ipv6_stack_enabled()
+     except RuntimeError as e:
+         root_logger.error(e)
+         sys.exit(1)
+-- 
+2.13.5
+
diff --git a/SOURCES/0229-control-logging-of-host_port_open-from-caller.patch b/SOURCES/0229-control-logging-of-host_port_open-from-caller.patch
new file mode 100644
index 0000000..951e7c2
--- /dev/null
+++ b/SOURCES/0229-control-logging-of-host_port_open-from-caller.patch
@@ -0,0 +1,103 @@
+From fbaa55fbe8447745a20c99a68d62790f5dd5a0f7 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Thu, 3 Aug 2017 15:48:33 +0200
+Subject: [PATCH] control logging of host_port_open from caller
+
+host_port_open copied logging behavior of ipa-replica-conncheck utility
+which doesn't make it much reusable.
+
+Now log level can be controlled from caller so other callers might use
+other logging level without host_port_open guessing what was the
+intention.
+
+https://pagure.io/freeipa/issue/7083
+
+Reviewed-By: Tomas Krizek <tkrizek@redhat.com>
+---
+ install/tools/ipa-replica-conncheck |  9 ++++++++-
+ ipapython/ipautil.py                | 17 ++++++-----------
+ 2 files changed, 14 insertions(+), 12 deletions(-)
+
+diff --git a/install/tools/ipa-replica-conncheck b/install/tools/ipa-replica-conncheck
+index 528242268f9992e903781b76a379039d533853c0..f10b7e3d2f94540dba3956bf460c4b9f38da90da 100755
+--- a/install/tools/ipa-replica-conncheck
++++ b/install/tools/ipa-replica-conncheck
+@@ -46,6 +46,8 @@ import distutils.spawn
+ from ipaplatform.paths import paths
+ import gssapi
+ from cryptography.hazmat.primitives import serialization
++import logging
++
+ 
+ CONNECT_TIMEOUT = 5
+ RESPONDER = None
+@@ -379,11 +381,16 @@ class PortResponder(threading.Thread):
+ def port_check(host, port_list):
+     ports_failed = []
+     ports_udp_warning = []  # conncheck could not verify that port is open
++    log_level = {
++        SOCK_DGRAM: logging.WARNING,
++        SOCK_STREAM: logging.ERROR
++    }
+     for port in port_list:
+         try:
+             port_open = ipautil.host_port_open(
+                 host, port.port, port.port_type,
+-                socket_timeout=CONNECT_TIMEOUT, log_errors=True)
++                socket_timeout=CONNECT_TIMEOUT, log_errors=True,
++                log_level=log_level[port.port_type])
+         except socket.gaierror:
+             raise RuntimeError("Port check failed! Unable to resolve host name '%s'" % host)
+         if port_open:
+diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
+index 5a6bf5a27d5a6e25c51fbaa6e2b1167652e2735d..e1e6e32b15559486caecb070627db82e14a57bdf 100644
+--- a/ipapython/ipautil.py
++++ b/ipapython/ipautil.py
+@@ -42,6 +42,7 @@ from contextlib import contextmanager
+ import locale
+ import collections
+ from subprocess import CalledProcessError
++import logging
+ 
+ from dns import resolver, reversename
+ from dns.exception import DNSException
+@@ -948,7 +949,8 @@ def user_input(prompt, default = None, allow_empty = True):
+ 
+ 
+ def host_port_open(host, port, socket_type=socket.SOCK_STREAM,
+-                   socket_timeout=None, log_errors=False):
++                   socket_timeout=None, log_errors=False,
++                   log_level=logging.DEBUG):
+     """
+     host: either hostname or IP address;
+           if hostname is provided, port MUST be open on ALL resolved IPs
+@@ -970,23 +972,16 @@ def host_port_open(host, port, socket_type=socket.SOCK_STREAM,
+             s.connect(sa)
+ 
+             if socket_type == socket.SOCK_DGRAM:
+-                s.send('')
++                s.send(b'')
+                 s.recv(512)
+         except socket.error:
+             port_open = False
+-
+             if log_errors:
+-                msg = ('Failed to connect to port %(port)d %(proto)s on '
++                msg = ('Failed to connect to port %(port)s %(proto)s on '
+                        '%(addr)s' % dict(port=port,
+                                          proto=PROTOCOL_NAMES[socket_type],
+                                          addr=sa[0]))
+-
+-                # Do not log udp failures as errors (to be consistent with
+-                # the rest of the code that checks for open ports)
+-                if socket_type == socket.SOCK_DGRAM:
+-                    root_logger.warning(msg)
+-                else:
+-                    root_logger.error(msg)
++                root_logger.log(log_level, msg)
+         finally:
+             if s is not None:
+                 s.close()
+-- 
+2.13.5
+
diff --git a/SOURCES/0230-log-progress-of-wait_for_open_ports.patch b/SOURCES/0230-log-progress-of-wait_for_open_ports.patch
new file mode 100644
index 0000000..480be17
--- /dev/null
+++ b/SOURCES/0230-log-progress-of-wait_for_open_ports.patch
@@ -0,0 +1,44 @@
+From 647e23eb307e09597f355fb10abfd4c74a4b6f84 Mon Sep 17 00:00:00 2001
+From: Petr Vobornik <pvoborni@redhat.com>
+Date: Thu, 3 Aug 2017 16:03:29 +0200
+Subject: [PATCH] log progress of wait_for_open_ports
+
+To know what to focus on when some check fail. E.g. to detect that
+IPv6 address or its resolution for localhost is misconfigured.
+
+https://pagure.io/freeipa/issue/7083
+
+Reviewed-By: Tomas Krizek <tkrizek@redhat.com>
+---
+ ipapython/ipautil.py | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
+index e1e6e32b15559486caecb070627db82e14a57bdf..59ea84da4ac667a39bdaa9a6fd7d87ab1b6e658d 100644
+--- a/ipapython/ipautil.py
++++ b/ipapython/ipautil.py
+@@ -1213,15 +1213,20 @@ def wait_for_open_ports(host, ports, timeout=0):
+     op_timeout = time.time() + timeout
+ 
+     for port in ports:
++        root_logger.debug('waiting for port: %s', port)
++        log_error = True
+         while True:
+-            port_open = host_port_open(host, port)
++            port_open = host_port_open(host, port, log_errors=log_error)
++            log_error = False  # Log only first err so that the log is readable
+ 
+             if port_open:
++                root_logger.debug('SUCCESS: port: %s', port)
+                 break
+             if timeout and time.time() > op_timeout: # timeout exceeded
+                 raise socket.timeout("Timeout exceeded")
+             time.sleep(1)
+ 
++
+ def wait_for_open_socket(socket_name, timeout=0):
+     """
+     Wait until the specified socket on the local host is open. Timeout
+-- 
+2.13.5
+
diff --git a/SOURCES/0231-Store-help-in-Schema-before-writing-to-disk.patch b/SOURCES/0231-Store-help-in-Schema-before-writing-to-disk.patch
new file mode 100644
index 0000000..b336e43
--- /dev/null
+++ b/SOURCES/0231-Store-help-in-Schema-before-writing-to-disk.patch
@@ -0,0 +1,39 @@
+From 5693c0fe6dfe998fa5ea3f86f477dc9dcbfab881 Mon Sep 17 00:00:00 2001
+From: David Kreitschmann <david@kreitschmann.de>
+Date: Fri, 7 Apr 2017 18:22:25 +0200
+Subject: [PATCH] Store help in Schema before writing to disk
+
+Signed-off-by: David Kreitschmann <david@kreitschmann.de>
+Reviewed-By: David Kupka <dkupka@redhat.com>
+Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
+Reviewed-By: David Kupka <dkupka@redhat.com>
+Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+---
+ ipaclient/remote_plugins/schema.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py
+index 3ecd608f96e336df57739db380a00c2d95b2ece5..9b6668d26352a24d7249bac5e304277563ee450f 100644
+--- a/ipaclient/remote_plugins/schema.py
++++ b/ipaclient/remote_plugins/schema.py
+@@ -383,6 +383,7 @@ class Schema(object):
+ 
+         if fingerprint is None:
+             fingerprint, ttl = self._fetch(client, ignore_cache=read_failed)
++            self._help = self._generate_help(self._dict)
+             try:
+                 self._write_schema(fingerprint)
+             except Exception as e:
+@@ -498,7 +499,7 @@ class Schema(object):
+ 
+             schema.writestr(
+                 '_help',
+-                json.dumps(self._generate_help(self._dict)).encode('utf-8')
++                json.dumps(self._help).encode('utf-8')
+             )
+ 
+     def read_namespace_member(self, namespace, member):
+-- 
+2.13.5
+
diff --git a/SOURCES/0232-Disable-pylint-in-get_help-function-because-of-type-.patch b/SOURCES/0232-Disable-pylint-in-get_help-function-because-of-type-.patch
new file mode 100644
index 0000000..6d97395
--- /dev/null
+++ b/SOURCES/0232-Disable-pylint-in-get_help-function-because-of-type-.patch
@@ -0,0 +1,33 @@
+From df9933a8cbc5c6cf4041709ed61c589adaae7a08 Mon Sep 17 00:00:00 2001
+From: David Kreitschmann <david@kreitschmann.de>
+Date: Fri, 9 Jun 2017 17:59:35 +0200
+Subject: [PATCH] Disable pylint in get_help function because of type
+ confusion.
+
+Reviewed-By: David Kupka <dkupka@redhat.com>
+Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
+Reviewed-By: David Kupka <dkupka@redhat.com>
+Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+---
+ ipaclient/remote_plugins/schema.py | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py
+index 9b6668d26352a24d7249bac5e304277563ee450f..2892ab9ec7c6fb092ef470b7e5bd2b9c0760c2af 100644
+--- a/ipaclient/remote_plugins/schema.py
++++ b/ipaclient/remote_plugins/schema.py
+@@ -516,7 +516,9 @@ class Schema(object):
+ 
+     def get_help(self, namespace, member):
+         if isinstance(self._help, bytes):
+-            self._help = json.loads(self._help.decode('utf-8'))
++            self._help = json.loads(
++                self._help.decode('utf-8')  # pylint: disable=no-member
++            )
+ 
+         return self._help[namespace][member]
+ 
+-- 
+2.13.5
+
diff --git a/SOURCES/1001-Change-branding-to-IPA-and-Identity-Management.patch b/SOURCES/1001-Change-branding-to-IPA-and-Identity-Management.patch
index 3eb1df2..24c8cb4 100644
--- a/SOURCES/1001-Change-branding-to-IPA-and-Identity-Management.patch
+++ b/SOURCES/1001-Change-branding-to-IPA-and-Identity-Management.patch
@@ -1,4 +1,4 @@
-From 27b4f549af4f55b95ff44b9c5a59b9174ab7ad2e Mon Sep 17 00:00:00 2001
+From 7a5799402ddfbe2704afa4449bb597f2feeea6c2 Mon Sep 17 00:00:00 2001
 From: Jan Cholasta <jcholast@redhat.com>
 Date: Tue, 14 Mar 2017 15:48:07 +0000
 Subject: [PATCH] Change branding to IPA and Identity Management
@@ -982,10 +982,10 @@ index dced253e7f039dc9d66466bf8bcd777e53919f54..2906cad2f4535a5f4aace1e24397314f
      print("This includes:")
      if setup_ca:
 diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
-index 814925de152809808f726c60ae7f35a24bc32a4a..05f263cd2b1c6a7cd9d21b0d9a076d32d241ab96 100644
+index 326daf708f091d9d2c56ad399e46aef659dbba2e..0d3fc5a24dcd55aab420db4a6565809dbe8e70a9 100644
 --- a/ipaserver/install/server/replicainstall.py
 +++ b/ipaserver/install/server/replicainstall.py
-@@ -604,7 +604,7 @@ def check_domain_level_is_supported(current):
+@@ -601,7 +601,7 @@ def check_domain_level_is_supported(current):
      above_upper_bound = current > constants.MAX_DOMAIN_LEVEL
  
      if under_lower_bound or above_upper_bound:
@@ -995,5 +995,5 @@ index 814925de152809808f726c60ae7f35a24bc32a4a..05f263cd2b1c6a7cd9d21b0d9a076d32
                     "this domain. The Domain Level needs to be "
                     "raised before installing a replica with "
 -- 
-2.9.4
+2.13.5
 
diff --git a/SOURCES/1002-Package-copy-schema-to-ca.py.patch b/SOURCES/1002-Package-copy-schema-to-ca.py.patch
index 3972454..f8d9079 100644
--- a/SOURCES/1002-Package-copy-schema-to-ca.py.patch
+++ b/SOURCES/1002-Package-copy-schema-to-ca.py.patch
@@ -1,4 +1,4 @@
-From 85ac8d7f55b26f7d783844acbf942f5db99d0a37 Mon Sep 17 00:00:00 2001
+From 6013929e6ae2ea5cce4437281b3ee019b33ec151 Mon Sep 17 00:00:00 2001
 From: Jan Cholasta <jcholast@redhat.com>
 Date: Tue, 14 Mar 2017 16:07:15 +0000
 Subject: [PATCH] Package copy-schema-to-ca.py
@@ -40,5 +40,5 @@ index 62f79b28000b015edb66f4c39a270097ab3ed666..d876c5b385a250f3bd9c2689f9794ef7
  
  
 -- 
-2.9.4
+2.13.5
 
diff --git a/SOURCES/1003-Revert-Increased-mod_wsgi-socket-timeout.patch b/SOURCES/1003-Revert-Increased-mod_wsgi-socket-timeout.patch
index 8f4863a..45987ae 100644
--- a/SOURCES/1003-Revert-Increased-mod_wsgi-socket-timeout.patch
+++ b/SOURCES/1003-Revert-Increased-mod_wsgi-socket-timeout.patch
@@ -1,4 +1,4 @@
-From e419842024b0fc9a774988972fadcbaf4650c395 Mon Sep 17 00:00:00 2001
+From 3faf68ad37710c6650fdb12fc1b5751896a6e7e0 Mon Sep 17 00:00:00 2001
 From: Jan Cholasta <jcholast@redhat.com>
 Date: Wed, 22 Jun 2016 13:53:46 +0200
 Subject: [PATCH] Revert "Increased mod_wsgi socket-timeout"
@@ -24,5 +24,5 @@ index 01bf9a4f97fc0cf197c0ad12743affa597b54911..d3389ec5d34dba6429986b1c2a6dfb21
  WSGIScriptAlias /ipa /usr/share/ipa/wsgi.py
  WSGIScriptReloading Off
 -- 
-2.9.4
+2.13.5
 
diff --git a/SOURCES/1004-Remove-csrgen.patch b/SOURCES/1004-Remove-csrgen.patch
index a532876..5707809 100644
--- a/SOURCES/1004-Remove-csrgen.patch
+++ b/SOURCES/1004-Remove-csrgen.patch
@@ -1,4 +1,4 @@
-From 12d2356795d64089ce2578031a1297d56c8048ce Mon Sep 17 00:00:00 2001
+From f0851afdf0abd516dcd707e6e3ec0086f09f6090 Mon Sep 17 00:00:00 2001
 From: Jan Cholasta <jcholast@redhat.com>
 Date: Thu, 16 Mar 2017 09:44:21 +0000
 Subject: [PATCH] Remove csrgen
@@ -1662,5 +1662,5 @@ index 556f8e096976387d24057084c06d53bcb9998a69..00000000000000000000000000000000
 -            _script = generator.csr_script(
 -                principal, {}, 'example', 'identity')
 -- 
-2.9.4
+2.13.5
 
diff --git a/SOURCES/ipa-centos-branding.patch b/SOURCES/ipa-centos-branding.patch
deleted file mode 100644
index 673cd2f..0000000
--- a/SOURCES/ipa-centos-branding.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-From 99efecaf87dc1fc9517efaff441a6a7ce46444eb Mon Sep 17 00:00:00 2001
-From: Jim Perrin <jperrin@centos.org>
-Date: Wed, 11 Mar 2015 10:37:03 -0500
-Subject: [PATCH] update for new ntp server method
-
----
- ipaplatform/base/paths.py        | 1 +
- ipaserver/install/ntpinstance.py | 2 ++
- 2 files changed, 3 insertions(+)
-
-diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
-index af50262..5090062 100644
---- a/ipaplatform/base/paths.py
-+++ b/ipaplatform/base/paths.py
-@@ -99,6 +99,7 @@ class BasePathNamespace(object):
-     PKI_TOMCAT_ALIAS_DIR = "/etc/pki/pki-tomcat/alias/"
-     PKI_TOMCAT_PASSWORD_CONF = "/etc/pki/pki-tomcat/password.conf"
-     ETC_REDHAT_RELEASE = "/etc/redhat-release"
-+    ETC_CENTOS_RELEASE = "/etc/centos-release"
-     RESOLV_CONF = "/etc/resolv.conf"
-     SAMBA_KEYTAB = "/etc/samba/samba.keytab"
-     SMB_CONF = "/etc/samba/smb.conf"
-diff --git a/ipaserver/install/ntpinstance.py b/ipaserver/install/ntpinstance.py
-index c653525..4b0578b 100644
---- a/ipaserver/install/ntpinstance.py
-+++ b/ipaserver/install/ntpinstance.py
-@@ -44,6 +44,8 @@ class NTPInstance(service.Service):
-         os = ""
-         if ipautil.file_exists(paths.ETC_FEDORA_RELEASE):
-             os = "fedora"
-+        elif ipautil.file_exists(paths.ETC_CENTOS_RELEASE):
-+            os = "centos"
-         elif ipautil.file_exists(paths.ETC_REDHAT_RELEASE):
-             os = "rhel"
- 
--- 
-1.8.3.1
-
diff --git a/SPECS/ipa.spec b/SPECS/ipa.spec
index 4fc5d6f..d96d62f 100644
--- a/SPECS/ipa.spec
+++ b/SPECS/ipa.spec
@@ -68,7 +68,7 @@
 
 Name:           ipa
 Version:        %{IPA_VERSION}
-Release:        21%{?dist}.1.2
+Release:        21%{?dist}.2.2
 Summary:        The Identity, Policy and Audit system
 
 Group:          System Environment/Base
@@ -76,10 +76,10 @@ License:        GPLv3+
 URL:            http://www.freeipa.org/
 Source0:        https://releases.pagure.org/freeipa/freeipa-%{version}.tar.gz
 # RHEL spec file only: START: Change branding to IPA and Identity Management
-#Source1:        header-logo.png
-#Source2:        login-screen-background.jpg
-#Source3:        login-screen-logo.png
-#Source4:        product-name.png
+Source1:        header-logo.png
+Source2:        login-screen-background.jpg
+Source3:        login-screen-logo.png
+Source4:        product-name.png
 # RHEL spec file only: END: Change branding to IPA and Identity Management
 BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
 
@@ -303,6 +303,19 @@ Patch0216:      0216-smart-card-advise-use-password-when-changing-trust-f.patch
 Patch0217:      0217-smart-card-advises-ensure-that-krb5-pkinit-is-instal.patch
 Patch0218:      0218-NULL-LDAP-context-in-call-to-ldap_search_ext_s-durin.patch
 Patch0219:      0219-Restore-old-version-of-caIPAserviceCert-for-upgrade-.patch
+Patch0220:      0220-ipa-otptoken-import-Make-PBKDF2-refer-to-the-pkcs5-n.patch
+Patch0221:      0221-Adds-whoami-DS-plugin-in-case-that-plugin-is-missing.patch
+Patch0222:      0222-Fix-ipa-config-mod-ca-renewal-master.patch
+Patch0223:      0223-Backport-PR-988-to-ipa-4-5-Fix-Certificate-renewal-w.patch
+Patch0224:      0224-Backport-PR-1008-to-ipa-4-5-Fix-ipa-server-upgrade-T.patch
+Patch0225:      0225-Fixing-how-sssd.conf-is-updated-when-promoting-a-cli.patch
+Patch0226:      0226-Backport-4-5-Fix-ipa-server-upgrade-with-server-cert.patch
+Patch0227:      0227-Always-check-peer-has-keys-before-connecting.patch
+Patch0228:      0228-Make-sure-upgrade-also-checks-for-IPv6-stack.patch
+Patch0229:      0229-control-logging-of-host_port_open-from-caller.patch
+Patch0230:      0230-log-progress-of-wait_for_open_ports.patch
+Patch0231:      0231-Store-help-in-Schema-before-writing-to-disk.patch
+Patch0232:      0232-Disable-pylint-in-get_help-function-because-of-type-.patch
 
 Patch1001:      1001-Change-branding-to-IPA-and-Identity-Management.patch
 Patch1002:      1002-Package-copy-schema-to-ca.py.patch
@@ -1104,10 +1117,10 @@ cp -r %{_builddir}/freeipa-%{version} %{_builddir}/freeipa-%{version}-python3
 %endif # with_python3
 
 # RHEL spec file only: START: Change branding to IPA and Identity Management
-#cp %SOURCE1 install/ui/images/header-logo.png
-#cp %SOURCE2 install/ui/images/login-screen-background.jpg
-#cp %SOURCE3 install/ui/images/login-screen-logo.png
-#cp %SOURCE4 install/ui/images/product-name.png
+cp %SOURCE1 install/ui/images/header-logo.png
+cp %SOURCE2 install/ui/images/login-screen-background.jpg
+cp %SOURCE3 install/ui/images/login-screen-logo.png
+cp %SOURCE4 install/ui/images/product-name.png
 # RHEL spec file only: END: Change branding to IPA and Identity Management
 
 
@@ -1131,8 +1144,7 @@ find \
 %configure --with-vendor-suffix=-%{release} \
            %{enable_server_option} \
            %{with_ipatests_option} \
-           %{linter_options} \
-           --with-ipaplatform=rhel
+           %{linter_options}
 
 %make_build
 
@@ -1856,11 +1868,41 @@ fi
 
 
 %changelog
-* Wed Sep 06 2017 Johnny Hughes <johnny@centos.org> - 4.5.0-21.el7.centos.1.2
-- set ipaplatform to rhel for compatibilty for updates
-
-* Tue Sep 05 2017 CentOS Sources <bugs@centos.org> - 4.5.0-21.el7.centos.1.2
-- Roll in CentOS Branding
+* Wed Sep 20 2017 Felipe Barreto <fbarreto@redhat.com> - 4.5.0-21.el7.2.2
+- Resolves: #1493410 ipa-server-upgrade timeouts on wait_for_open ports
+  expecting IPA services listening on IPv6 ports
+    - Make sure upgrade also checks for IPv6 stack
+    - control logging of host_port_open from caller
+    - log progress of wait_for_open_ports
+- Resolves: #1493411 ipa help command returns traceback when no cache
+  is present
+    - Store help in Schema before writing to disk
+    - Disable pylint in get_help function because of type confusion.
+
+* Tue Sep 19 2017 Felipe Barreto <fbarreto@redhat.com> - 4.5.0-21.el7.2
+- Resolves: #1486794 - [ipa-replica-install] - 406 Client Error: Failed to
+  validate message: Incorrect number of results (0) searching forpublic
+  key for host
+    - Always check peer has keys before connecting
+- Resolves: #1489300 - Unable to set ca renewal master on replica
+    - Fix ipa config-mod --ca-renewal-master
+- Resolves: #1489815 - TypeError in renew_ca_cert prevents from swiching
+  back to self-signed CA
+    - Backport PR 988 to ipa-4-5 Fix Certificate renewal (with ext ca)
+- Resolves: #1489817 - ipa-server-upgrade failes with "This entry already exists"
+    - Backport PR 1008 to ipa-4-5 Fix ipa-server-upgrade: This entry already exists
+- Resolves: #1490331 - FreeIPA/IdM installations which were upgraded from
+  versions with 389 DS prior to 1.3.3.0 doesn't have whomai plugin enabled and
+  thus startup of Web UI fails
+    - Adds whoami DS plugin in case that plugin is missing
+- Resolves: #1491545 - IPA WebUI does not work after upgrade from IPA 4.4 to 4.5
+    - Fixing how sssd.conf is updated when promoting a client to replica
+- Resolves: #1492616 - ipa-otptoken-import - XML file is missing PBKDF2
+  parameters!
+    - ipa-otptoken-import: Make PBKDF2 refer to the pkcs5 namespace
+- Resolves: #1493153 - Updating from RHEL 7.3 fails with Server-Cert not found
+  (ipa-server-upgrade)
+    - Backport 4-5: Fix ipa-server-upgrade with server cert tracking
 
 * Wed Aug 16 2017 Pavel Vomacka <pvomacka@redhat.com> - 4.5.0-21.el7.1.2
 - Fixing issues reported by Errata tool