diff --git a/SOURCES/0001-WebUI-Fix-IPA-Error-3007-RequirmentError-while-addin_rhbz#1757045.patch b/SOURCES/0001-WebUI-Fix-IPA-Error-3007-RequirmentError-while-addin_rhbz#1757045.patch
index 0f0d3a5..34580fe 100644
--- a/SOURCES/0001-WebUI-Fix-IPA-Error-3007-RequirmentError-while-addin_rhbz#1757045.patch
+++ b/SOURCES/0001-WebUI-Fix-IPA-Error-3007-RequirmentError-while-addin_rhbz#1757045.patch
@@ -291,3 +291,119 @@ index 5f2b1fdc2..7622e65dc 100644
 -- 
 2.26.2
 
+From f6c460aee8542d4d81cd9970d71051c240156973 Mon Sep 17 00:00:00 2001
+From: Serhii Tsymbaliuk <stsymbal@redhat.com>
+Date: Thu, 16 Jul 2020 18:52:24 +0200
+Subject: [PATCH] WebUI: Fix error "unknown command
+ 'idoverrideuser_add_member'"
+
+There was wrong IPA.associator class used for 'Groups' -> 'User ID overrides' association,
+as a result a wrong command was sent to the server.
+
+Ticket: https://pagure.io/freeipa/issue/8416
+
+Signed-off-by: Serhii Tsymbaliuk <stsymbal@redhat.com>
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ install/ui/src/freeipa/group.js | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/install/ui/src/freeipa/group.js b/install/ui/src/freeipa/group.js
+index 2984bd4b2..61c19a82f 100644
+--- a/install/ui/src/freeipa/group.js
++++ b/install/ui/src/freeipa/group.js
+@@ -209,7 +209,6 @@ return {
+         {
+             $type: 'association',
+             name: 'member_idoverrideuser',
+-            associator: IPA.serial_associator,
+             add_title: '@i18n:objects.group.add_idoverride_user',
+             remove_title: '@i18n:objects.group.remove_idoverride_users',
+             columns: [
+-- 
+2.26.2
+
+From e35739b7e9f6bb016b37abbd92bdaee71a59a288 Mon Sep 17 00:00:00 2001
+From: Serhii Tsymbaliuk <stsymbal@redhat.com>
+Date: Wed, 29 Jul 2020 09:41:36 +0200
+Subject: [PATCH] WebUI tests: Add test case to cover user ID override feature
+
+The test case includes adding an user ID override to Default Trust View
+and adding the ID override to some IPA group.
+
+Ticket: https://pagure.io/freeipa/issue/8416
+
+Signed-off-by: Serhii Tsymbaliuk <stsymbal@redhat.com>
+Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ ipatests/test_webui/test_trust.py | 41 +++++++++++++++++++++++++++++++
+ 1 file changed, 41 insertions(+)
+
+diff --git a/ipatests/test_webui/test_trust.py b/ipatests/test_webui/test_trust.py
+index c04c2fcd8..605f8a2a7 100644
+--- a/ipatests/test_webui/test_trust.py
++++ b/ipatests/test_webui/test_trust.py
+@@ -21,6 +21,8 @@
+ Trust tests
+ """
+ 
++import ipatests.test_webui.data_group as group
++import ipatests.test_webui.data_idviews as idview
+ from ipatests.test_webui.ui_driver import UI_driver
+ from ipatests.test_webui.ui_driver import screenshot
+ from ipatests.test_webui.task_range import range_tasks
+@@ -29,6 +31,8 @@ import pytest
+ ENTITY = 'trust'
+ CONFIG_ENTITY = 'trustconfig'
+ 
++DEFAULT_TRUST_VIEW = 'Default Trust View'
++
+ CONFIG_DATA = {
+     'mod': [
+         ['combobox', 'ipantfallbackprimarygroup', 'admins'],
+@@ -164,3 +168,40 @@ class test_trust(trust_tasks):
+ 
+         self.mod_record(CONFIG_ENTITY, CONFIG_DATA)
+         self.mod_record(CONFIG_ENTITY, CONFIG_DATA2)
++
++    @screenshot
++    def test_group_member_idoverrideuser(self):
++
++        self.init_app()
++
++        # Create new trust
++        data = self.get_data()
++        self.add_record(ENTITY, data)
++
++        # Create an user ID override
++        ad_domain = self.config.get('ad_domain')
++        ad_admin = self.config.get('ad_admin')
++        idoverrideuser_pkey = '{}@{}'.format(ad_admin, ad_domain).lower()
++
++        self.navigate_to_record(DEFAULT_TRUST_VIEW, entity=idview.ENTITY)
++        self.add_record(idview.ENTITY, {
++            'pkey': idoverrideuser_pkey,
++            'add': [
++                ('textbox', 'ipaanchoruuid_default', idoverrideuser_pkey),
++            ],
++        }, facet='idoverrideuser')
++
++        # Create new group and add the user ID override there
++        self.navigate_to_entity(group.ENTITY)
++        self.add_record(group.ENTITY, group.DATA)
++        self.navigate_to_record(group.PKEY)
++        self.add_associations([idoverrideuser_pkey],
++                              facet='member_idoverrideuser', delete=True)
++
++        # Clean up data
++        self.navigate_to_entity(group.ENTITY)
++        self.delete_record(group.PKEY)
++        self.navigate_to_record(DEFAULT_TRUST_VIEW, entity=idview.ENTITY)
++        self.delete_record(idoverrideuser_pkey)
++        self.navigate_to_entity(ENTITY)
++        self.delete_record(ad_domain)
+-- 
+2.26.2
+
diff --git a/SOURCES/0005-selinux-don-t-audit-rules-deny-fetching-trust-topology_rhbz#1845596.patch b/SOURCES/0005-selinux-don-t-audit-rules-deny-fetching-trust-topology_rhbz#1845596.patch
new file mode 100644
index 0000000..b67d1ef
--- /dev/null
+++ b/SOURCES/0005-selinux-don-t-audit-rules-deny-fetching-trust-topology_rhbz#1845596.patch
@@ -0,0 +1,93 @@
+From 42dd1628a1211363c860917e474ecc5b9c1fdb84 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Thu, 2 Jul 2020 15:50:00 +0300
+Subject: [PATCH] selinux: allow oddjobd to set up ipa_helper_t context for
+ execution
+
+On Fedora 32+ and RHEL 8.3.0+ execution of ipa_helper_t context requires
+SELinux policy permission to use 'noatsecure'. This comes most likely
+from execve() setup by glibc.
+
+Add SELinux interface ipa_helper_noatsecure() that can be called by
+oddjob's SELinux policy definition.
+
+In addition, if ipa_helper_t runs ipa-getkeytab, libkrb5 will attempt to
+access SELinux configuration and produce AVC for that. Allow reading
+general userspace SELinux configuration.
+
+Fixes: https://pagure.io/freeipa/issue/8395
+Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-By: Christian Heimes <cheimes@redhat.com>
+---
+ selinux/ipa.if | 18 ++++++++++++++++++
+ selinux/ipa.te |  1 +
+ 2 files changed, 19 insertions(+)
+
+diff --git a/selinux/ipa.if b/selinux/ipa.if
+index ea971b8fa..783db8b78 100644
+--- a/selinux/ipa.if
++++ b/selinux/ipa.if
+@@ -419,3 +419,21 @@ ifndef(`dirsrv_systemctl',`
+         ps_process_pattern($1, dirsrv_t)
+     ')
+ ')
++
++
++########################################
++## <summary>
++##	Allow ipa_helper noatsecure
++## </summary>
++## <param name="domain">
++##	<summary>
++##	Domain allowed access.
++##	</summary>
++## </param>
++#
++interface(`ipa_helper_noatsecure',`
++    gen_require(`
++	type ipa_helper_t;
++    ')
++    allow $1 ipa_helper_t:process { noatsecure };
++')
+diff --git a/selinux/ipa.te b/selinux/ipa.te
+index 587e5e585..383979094 100644
+--- a/selinux/ipa.te
++++ b/selinux/ipa.te
+@@ -115,6 +115,7 @@ optional_policy(`
+ 
+ 
+ allow ipa_helper_t self:capability { net_admin dac_read_search dac_override chown };
++seutil_read_config(ipa_helper_t);
+ 
+ #kernel bug
+ dontaudit ipa_helper_t self:capability2  block_suspend;
+-- 
+2.26.2
+
+From 0d70addbbf2a99e7398a518bc98d5fe109469bb5 Mon Sep 17 00:00:00 2001
+From: Alexander Bokovoy <abokovoy@redhat.com>
+Date: Fri, 3 Jul 2020 17:20:49 +0300
+Subject: [PATCH] selinux: support running ipa-custodia with PrivateTmp=yes
+
+Related: https://pagure.io/freeipa/issue/8395
+Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
+Reviewed-By: Christian Heimes <cheimes@redhat.com>
+---
+ selinux/ipa.te | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/selinux/ipa.te b/selinux/ipa.te
+index 383979094..a3381217a 100644
+--- a/selinux/ipa.te
++++ b/selinux/ipa.te
+@@ -390,3 +390,7 @@ optional_policy(`
+ 	sssd_search_lib(ipa_custodia_t)
+ 	sssd_stream_connect(ipa_custodia_t)
+ ')
++
++optional_policy(`
++       systemd_private_tmp(ipa_custodia_tmp_t)
++')
+-- 
+2.26.2
+
diff --git a/SOURCES/0006-fix-iPAddress-cert-issuance-for-1-host-service_rhbz#1846352.patch b/SOURCES/0006-fix-iPAddress-cert-issuance-for-1-host-service_rhbz#1846352.patch
new file mode 100644
index 0000000..c1c7764
--- /dev/null
+++ b/SOURCES/0006-fix-iPAddress-cert-issuance-for-1-host-service_rhbz#1846352.patch
@@ -0,0 +1,180 @@
+From 128500198d3782a76616cf1d971d5aeb17e8c1da Mon Sep 17 00:00:00 2001
+From: Fraser Tweedale <ftweedal@redhat.com>
+Date: Thu, 11 Jun 2020 22:42:38 +1000
+Subject: [PATCH] fix iPAddress cert issuance for >1 host/service
+
+The 'cert_request' command accumulates DNS names from the CSR,
+before checking that all IP addresses in the CSR are reachable from
+those DNS names.  Before adding a DNS name to the set, we check that
+that it corresponds to the FQDN of a known host/service principal
+(including principal aliases).  When a DNS name maps to a
+"alternative" principal (i.e.  not the one given via the 'principal'
+argument), this check was not being performed correctly.
+Specifically, we were looking for the 'krbprincipalname' field on
+the RPC response object directly, instead of its 'result' field.
+
+To resolve the issue, dereference the RPC response to its 'result'
+field before invoking the '_dns_name_matches_principal' subroutine.
+
+Fixes: https://pagure.io/freeipa/issue/8368
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+---
+ ipaserver/plugins/cert.py                     |  6 +-
+ .../test_cert_request_ip_address.py           | 62 +++++++++++++++++--
+ 2 files changed, 61 insertions(+), 7 deletions(-)
+
+diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
+index d353bc3ea..fe7ea34f5 100644
+--- a/ipaserver/plugins/cert.py
++++ b/ipaserver/plugins/cert.py
+@@ -827,13 +827,13 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
+                 try:
+                     if principal_type == HOST:
+                         alt_principal_obj = api.Command['host_show'](
+-                            name, all=True)
++                            name, all=True)['result']
+                     elif principal_type == KRBTGT:
+                         alt_principal = kerberos.Principal(
+                             (u'host', name), principal.realm)
+                     elif principal_type == SERVICE:
+                         alt_principal_obj = api.Command['service_show'](
+-                            alt_principal, all=True)
++                            alt_principal, all=True)['result']
+                 except errors.NotFound:
+                     # We don't want to issue any certificates referencing
+                     # machines we don't know about. Nothing is stored in this
+@@ -866,7 +866,7 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
+                         pass
+ 
+                     # Now check write access and caacl
+-                    altdn = alt_principal_obj['result']['dn']
++                    altdn = alt_principal_obj['dn']
+                     if not ldap.can_write(altdn, "usercertificate"):
+                         raise errors.ACIError(info=_(
+                             "Insufficient privilege to create a certificate "
+diff --git a/ipatests/test_xmlrpc/test_cert_request_ip_address.py b/ipatests/test_xmlrpc/test_cert_request_ip_address.py
+index bf4de05bf..c0475d30d 100644
+--- a/ipatests/test_xmlrpc/test_cert_request_ip_address.py
++++ b/ipatests/test_xmlrpc/test_cert_request_ip_address.py
+@@ -28,10 +28,16 @@ from ipatests.test_xmlrpc.tracker.host_plugin import HostTracker
+ from ipatests.test_xmlrpc.tracker.user_plugin import UserTracker
+ from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
+ 
+-host_fqdn = f'iptest.{api.env.domain}'
++host_shortname = 'iptest'
++host_fqdn = f'{host_shortname}.{api.env.domain}'
+ host_princ = f'host/{host_fqdn}'
+ host_ptr = f'{host_fqdn}.'
+ 
++host2_shortname = 'iptest2'
++host2_fqdn = f'{host2_shortname}.{api.env.domain}'
++host2_princ = f'host/{host2_fqdn}'
++host2_ptr = f'{host2_fqdn}.'
++
+ other_fqdn = f'other.{api.env.domain}'
+ other_ptr = f'{other_fqdn}.'
+ 
+@@ -39,6 +45,10 @@ ipv4_address = '169.254.0.42'
+ ipv4_revzone_s = '0.254.169.in-addr.arpa.'
+ ipv4_revrec_s = '42'
+ 
++host2_ipv4_address = '169.254.0.43'
++host2_ipv4_revzone_s = '0.254.169.in-addr.arpa.'
++host2_ipv4_revrec_s = '43'
++
+ ipv6_address = 'fe80::8f18:bdab:4299:95fa'
+ ipv6_revzone_s = '0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.'
+ ipv6_revrec_s = 'a.f.5.9.9.9.2.4.b.a.d.b.8.1.f.8'
+@@ -46,7 +56,13 @@ ipv6_revrec_s = 'a.f.5.9.9.9.2.4.b.a.d.b.8.1.f.8'
+ 
+ @pytest.fixture(scope='class')
+ def host(request, xmlrpc_setup):
+-    tr = HostTracker('iptest')
++    tr = HostTracker(host_shortname)
++    return tr.make_fixture(request)
++
++
++@pytest.fixture(scope='class')
++def host2(request, xmlrpc_setup):
++    tr = HostTracker(host2_shortname)
+     return tr.make_fixture(request)
+ 
+ 
+@@ -88,6 +104,12 @@ def ipv6_revzone(host):
+     yield from _zone_setup(host, ipv6_revzone_s)
+ 
+ 
++@pytest.fixture(scope='class')
++def host2_ipv4_ptr(host2, ipv4_revzone):
++    yield from _record_setup(
++        host2, ipv4_revzone, host2_ipv4_revrec_s, ptrrecord=host2_ptr)
++
++
+ @pytest.fixture(scope='class')
+ def ipv4_ptr(host, ipv4_revzone):
+     yield from _record_setup(
+@@ -100,16 +122,22 @@ def ipv6_ptr(host, ipv6_revzone):
+         host, ipv6_revzone, ipv6_revrec_s, ptrrecord=host_ptr)
+ 
+ 
++@pytest.fixture(scope='class')
++def host2_ipv4_a(host2):
++    yield from _record_setup(
++        host2, api.env.domain, host2_shortname, arecord=host2_ipv4_address)
++
++
+ @pytest.fixture(scope='class')
+ def ipv4_a(host):
+     yield from _record_setup(
+-        host, api.env.domain, 'iptest', arecord=ipv4_address)
++        host, api.env.domain, host_shortname, arecord=ipv4_address)
+ 
+ 
+ @pytest.fixture(scope='class')
+ def ipv6_aaaa(host):
+     yield from _record_setup(
+-        host, api.env.domain, 'iptest', aaaarecord=ipv6_address)
++        host, api.env.domain, host_shortname, aaaarecord=ipv6_address)
+ 
+ 
+ @pytest.fixture(scope='class')
+@@ -210,6 +238,12 @@ csr_cname2 = csr([
+     x509.DNSName(f'cname2.{api.env.domain}'),
+     x509.IPAddress(ipaddress.ip_address(ipv4_address)),
+ ])
++csr_two_dnsname_two_ip = csr([
++    x509.DNSName(host_fqdn),
++    x509.IPAddress(ipaddress.ip_address(ipv4_address)),
++    x509.DNSName(host2_fqdn),
++    x509.IPAddress(ipaddress.ip_address(host2_ipv4_address)),
++])
+ 
+ 
+ @pytest.fixture
+@@ -449,3 +483,23 @@ class TestIPAddressCNAME(XMLRPC_test):
+     def test_two_levels(self, host, csr_cname2):
+         with pytest.raises(errors.ValidationError, match=PAT_FWD):
+             host.run_command('cert_request', csr_cname2, principal=host_princ)
++
++
++@pytest.mark.tier1
++class TestTwoHostsTwoIPAddresses(XMLRPC_test):
++    """
++    Test certificate issuance with CSR containing two hosts
++    and two IP addresses (one for each host).
++
++    """
++    def test_host_exists(
++        self, host, host2, ipv4_a, ipv4_ptr, host2_ipv4_a, host2_ipv4_ptr,
++    ):
++        # for convenience, this test also establishes the DNS
++        # record fixtures, which have class scope
++        host.ensure_exists()
++        host2.ensure_exists()
++
++    def test_issuance(self, host, csr_two_dnsname_two_ip):
++        host.run_command(
++            'cert_request', csr_two_dnsname_two_ip, principal=host_princ)
+-- 
+2.26.2
+
diff --git a/SOURCES/0007-Specify-cert_paths-when-calling-PKIConnection_rhbz#1849155.patch b/SOURCES/0007-Specify-cert_paths-when-calling-PKIConnection_rhbz#1849155.patch
new file mode 100644
index 0000000..72a73cb
--- /dev/null
+++ b/SOURCES/0007-Specify-cert_paths-when-calling-PKIConnection_rhbz#1849155.patch
@@ -0,0 +1,118 @@
+From 9ded9e2573a00c388533f2a09365c499a4e2961e Mon Sep 17 00:00:00 2001
+From: Alexander Scheel <ascheel@redhat.com>
+Date: Fri, 19 Jun 2020 08:48:56 -0400
+Subject: [PATCH] Specify cert_paths when calling PKIConnection
+
+PKIConnection now defaults to specifying verify=True. We've introduced
+a new parameter, cert_paths, to specify additional paths (directories or
+files) to load as certificates. Specify the IPA CA certificate file so
+we can guarantee connections succeed and validate the peer's certificate.
+
+Point to IPA CA certificate during pkispawn
+
+Bump pki_version to 10.9.0-0.4 (aka -b2)
+
+Fixes: https://pagure.io/freeipa/issue/8379
+Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1849155
+Related: https://github.com/dogtagpki/pki/pull/443
+Related: https://bugzilla.redhat.com/show_bug.cgi?id=1426572
+Signed-off-by: Alexander Scheel <ascheel@redhat.com>
+Signed-off-by: Christian Heimes <cheimes@redhat.com>
+Reviewed-By: Christian Heimes <cheimes@redhat.com>
+---
+ freeipa.spec.in                       |  6 +++---
+ install/tools/ipa-pki-wait-running.in |  3 ++-
+ ipaserver/install/cainstance.py       |  7 +++++++
+ ipaserver/install/dogtaginstance.py   |  3 ++-
+ ipaserver/plugins/dogtag.py           | 11 +++++------
+ 5 files changed, 19 insertions(+), 11 deletions(-)
+
+diff --git a/freeipa.spec.in b/freeipa.spec.in
+index 74e752ea5..d00b9d640 100755
+--- a/freeipa.spec.in
++++ b/freeipa.spec.in
+@@ -112,9 +112,9 @@
+ # Fedora
+ %endif
+ 
+-# 10.7.3 supports LWCA key replication using AES
+-# https://pagure.io/freeipa/issue/8020
+-%global pki_version 10.7.3-1
++# PKIConnection has been modified to always validate certs.
++# https://pagure.io/freeipa/issue/8379
++%global pki_version 10.9.0-0.4
+ 
+ # https://pagure.io/certmonger/issue/90
+ %global certmonger_version 0.79.7-1
+diff --git a/install/tools/ipa-pki-wait-running.in b/install/tools/ipa-pki-wait-running.in
+index 69f5ec296..4f0f2f34a 100644
+--- a/install/tools/ipa-pki-wait-running.in
++++ b/install/tools/ipa-pki-wait-running.in
+@@ -59,7 +59,8 @@ def get_conn(hostname, subsystem):
+     """
+     conn = PKIConnection(
+         hostname=hostname,
+-        subsystem=subsystem
++        subsystem=subsystem,
++        cert_paths=paths.IPA_CA_CRT
+     )
+     logger.info(
+         "Created connection %s://%s:%s/%s",
+diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
+index 706bc28cc..9294f1dba 100644
+--- a/ipaserver/install/cainstance.py
++++ b/ipaserver/install/cainstance.py
+@@ -509,6 +509,13 @@ class CAInstance(DogtagInstance):
+         else:
+             pki_pin = None
+ 
++        # When spawning a CA instance, always point to IPA_CA_CRT if it
++        # exists. Later, when we're performing step 2 of an external CA
++        # installation, we'll overwrite this key to point to the real
++        # external CA.
++        if os.path.exists(paths.IPA_CA_CRT):
++            cfg['pki_cert_chain_path'] = paths.IPA_CA_CRT
++
+         if self.clone:
+             if self.no_db_setup:
+                 cfg.update(
+diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
+index 361d80a8c..7e295665c 100644
+--- a/ipaserver/install/dogtaginstance.py
++++ b/ipaserver/install/dogtaginstance.py
+@@ -70,7 +70,8 @@ def get_security_domain():
+     connection = PKIConnection(
+         protocol='https',
+         hostname=api.env.ca_host,
+-        port='8443'
++        port='8443',
++        cert_paths=paths.IPA_CA_CRT
+     )
+     domain_client = pki.system.SecurityDomainClient(connection)
+     info = domain_client.get_security_domain_info()
+diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py
+index 4de26d76f..b300f6b18 100644
+--- a/ipaserver/plugins/dogtag.py
++++ b/ipaserver/plugins/dogtag.py
+@@ -2082,13 +2082,12 @@ class kra(Backend):
+             'https',
+             self.kra_host,
+             str(self.kra_port),
+-            'kra')
++            'kra',
++            cert_paths=paths.IPA_CA_CRT
++        )
+ 
+-        connection.session.cert = (paths.RA_AGENT_PEM, paths.RA_AGENT_KEY)
+-        # uncomment the following when this commit makes it to release
+-        # https://git.fedorahosted.org/cgit/pki.git/commit/?id=71ae20c
+-        # connection.set_authentication_cert(paths.RA_AGENT_PEM,
+-        #                                    paths.RA_AGENT_KEY)
++        connection.set_authentication_cert(paths.RA_AGENT_PEM,
++                                           paths.RA_AGENT_KEY)
+ 
+         try:
+             yield KRAClient(connection, crypto)
+-- 
+2.26.2
+
diff --git a/SOURCES/0008-Add-missing-SELinux-rule-for-ipa-custodia.sock_rhbz#1857157.patch b/SOURCES/0008-Add-missing-SELinux-rule-for-ipa-custodia.sock_rhbz#1857157.patch
new file mode 100644
index 0000000..c94ebee
--- /dev/null
+++ b/SOURCES/0008-Add-missing-SELinux-rule-for-ipa-custodia.sock_rhbz#1857157.patch
@@ -0,0 +1,34 @@
+From d83b760d1f76a3ba8e527dd27551e51a600b22c0 Mon Sep 17 00:00:00 2001
+From: Christian Heimes <cheimes@redhat.com>
+Date: Wed, 15 Jul 2020 10:23:35 +0200
+Subject: [PATCH] Add missing SELinux rule for ipa-custodia.sock
+
+A SELinux rule for ipa_custodia_stream_connect(httpd_t) was not copied
+from upstream rules. It breaks installations on systems that don't have
+ipa_custodia_stream_connect in SELinux domain for apache, e.g. RHEL 8.3.
+
+Fixes: https://pagure.io/freeipa/issue/8412
+Signed-off-by: Christian Heimes <cheimes@redhat.com>
+Reviewed-By: Thomas Woerner <twoerner@redhat.com>
+---
+ selinux/ipa.te | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/selinux/ipa.te b/selinux/ipa.te
+index a3381217a4..c4c3fa805e 100644
+--- a/selinux/ipa.te
++++ b/selinux/ipa.te
+@@ -378,6 +378,13 @@ optional_policy(`
+ 	ipa_search_lib(ipa_custodia_t)
+ ')
+ 
++optional_policy(`
++    gen_require(`
++        type httpd_t;
++    ')
++    ipa_custodia_stream_connect(httpd_t)
++')
++
+ optional_policy(`
+ 	pki_manage_tomcat_etc_rw(ipa_custodia_t)
+ 	pki_read_tomcat_cert(ipa_custodia_t)
diff --git a/SOURCES/0009-ipa-client-install-use-the-authselect-backup-during_rhbz#1810179.patch b/SOURCES/0009-ipa-client-install-use-the-authselect-backup-during_rhbz#1810179.patch
new file mode 100644
index 0000000..5a96294
--- /dev/null
+++ b/SOURCES/0009-ipa-client-install-use-the-authselect-backup-during_rhbz#1810179.patch
@@ -0,0 +1,189 @@
+From ca880cfb117fc870a6e2710b9e31b2f67d5651e1 Mon Sep 17 00:00:00 2001
+From: Florence Blanc-Renaud <flo@redhat.com>
+Date: Wed, 29 Jul 2020 13:35:49 +0200
+Subject: [PATCH] ipa-client-install: use the authselect backup during
+ uninstall
+
+When ipa-client-install is run on a system with no existing
+authselect configuration (for instance a fedora 31 new install),
+uninstallation is picking sssd profile but this may lead to
+a configuration with differences compared to the pre-ipa-client
+state.
+
+Now that authselect provides an option to backup the existing
+configuration prior to setting a profile, the client install
+can save the backup name and uninstall is able to apply the
+backup in order to go back to the pre-ipa-client state.
+
+Fixes: https://pagure.io/freeipa/issue/8189
+Reviewed-By: Francois Cami <fcami@redhat.com>
+Reviewed-By: Michal Polovka <mpolovka@redhat.com>
+---
+ ipaplatform/redhat/authconfig.py | 37 ++++++++++++++------------------
+ 1 file changed, 16 insertions(+), 21 deletions(-)
+
+diff --git a/ipaplatform/redhat/authconfig.py b/ipaplatform/redhat/authconfig.py
+index 758376f2b..89f452d66 100644
+--- a/ipaplatform/redhat/authconfig.py
++++ b/ipaplatform/redhat/authconfig.py
+@@ -27,6 +27,7 @@ from ipaplatform.paths import paths
+ from ipapython import ipautil
+ from ipapython.admintool import ScriptError
+ import os
++import time
+ 
+ FILES_TO_NOT_BACKUP = ['passwd', 'group', 'shadow', 'gshadow']
+ 
+@@ -103,28 +104,16 @@ class RedHatAuthSelect(RedHatAuthToolBase):
+     def configure(self, sssd, mkhomedir, statestore, sudo=True):
+         # In the statestore, the following keys are used for the
+         # 'authselect' module:
++        # Old method:
+         # profile: name of the profile configured pre-installation
+         # features_list: list of features configured pre-installation
+         # mkhomedir: True if installation was called with --mkhomedir
+         # profile and features_list are used when reverting to the
+         # pre-install state
+-        cfg = self._parse_authselect_output()
+-        if cfg:
+-            statestore.backup_state('authselect', 'profile', cfg[0])
+-            statestore.backup_state(
+-                    'authselect', 'features_list', " ".join(cfg[1]))
+-        else:
+-            # cfg = None means that the current conf is not managed by
+-            # authselect but by authconfig.
+-            # As we are using authselect to configure the host,
+-            # it will not be possible to revert to a custom authconfig
+-            # configuration later (during uninstall)
+-            # Best thing to do will be to use sssd profile at this time
+-            logger.warning(
+-                "WARNING: The configuration pre-client installation is not "
+-                "managed by authselect and cannot be backed up. "
+-                "Uninstallation may not be able to revert to the original "
+-                "state.")
++        # New method:
++        # backup: name of the authselect backup
++        backup_name = "pre_ipaclient_{}".format(time.strftime("%Y%m%d%H%M%S"))
++        statestore.backup_state('authselect', 'backup', backup_name)
+ 
+         cmd = [paths.AUTHSELECT, "select", "sssd"]
+         if mkhomedir:
+@@ -133,6 +122,7 @@ class RedHatAuthSelect(RedHatAuthToolBase):
+         if sudo:
+             cmd.append("with-sudo")
+         cmd.append("--force")
++        cmd.append("--backup={}".format(backup_name))
+ 
+         ipautil.run(cmd)
+ 
+@@ -179,10 +169,15 @@ class RedHatAuthSelect(RedHatAuthToolBase):
+             else:
+                 features = []
+ 
+-        cmd = [paths.AUTHSELECT, "select", profile]
+-        cmd.extend(features)
+-        cmd.append("--force")
+-        ipautil.run(cmd)
++        backup = statestore.restore_state('authselect', 'backup')
++        if backup:
++            cmd = [paths.AUTHSELECT, "backup-restore", backup]
++            ipautil.run(cmd)
++        else:
++            cmd = [paths.AUTHSELECT, "select", profile]
++            cmd.extend(features)
++            cmd.append("--force")
++            ipautil.run(cmd)
+ 
+     def backup(self, path):
+         current = self._get_authselect_current_output()
+-- 
+2.26.2
+
+# Not needed for 4.7.8 release
+#
+#From 3eaab97e317584bc47d4a27a607267ed90df7ff7 Mon Sep 17 00:00:00 2001
+#From: Florence Blanc-Renaud <flo@redhat.com>
+#Date: Wed, 29 Jul 2020 13:40:26 +0200
+#Subject: [PATCH] ipatests: remove the xfail for test_nfs.py
+#
+#Related: https://pagure.io/freeipa/issue/8189
+#Reviewed-By: Francois Cami <fcami@redhat.com>
+#Reviewed-By: Michal Polovka <mpolovka@redhat.com>
+#---
+# ipatests/test_integration/test_nfs.py | 4 ----
+# 1 file changed, 4 deletions(-)
+#
+#diff --git a/ipatests/test_integration/test_nfs.py b/ipatests/test_integration/test_nfs.py
+#index 7272b0d44..832c56cca 100644
+#--- a/ipatests/test_integration/test_nfs.py
+#+++ b/ipatests/test_integration/test_nfs.py
+#@@ -363,10 +363,6 @@ class TestIpaClientAutomountFileRestore(IntegrationTest):
+#         cmd = self.clients[0].run_command(sha256nsswitch_cmd)
+#         assert cmd.stdout_text == orig_sha256
+# 
+#-    @pytest.mark.xfail(
+#-        reason="https://pagure.io/freeipa/issue/8189",
+#-        strict=True
+#-    )
+#     def test_nsswitch_backup_restore_sssd(self):
+#         self.nsswitch_backup_restore()
+# 
+#-- 
+#2.26.2
+
+From 4baf6b292f28481ece483bb8ecbd6a0807d9d45a Mon Sep 17 00:00:00 2001
+From: Florence Blanc-Renaud <flo@redhat.com>
+Date: Wed, 29 Jul 2020 17:57:53 +0200
+Subject: [PATCH] ipatests: fix test_authselect
+
+Before the code fix, install/uninstall on a config without
+any authselect profile was not able to restore the exact
+state but configured sssd profile instead.
+
+Now that the code is doing a pre-install backup, uninstall
+restores the exact state and the test needs to be updated
+accordingly.
+
+Related: https://pagure.io/freeipa/issue/8189
+Reviewed-By: Francois Cami <fcami@redhat.com>
+Reviewed-By: Michal Polovka <mpolovka@redhat.com>
+---
+ ipatests/test_integration/test_authselect.py | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
+
+diff --git a/ipatests/test_integration/test_authselect.py b/ipatests/test_integration/test_authselect.py
+index bdf7d9f77..cba23e707 100644
+--- a/ipatests/test_integration/test_authselect.py
++++ b/ipatests/test_integration/test_authselect.py
+@@ -100,7 +100,9 @@ class TestClientInstallation(IntegrationTest):
+             ['rm', '-f', '/etc/authselect/authselect.conf'])
+         result = self._install_client()
+         assert result.returncode == 0
+-        assert self.msg_warn_install in result.stderr_text
++        # With the fix for 8189, there is no warning any more
++        # because install is performing a pre-install backup
++        assert self.msg_warn_install not in result.stderr_text
+         # Client installation must configure the 'sssd' profile
+         # with sudo
+         check_authselect_profile(self.client, default_profile, ('with-sudo',))
+@@ -109,12 +111,13 @@ class TestClientInstallation(IntegrationTest):
+         """
+         Test client un-installation when there was no authselect profile
+         """
+-        # As the client did not have any authselect profile before install,
+-        # uninstall must print a warning about restoring 'sssd' profile
+-        # by default
++        # The client did not have any authselect profile before install,
++        # but uninstall must be able to restore the backup
++        # Check that no profile is configured after uninstall
+         result = self._uninstall_client()
+         assert result.returncode == 0
+-        check_authselect_profile(self.client, default_profile)
++        assert not self.client.transport.file_exists(
++            '/etc/authselect/authselect.conf')
+ 
+     def test_install_client_preconfigured_profile(self):
+         """
+-- 
+2.26.2
+
diff --git a/SOURCES/0010-Replace-SSLCertVerificationError-with-CertificateErr_rhbz#1858318.patch b/SOURCES/0010-Replace-SSLCertVerificationError-with-CertificateErr_rhbz#1858318.patch
new file mode 100644
index 0000000..4144d57
--- /dev/null
+++ b/SOURCES/0010-Replace-SSLCertVerificationError-with-CertificateErr_rhbz#1858318.patch
@@ -0,0 +1,32 @@
+From 66a5a0efd538e31a190ca6ecb775bc1dfc4ee232 Mon Sep 17 00:00:00 2001
+From: Rob Crittenden <rcritten@redhat.com>
+Date: Wed, 29 Jul 2020 13:42:43 -0400
+Subject: [PATCH] Replace SSLCertVerificationError with CertificateError for
+ py36
+
+This exception was added in python 3.7. Use CertificateError
+instead which is an alias and will work with older python releases.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1858318
+
+Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
+---
+ ipaserver/install/server/upgrade.py | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
+index 2c36bc0e2..2c1517865 100644
+--- a/ipaserver/install/server/upgrade.py
++++ b/ipaserver/install/server/upgrade.py
+@@ -667,7 +667,7 @@ def http_certificate_ensure_ipa_ca_dnsname(http):
+ 
+     try:
+         cert.match_hostname(expect)
+-    except ssl.SSLCertVerificationError:
++    except ssl.CertificateError:
+         if certs.is_ipa_issued_cert(api, cert):
+             request_id = certmonger.get_request_id(
+                 {'cert-file': paths.HTTPD_CERT_FILE})
+-- 
+2.26.2
+
diff --git a/SOURCES/0011-Fix-AVC-denial-during-ipa-adtrust-install---add-agents_rhbz#1859213.patch b/SOURCES/0011-Fix-AVC-denial-during-ipa-adtrust-install---add-agents_rhbz#1859213.patch
new file mode 100644
index 0000000..1298351
--- /dev/null
+++ b/SOURCES/0011-Fix-AVC-denial-during-ipa-adtrust-install---add-agents_rhbz#1859213.patch
@@ -0,0 +1,103 @@
+From c72ef1ed965aca79da4576d9579dec5459e14b99 Mon Sep 17 00:00:00 2001
+From: Christian Heimes <cheimes@redhat.com>
+Date: Fri, 8 May 2020 15:27:01 +0200
+Subject: [PATCH] SELinux: Backport dirsrv_systemctl interface
+
+Signed-off-by: Christian Heimes <cheimes@redhat.com>
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+Reviewed-By: Christian Heimes <cheimes@redhat.com>
+---
+ selinux/ipa.if | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/selinux/ipa.if b/selinux/ipa.if
+index cefae5d90..ea971b8fa 100644
+--- a/selinux/ipa.if
++++ b/selinux/ipa.if
+@@ -392,3 +392,30 @@ ifndef(`apache_manage_pid_files',`
+ 		manage_sock_files_pattern($1, httpd_var_run_t, httpd_var_run_t)
+ 	')
+ ')
++
++########################################
++## <summary>
++##	Execute dirsrv server in the dirsrv domain.
++##  Backport from https://github.com/fedora-selinux/selinux-policy-contrib/pull/241
++## </summary>
++## <param name="domain">
++##	<summary>
++##	Domain allowed to transition.
++##	</summary>
++## </param>
++#
++ifndef(`dirsrv_systemctl',`
++    interface(`dirsrv_systemctl',`
++        gen_require(`
++            type dirsrv_unit_file_t;
++            type dirsrv_t;
++        ')
++
++        systemd_exec_systemctl($1)
++        init_reload_services($1)
++        allow $1 dirsrv_unit_file_t:file read_file_perms;
++        allow $1 dirsrv_unit_file_t:service manage_service_perms;
++
++        ps_process_pattern($1, dirsrv_t)
++    ')
++')
+-- 
+2.26.2
+
+From f76c56c6072418c78f138678b1c4dd917fea6ee1 Mon Sep 17 00:00:00 2001
+From: Zdenek Pytela <zpytela@redhat.com>
+Date: Thu, 7 May 2020 16:17:12 +0200
+Subject: [PATCH] Allow ipa-adtrust-install restart sssd and dirsrv services
+
+Allow ipa_helper_t connect to init using /run/systemd/private socket.
+Allow ipa_helper_t read init process state.
+Allow ipa_helper_t manage sssd and dirsrv units.
+
+See: https://bugzilla.redhat.com/show_bug.cgi?id=1820298
+See: https://github.com/fedora-selinux/selinux-policy-contrib/pull/241
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+Reviewed-By: Christian Heimes <cheimes@redhat.com>
+---
+ selinux/ipa.te | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+diff --git a/selinux/ipa.te b/selinux/ipa.te
+index b1e29c8e2..587e5e585 100644
+--- a/selinux/ipa.te
++++ b/selinux/ipa.te
+@@ -147,6 +147,9 @@ auth_use_nsswitch(ipa_helper_t)
+ 
+ files_list_tmp(ipa_helper_t)
+ 
++init_read_state(ipa_helper_t)
++init_stream_connect(ipa_helper_t)
++
+ ipa_manage_pid_files(ipa_helper_t)
+ ipa_read_lib(ipa_helper_t)
+ 
+@@ -156,6 +159,10 @@ optional_policy(`
+     dirsrv_stream_connect(ipa_helper_t)
+ ')
+ 
++optional_policy(`
++    dirsrv_systemctl(ipa_helper_t)
++')
++
+ optional_policy(`
+     ldap_stream_connect(ipa_helper_t)
+ ')
+@@ -182,6 +189,7 @@ optional_policy(`
+ 
+ optional_policy(`
+     sssd_manage_lib_files(ipa_helper_t)
++    sssd_systemctl(ipa_helper_t)
+ ')
+ 
+ ########################################
+-- 
+2.26.2
+
diff --git a/SOURCES/0012-CAless-installation-set-the-perms-on-KDC-cert-file_rhbz#1863616.patch b/SOURCES/0012-CAless-installation-set-the-perms-on-KDC-cert-file_rhbz#1863616.patch
new file mode 100644
index 0000000..ac9ddfe
--- /dev/null
+++ b/SOURCES/0012-CAless-installation-set-the-perms-on-KDC-cert-file_rhbz#1863616.patch
@@ -0,0 +1,84 @@
+From 81c955e561dd42ab70a39bf636c90e82a9d7d899 Mon Sep 17 00:00:00 2001
+From: Florence Blanc-Renaud <flo@redhat.com>
+Date: Mon, 3 Aug 2020 18:52:07 +0200
+Subject: [PATCH] CAless installation: set the perms on KDC cert file
+
+In CA less installation, the KDC certificate file does not have
+the expected 644 permissions. As a consequence, WebUI login
+fails.
+
+The fix makes sure that the KDC cert file is saved with 644 perms.
+
+Fixes: https://pagure.io/freeipa/issue/8440
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+---
+ ipaserver/install/krbinstance.py | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
+index 09d14693c..1910ff374 100644
+--- a/ipaserver/install/krbinstance.py
++++ b/ipaserver/install/krbinstance.py
+@@ -536,6 +536,8 @@ class KrbInstance(service.Service):
+         certs.install_pem_from_p12(self.pkcs12_info[0],
+                                    self.pkcs12_info[1],
+                                    paths.KDC_CERT)
++        # The KDC cert needs to be readable by everyone
++        os.chmod(paths.KDC_CERT, 0o644)
+         certs.install_key_from_p12(self.pkcs12_info[0],
+                                    self.pkcs12_info[1],
+                                    paths.KDC_KEY)
+-- 
+2.26.2
+
+From 295dd4235f693b7b4b4270b46a28cb6e7b3d00b4 Mon Sep 17 00:00:00 2001
+From: Florence Blanc-Renaud <flo@redhat.com>
+Date: Mon, 3 Aug 2020 18:53:47 +0200
+Subject: [PATCH] ipatests: check KDC cert permissions in CA less install
+
+The KDC certificate file must be stored with 644 permissions.
+Add a test checking the file permissions on server + replica.
+
+Related: https://pagure.io/freeipa/issue/8440
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+---
+ ipatests/test_integration/test_caless.py | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/ipatests/test_integration/test_caless.py b/ipatests/test_integration/test_caless.py
+index a7b2cbbbc..1ea7d9896 100644
+--- a/ipatests/test_integration/test_caless.py
++++ b/ipatests/test_integration/test_caless.py
+@@ -1527,6 +1527,13 @@ class TestCertInstall(CALessBase):
+         assert result.returncode == 0
+ 
+ 
++def verify_kdc_cert_perms(host):
++    """Verify that the KDC cert pem file has 0644 perms"""
++    cmd = host.run_command(['stat', '-c',
++                           '"%a %G:%U"', paths.KDC_CERT])
++    assert "644 root:root" in cmd.stdout_text
++
++
+ class TestPKINIT(CALessBase):
+     """Install master and replica with PKINIT"""
+     num_replicas = 1
+@@ -1540,6 +1547,7 @@ class TestPKINIT(CALessBase):
+         result = cls.install_server(pkinit_pkcs12_exists=True,
+                                     pkinit_pin=_DEFAULT)
+         assert result.returncode == 0
++        verify_kdc_cert_perms(cls.master)
+ 
+     @replica_install_teardown
+     def test_server_replica_install_pkinit(self):
+@@ -1549,6 +1557,7 @@ class TestPKINIT(CALessBase):
+                                       pkinit_pin=_DEFAULT)
+         assert result.returncode == 0
+         self.verify_installation()
++        verify_kdc_cert_perms(self.replicas[0])
+ 
+ 
+ class TestServerReplicaCALessToCAFull(CALessBase):
+-- 
+2.26.2
+
diff --git a/SOURCES/0013-IPA-EPN-Use-a-helper-to-retrieve-LDAP-attributes-fro_rhbz#1866938.patch b/SOURCES/0013-IPA-EPN-Use-a-helper-to-retrieve-LDAP-attributes-fro_rhbz#1866938.patch
new file mode 100644
index 0000000..b2655a8
--- /dev/null
+++ b/SOURCES/0013-IPA-EPN-Use-a-helper-to-retrieve-LDAP-attributes-fro_rhbz#1866938.patch
@@ -0,0 +1,145 @@
+From b95817e35716bbab000633043817202e17d7c53e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= <fcami@redhat.com>
+Date: Thu, 6 Aug 2020 17:07:36 +0200
+Subject: [PATCH] IPA-EPN: Use a helper to retrieve LDAP attributes from an
+ entry
+
+Allow for empty attributes.
+
+Reviewed-By: Francois Cami <fcami@redhat.com>
+---
+ ipaclient/install/ipa_epn.py | 22 +++++++++++++++-------
+ 1 file changed, 15 insertions(+), 7 deletions(-)
+
+diff --git a/ipaclient/install/ipa_epn.py b/ipaclient/install/ipa_epn.py
+index 65f9f3d47..0d1ae2add 100644
+--- a/ipaclient/install/ipa_epn.py
++++ b/ipaclient/install/ipa_epn.py
+@@ -122,22 +122,30 @@ class EPNUserList:
+         """Return len(self)."""
+         return len(self._expiring_password_user_dq)
+ 
++    def get_ldap_attr(self, entry, attr):
++        """Get a single value from a multi-valued attr in a safe way"""
++        return str(entry.get(attr, [""]).pop(0))
++
+     def add(self, entry):
+         """Parses and appends an LDAP user entry with the uid, cn,
+            givenname, sn, krbpasswordexpiration and mail attributes.
+         """
+         try:
+             self._sorted = False
++            if entry.get("mail") is None:
++                logger.error("IPA-EPN: No mail address defined for: %s",
++                             entry.dn)
++                return
+             self._expiring_password_user_dq.append(
+                 dict(
+-                    uid=str(entry["uid"].pop(0)),
+-                    cn=str(entry["cn"].pop(0)),
+-                    givenname=str(entry["givenname"].pop(0)),
+-                    sn=str(entry["sn"].pop(0)),
+-                    krbpasswordexpiration=str(
+-                        entry["krbpasswordexpiration"].pop(0)
++                    uid=self.get_ldap_attr(entry, "uid"),
++                    cn=self.get_ldap_attr(entry, "cn"),
++                    givenname=self.get_ldap_attr(entry, "givenname"),
++                    sn=self.get_ldap_attr(entry, "sn"),
++                    krbpasswordexpiration=(
++                        self.get_ldap_attr(entry,"krbpasswordexpiration")
+                     ),
+-                    mail=str(entry["mail"]),
++                    mail=str(entry.get("mail")),
+                 )
+             )
+         except IndexError as e:
+-- 
+2.26.2
+
+From 8e810d8cf38ec60d76178bd673e218fb05d56c8e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= <fcami@redhat.com>
+Date: Thu, 6 Aug 2020 17:13:19 +0200
+Subject: [PATCH] IPA-EPN: fix configuration file typo
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: François Cami <fcami@redhat.com>
+Reviewed-By: Francois Cami <fcami@redhat.com>
+---
+ client/share/epn.conf | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/client/share/epn.conf b/client/share/epn.conf
+index 0e590dfc3..e3645801c 100644
+--- a/client/share/epn.conf
++++ b/client/share/epn.conf
+@@ -23,7 +23,7 @@ smtp_port = 25
+ # Default None (empty value).
+ # smtp_password =
+ 
+-# pecifies the number of seconds to wait for SMTP to respond.
++# Specifies the number of seconds to wait for SMTP to respond.
+ smtp_timeout = 60
+ 
+ # Specifies the type of secure connection to make. Options are: none,
+-- 
+2.26.2
+
+From 1b1dbcbe9d83ba35f3cfdd01399f123816ec6e5b Mon Sep 17 00:00:00 2001
+From: Rob Crittenden <rcritten@redhat.com>
+Date: Thu, 6 Aug 2020 18:57:10 -0400
+Subject: [PATCH] IPA-EPN: Test that users without givenname and/or mail are
+ handled
+
+The admin user does not have a givenname by default, allow for that.
+
+Report errors for users without a default e-mail address.
+
+Update the SHA256 hash with the typo fix.
+
+Reviewed-By: Francois Cami <fcami@redhat.com>
+---
+ ipatests/test_integration/test_epn.py | 22 +++++++++++++++++++++-
+ 1 file changed, 21 insertions(+), 1 deletion(-)
+
+diff --git a/ipatests/test_integration/test_epn.py b/ipatests/test_integration/test_epn.py
+index 18f73c722..c5c73835a 100644
+--- a/ipatests/test_integration/test_epn.py
++++ b/ipatests/test_integration/test_epn.py
+@@ -240,7 +240,7 @@ class TestEPN(IntegrationTest):
+         assert epn_conf in cmd1.stdout_text
+         assert epn_template in cmd1.stdout_text
+         cmd2 = self.master.run_command(["sha256sum", epn_conf])
+-        ck = "4c207b5c9c760c36db0d3b2b93da50ea49edcc4002d6d1e7383601f0ec30b957"
++        ck = "192481b52fb591112afd7b55b12a44c6618fdbc7e05a3b1866fd67ec579c51df"
+         assert cmd2.stdout_text.find(ck) == 0
+ 
+     def test_EPN_smoketest_1(self):
+@@ -591,3 +591,23 @@ class TestEPN(IntegrationTest):
+         self.master.put_file_contents('/etc/ipa/epn.conf', epn_conf)
+         result = tasks.ipa_epn(self.master, raiseonerr=False)
+         assert "smtp_delay cannot be less than zero" in result.stderr_text
++
++    def test_EPN_admin(self):
++        """The admin user is special and has no givenName by default
++           It also doesn't by default have an e-mail address
++           Check --dry-run output.
++        """
++        epn_conf = textwrap.dedent('''
++            [global]
++        ''')
++        self.master.put_file_contents('/etc/ipa/epn.conf', epn_conf)
++        self.master.run_command(
++            ['ipa', 'user-mod', 'admin', '--password-expiration',
++             datetime_to_generalized_time(
++                 datetime.datetime.utcnow() + datetime.timedelta(days=7)
++             )]
++        )
++        (unused, stderr_text, _unused) = self._check_epn_output(
++            self.master, dry_run=True
++        )
++        assert "uid=admin" in stderr_text
+-- 
+2.26.2
+
diff --git a/SOURCES/0014-IPA-EPN-enhance-input-validation_rhbz#1866291.patch b/SOURCES/0014-IPA-EPN-enhance-input-validation_rhbz#1866291.patch
new file mode 100644
index 0000000..b905262
--- /dev/null
+++ b/SOURCES/0014-IPA-EPN-enhance-input-validation_rhbz#1866291.patch
@@ -0,0 +1,404 @@
+From 9479a393a71fe1de7d62ca2b50a7d3d8698d4ba1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= <fcami@redhat.com>
+Date: Tue, 4 Aug 2020 11:05:31 +0200
+Subject: [PATCH] ipatests: tasks.py: fix ipa-epn invocation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+tasks.py::ipa_epn would previously fail to invoke ipa-epn with
+from_nbdays=0.
+
+Related: https://pagure.io/freeipa/issue/8449
+Signed-off-by: François Cami <fcami@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+---
+ ipatests/pytest_ipa/integration/tasks.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ipatests/pytest_ipa/integration/tasks.py b/ipatests/pytest_ipa/integration/tasks.py
+index a3f7cc838..c0a592750 100755
+--- a/ipatests/pytest_ipa/integration/tasks.py
++++ b/ipatests/pytest_ipa/integration/tasks.py
+@@ -1470,9 +1470,9 @@ def ipa_epn(
+         cmd.append("--dry-run")
+     if mailtest:
+         cmd.append("--mail-test")
+-    if from_nbdays:
++    if from_nbdays is not None:
+         cmd.extend(("--from-nbdays", str(from_nbdays)))
+-    if to_nbdays:
++    if to_nbdays is not None:
+         cmd.extend(("--to-nbdays", str(to_nbdays)))
+     return host.run_command(cmd, raiseonerr=raiseonerr)
+ 
+-- 
+2.26.2
+
+From 3b8fdd87760cfb8ec739c67298f012cf0bd3ac39 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= <fcami@redhat.com>
+Date: Wed, 5 Aug 2020 10:02:31 +0200
+Subject: [PATCH] ipatests: test_epn: test_EPN_nbdays enhancements
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Enhance test_EPN_nbdays so that it checks:
+* that no emails get sent when using --dry-run
+* that --from-nbdays implies --dry-run
+* that --to-nbdays requires --from-nbdays
+* illegal inputs for nbdays:
+** from-nbdays > to-nbdays
+** non-numerical input
+** decimal input
+
+Fixes: https://pagure.io/freeipa/issue/8449
+Signed-off-by: François Cami <fcami@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+---
+ ipatests/test_integration/test_epn.py | 130 +++++++++++++++++++++++---
+ 1 file changed, 117 insertions(+), 13 deletions(-)
+
+diff --git a/ipatests/test_integration/test_epn.py b/ipatests/test_integration/test_epn.py
+index f4c123c6d..18f73c722 100644
+--- a/ipatests/test_integration/test_epn.py
++++ b/ipatests/test_integration/test_epn.py
+@@ -15,6 +15,13 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
++######
++# This test suite will _expectedly_ fail if run at the end of the UTC day
++# because users would be created during day N and then EPN output checked
++# during day N+1. This is expected and should be ignored as it does not
++# reflect a product bug. -- fcami
++######
++
+ from __future__ import print_function, absolute_import
+ 
+ import base64
+@@ -178,12 +185,14 @@ class TestEPN(IntegrationTest):
+         from_nbdays=None,
+         to_nbdays=None,
+         raiseonerr=True,
++        validatejson=True
+     ):
+         result = tasks.ipa_epn(host, raiseonerr=raiseonerr, dry_run=dry_run,
+                                from_nbdays=from_nbdays,
+                                to_nbdays=to_nbdays)
+-        json.dumps(json.loads(result.stdout_text), ensure_ascii=False)
+-        return (result.stdout_text, result.stderr_text)
++        if validatejson:
++            json.dumps(json.loads(result.stdout_text), ensure_ascii=False)
++        return (result.stdout_text, result.stderr_text, result.returncode)
+ 
+     @classmethod
+     def install(cls, mh):
+@@ -244,12 +253,12 @@ class TestEPN(IntegrationTest):
+         ''')
+         self.master.put_file_contents('/etc/ipa/epn.conf', epn_conf)
+         # check EPN on client (LDAP+GSSAPI)
+-        (stdout_text, unused) = self._check_epn_output(
++        (stdout_text, unused, _unused) = self._check_epn_output(
+             self.clients[0], dry_run=True
+         )
+         assert len(json.loads(stdout_text)) == 0
+         # check EPN on master (LDAPI)
+-        (stdout_text, unused) = self._check_epn_output(
++        (stdout_text, unused, _unused) = self._check_epn_output(
+             self.master, dry_run=True
+         )
+         assert len(json.loads(stdout_text)) == 0
+@@ -292,10 +301,10 @@ class TestEPN(IntegrationTest):
+                 ),
+             ],
+         )
+-        (stdout_text_client, unused) = self._check_epn_output(
++        (stdout_text_client, unused, _unused) = self._check_epn_output(
+             self.clients[0], dry_run=True
+         )
+-        (stdout_text_master, unused) = self._check_epn_output(
++        (stdout_text_master, unused, _unused) = self._check_epn_output(
+             self.master, dry_run=True
+         )
+         assert stdout_text_master == stdout_text_client
+@@ -331,10 +340,10 @@ class TestEPN(IntegrationTest):
+                 password=None,
+             )
+ 
+-        (stdout_text_client, unused) = self._check_epn_output(
++        (stdout_text_client, unused, _unused) = self._check_epn_output(
+             self.clients[0], dry_run=True
+         )
+-        (stdout_text_master, unused) = self._check_epn_output(
++        (stdout_text_master, unused, _unused) = self._check_epn_output(
+             self.master, dry_run=True
+         )
+         assert stdout_text_master == stdout_text_client
+@@ -344,22 +353,117 @@ class TestEPN(IntegrationTest):
+         expected_users = ["user1", "user3", "user7", "user14", "user28"]
+         assert sorted(user_lst) == sorted(expected_users)
+ 
+-    def test_EPN_nbdays(self):
++    def test_EPN_nbdays_0(self, cleanupmail):
+         """Test the to/from nbdays options (implies --dry-run)
+ 
+            We have a set of users installed with varying expiration
+            dates. Confirm that to/from nbdays finds them.
++
++           Make sure --dry-run does not accidentally send emails.
+         """
+ 
+-        # Compare the notify_ttls values
++        # Use the notify_ttls values with a 1-day sliding window
+         for i in self.notify_ttls:
+             user_list = []
+-            (stdout_text_client, unused) = self._check_epn_output(
+-                self.clients[0], from_nbdays=i, to_nbdays=i + 1, dry_run=True)
++            (stdout_text_client, unused, _unused) = self._check_epn_output(
++                self.clients[0], from_nbdays=i, to_nbdays=i + 1, dry_run=True
++            )
+             for user in json.loads(stdout_text_client):
+                 user_list.append(user["uid"])
+             assert len(user_list) == 1
+-            assert user_list[0] == "user%d" % i
++            userid = "user{id}".format(id=i)
++            assert user_list[0] == userid
++
++            # Check that the user list is expected for any given notify_ttls.
++            (stdout_text_client, unused, _unused) = self._check_epn_output(
++                self.clients[0], to_nbdays=i
++            )
++            user_list = [user["uid"] for user in json.loads(stdout_text_client)]
++            assert len(user_list) == 1
++            assert user_list[0] == "user{id}".format(id=i - 1)
++
++            # make sure no emails were sent
++            result = self.clients[0].run_command(['ls', '-lha', '/var/mail/'])
++            assert userid not in result.stdout_text
++
++    def test_EPN_nbdays_1(self, cleanupmail):
++        """Test that for a given range, we find the users in that range"""
++
++        # Use hardcoded date ranges for now
++        for date_range in [(0, 5), (7, 15), (1, 20)]:
++            expected_user_list = ["user{i}".format(i=i)
++                                  for i in range(date_range[0], date_range[1])]
++            (stdout_text_client, unused, _unused) = self._check_epn_output(
++                self.clients[0],
++                from_nbdays=date_range[0],
++                to_nbdays=date_range[1]
++            )
++            user_list = [user["uid"] for user in json.loads(stdout_text_client)]
++            for user in expected_user_list:
++                assert user in user_list
++            for user in user_list:
++                assert user in expected_user_list
++
++    # Test the to/from nbdays options behavior with illegal input
++
++    def test_EPN_nbdays_input_0(self):
++        """Make sure that --to-nbdays implies --dry-run ;
++           therefore check that the output is valid JSON and contains the
++           expected user.
++        """
++
++        (stdout_text_client, unused, _unused) = self._check_epn_output(
++            self.clients[0], to_nbdays=5, dry_run=False
++        )
++        assert len(json.loads(stdout_text_client)) == 1
++        assert json.loads(stdout_text_client)[0]["uid"] == "user4"
++
++    def test_EPN_nbdays_input_1(self):
++        """Make sure that --from-nbdays cannot be used without --to-nbdays"""
++
++        (unused, stderr_text_client, rc) = \
++            self._check_epn_output(
++            self.clients[0], from_nbdays=3,
++            raiseonerr=False, validatejson=False
++        )
++        assert "You cannot specify --from-nbdays without --to-nbdays" \
++            in stderr_text_client
++        assert rc > 0
++
++    @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True)
++    def test_EPN_nbdays_input_2(self):
++        """alpha input"""
++
++        (unused, stderr, rc) = self._check_epn_output(
++            self.clients[0], to_nbdays="abc",
++            raiseonerr=False, validatejson=False
++        )
++        assert "error: --to-nbdays must be an integer." in stderr
++        assert rc > 0
++
++    @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True)
++    def test_EPN_nbdays_input_3(self):
++        """from_nbdays > to_nbdays"""
++
++        (unused, stderr, rc) = self._check_epn_output(
++            self.clients[0], from_nbdays=9, to_nbdays=7,
++            raiseonerr=False, validatejson=False
++        )
++        assert "error: --from-nbdays must be smaller than --to-nbdays." in \
++            stderr
++        assert rc > 0
++
++    @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True)
++    def test_EPN_nbdays_input_4(self):
++        """decimal input"""
++
++        (unused, stderr, rc) = self._check_epn_output(
++            self.clients[0], to_nbdays=7.3,
++            raiseonerr=False, validatejson=False
++        )
++        logger.info(stderr)
++        assert rc > 0
++        assert "error: --to-nbdays must be an integer." in stderr
+ 
+     # From here the tests build on one another:
+     #  1) add auth
+-- 
+2.26.2
+
+From b4266023e04729db12de2f7e0de4da9e1d00db38 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= <fcami@redhat.com>
+Date: Fri, 7 Aug 2020 19:08:39 +0200
+Subject: [PATCH] ipatests: test_epn: update error messages
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Update error messages in the test.
+
+Fixes: https://pagure.io/freeipa/issue/8449
+Signed-off-by: François Cami <fcami@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+---
+ ipatests/test_integration/test_epn.py | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/ipatests/test_integration/test_epn.py b/ipatests/test_integration/test_epn.py
+index e03521193..af662140a 100644
+--- a/ipatests/test_integration/test_epn.py
++++ b/ipatests/test_integration/test_epn.py
+@@ -458,7 +458,7 @@ class TestEPN(IntegrationTest):
+             self.clients[0], to_nbdays="abc",
+             raiseonerr=False, validatejson=False
+         )
+-        assert "error: --to-nbdays must be an integer." in stderr
++        assert "error: --to-nbdays must be a positive integer." in stderr
+         assert rc > 0
+ 
+     @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True)
+@@ -483,7 +483,7 @@ class TestEPN(IntegrationTest):
+         )
+         logger.info(stderr)
+         assert rc > 0
+-        assert "error: --to-nbdays must be an integer." in stderr
++        assert "error: --to-nbdays must be a positive integer." in stderr
+ 
+     # From here the tests build on one another:
+     #  1) add auth
+-- 
+2.26.2
+
+From 2809084a44e3b174fa48a611e79f04358e1d6dca Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= <fcami@redhat.com>
+Date: Wed, 5 Aug 2020 09:05:31 +0200
+Subject: [PATCH] IPA-EPN: enhance input validation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Enhance input validation:
+* make sure --from-nbdays and --to-nbdays are integer
+* make sure --from-nbdays < --to-nbdays
+
+Fixes: https://pagure.io/freeipa/issue/8444
+Signed-off-by: François Cami <fcami@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+---
+ ipaclient/install/ipa_epn.py          | 28 +++++++++++++++++++++++++--
+ ipatests/test_integration/test_epn.py |  3 ---
+ 2 files changed, 26 insertions(+), 5 deletions(-)
+
+diff --git a/ipaclient/install/ipa_epn.py b/ipaclient/install/ipa_epn.py
+index 82d7b3f57..88c926e88 100644
+--- a/ipaclient/install/ipa_epn.py
++++ b/ipaclient/install/ipa_epn.py
+@@ -246,9 +246,33 @@ class EPN(admintool.AdminTool):
+ 
+     def validate_options(self):
+         super(EPN, self).validate_options(needs_root=True)
+-        if self.options.to_nbdays:
++        if self.options.to_nbdays is not None:
++            try:
++                if int(self.options.to_nbdays) < 0:
++                    raise RuntimeError('Input is negative.')
++            except Exception as e:
++                self.option_parser.error(
++                    "--to-nbdays must be a positive integer. "
++                    "{error}".format(error=e)
++                )
+             self.options.dry_run = True
+-        if self.options.from_nbdays and not self.options.to_nbdays:
++        if self.options.from_nbdays is not None:
++            try:
++                if int(self.options.from_nbdays) < 0:
++                    raise RuntimeError('Input is negative.')
++            except Exception as e:
++                self.option_parser.error(
++                    "--from-nbdays must be a positive integer. "
++                    "{error}".format(error=e)
++                )
++        if self.options.from_nbdays is not None and \
++                self.options.to_nbdays is not None:
++            if int(self.options.from_nbdays) >= int(self.options.to_nbdays):
++                self.option_parser.error(
++                    "--from-nbdays must be smaller than --to-nbdays."
++                )
++        if self.options.from_nbdays is not None and \
++                self.options.to_nbdays is None:
+             self.option_parser.error(
+                 "You cannot specify --from-nbdays without --to-nbdays"
+             )
+diff --git a/ipatests/test_integration/test_epn.py b/ipatests/test_integration/test_epn.py
+index af662140a..fc26888cb 100644
+--- a/ipatests/test_integration/test_epn.py
++++ b/ipatests/test_integration/test_epn.py
+@@ -450,7 +450,6 @@ class TestEPN(IntegrationTest):
+             in stderr_text_client
+         assert rc > 0
+ 
+-    @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True)
+     def test_EPN_nbdays_input_2(self):
+         """alpha input"""
+ 
+@@ -461,7 +460,6 @@ class TestEPN(IntegrationTest):
+         assert "error: --to-nbdays must be a positive integer." in stderr
+         assert rc > 0
+ 
+-    @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True)
+     def test_EPN_nbdays_input_3(self):
+         """from_nbdays > to_nbdays"""
+ 
+@@ -473,7 +471,6 @@ class TestEPN(IntegrationTest):
+             stderr
+         assert rc > 0
+ 
+-    @pytest.mark.xfail(reason='freeipa ticket 8444', strict=True)
+     def test_EPN_nbdays_input_4(self):
+         """decimal input"""
+ 
+-- 
+2.26.2
+
diff --git a/SOURCES/0015-IPA-EPN-Fix-SMTP-connection-error-handling_rhbz#1863079.patch b/SOURCES/0015-IPA-EPN-Fix-SMTP-connection-error-handling_rhbz#1863079.patch
new file mode 100644
index 0000000..3871c56
--- /dev/null
+++ b/SOURCES/0015-IPA-EPN-Fix-SMTP-connection-error-handling_rhbz#1863079.patch
@@ -0,0 +1,141 @@
+From 3cf7fb1014ae40fd5a5278f27577a8196a4af051 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= <fcami@redhat.com>
+Date: Fri, 7 Aug 2020 07:51:53 +0200
+Subject: [PATCH] ipatests: test_epn: add test_EPN_connection_refused
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add a test for EPN behavior when the configured SMTP does not
+accept connections.
+
+Fixes: https://pagure.io/freeipa/issue/8445
+Signed-off-by: François Cami <fcami@redhat.com>
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+---
+ ipatests/test_integration/test_epn.py | 27 ++++++++++++++++++++++++---
+ 1 file changed, 24 insertions(+), 3 deletions(-)
+
+diff --git a/ipatests/test_integration/test_epn.py b/ipatests/test_integration/test_epn.py
+index c5c73835a..1a25d3710 100644
+--- a/ipatests/test_integration/test_epn.py
++++ b/ipatests/test_integration/test_epn.py
+@@ -182,14 +182,20 @@ class TestEPN(IntegrationTest):
+         self,
+         host,
+         dry_run=False,
++        mailtest=False,
+         from_nbdays=None,
+         to_nbdays=None,
+         raiseonerr=True,
+         validatejson=True
+     ):
+-        result = tasks.ipa_epn(host, raiseonerr=raiseonerr, dry_run=dry_run,
+-                               from_nbdays=from_nbdays,
+-                               to_nbdays=to_nbdays)
++        result = tasks.ipa_epn(
++            host,
++            from_nbdays=from_nbdays,
++            to_nbdays=to_nbdays,
++            mailtest=mailtest,
++            dry_run=dry_run,
++            raiseonerr=raiseonerr
++        )
+         if validatejson:
+             json.dumps(json.loads(result.stdout_text), ensure_ascii=False)
+         return (result.stdout_text, result.stderr_text, result.returncode)
+@@ -243,6 +249,21 @@ class TestEPN(IntegrationTest):
+         ck = "192481b52fb591112afd7b55b12a44c6618fdbc7e05a3b1866fd67ec579c51df"
+         assert cmd2.stdout_text.find(ck) == 0
+ 
++    @pytest.mark.xfail(reason='freeipa ticket 8445', strict=True)
++    def test_EPN_connection_refused(self):
++        """Test EPN behavior when the configured SMTP is down
++        """
++
++        self.master.run_command(["systemctl", "stop", "postfix"])
++        (unused, stderr_text, rc) = self._check_epn_output(
++            self.master, mailtest=True,
++            raiseonerr=False, validatejson=False
++        )
++        self.master.run_command(["systemctl", "start", "postfix"])
++        assert "IPA-EPN: Could not connect to the configured SMTP server" in \
++            stderr_text
++        assert rc > 0
++
+     def test_EPN_smoketest_1(self):
+         """No users except admin. Check --dry-run output.
+            With the default configuration, the result should be an empty list.
+-- 
+2.26.2
+
+From 53f330b053740b169d211aa16b3b36fb61157bbd Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Fran=C3=A7ois=20Cami?= <fcami@redhat.com>
+Date: Fri, 7 Aug 2020 06:19:31 +0200
+Subject: [PATCH] IPA-EPN: Fix SMTP connection error handling
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Enhance error message when SMTP is down.
+
+Fixes: https://pagure.io/freeipa/issue/8445
+Signed-off-by: François Cami <fcami@redhat.com>
+Reviewed-By: Florence Blanc-Renaud <frenaud@redhat.com>
+Reviewed-By: Rob Crittenden <rcritten@redhat.com>
+---
+ ipaclient/install/ipa_epn.py          | 17 ++++++++++-------
+ ipatests/test_integration/test_epn.py |  1 -
+ 2 files changed, 10 insertions(+), 8 deletions(-)
+
+diff --git a/ipaclient/install/ipa_epn.py b/ipaclient/install/ipa_epn.py
+index 0d1ae2add..82d7b3f57 100644
+--- a/ipaclient/install/ipa_epn.py
++++ b/ipaclient/install/ipa_epn.py
+@@ -38,6 +38,7 @@ from email.mime.multipart import MIMEMultipart
+ from email.mime.text import MIMEText
+ from email.header import Header
+ from email.utils import make_msgid
++from socket import error as socketerror
+ 
+ from ipaplatform.paths import paths
+ from ipalib import api, errors
+@@ -640,13 +641,15 @@ class MTAClient:
+                     port=self._smtp_port,
+                     timeout=self._smtp_timeout,
+                 )
+-        except smtplib.SMTPException as e:
+-            logger.error(
+-                "IPA-EPN: Unable to connect to %s:%s: %s",
+-                self._smtp_hostname,
+-                self._smtp_port,
+-                e,
+-            )
++        except (socketerror, smtplib.SMTPException) as e:
++            msg = \
++                "IPA-EPN: Could not connect to the configured SMTP server: " \
++                "{host}:{port}: {error}".format(
++                    host=self._smtp_hostname,
++                    port=self._smtp_port,
++                    error=e
++                )
++            raise admintool.ScriptError(msg)
+ 
+         try:
+             self._conn.ehlo()
+diff --git a/ipatests/test_integration/test_epn.py b/ipatests/test_integration/test_epn.py
+index 1a25d3710..e03521193 100644
+--- a/ipatests/test_integration/test_epn.py
++++ b/ipatests/test_integration/test_epn.py
+@@ -249,7 +249,6 @@ class TestEPN(IntegrationTest):
+         ck = "192481b52fb591112afd7b55b12a44c6618fdbc7e05a3b1866fd67ec579c51df"
+         assert cmd2.stdout_text.find(ck) == 0
+ 
+-    @pytest.mark.xfail(reason='freeipa ticket 8445', strict=True)
+     def test_EPN_connection_refused(self):
+         """Test EPN behavior when the configured SMTP is down
+         """
+-- 
+2.26.2
+
diff --git a/SOURCES/0016-Set-mode-of-etc-ipa-ca.crt-to-0644-in-CA-less-instal_rhbz#1870202.patch b/SOURCES/0016-Set-mode-of-etc-ipa-ca.crt-to-0644-in-CA-less-instal_rhbz#1870202.patch
new file mode 100644
index 0000000..8f8c1df
--- /dev/null
+++ b/SOURCES/0016-Set-mode-of-etc-ipa-ca.crt-to-0644-in-CA-less-instal_rhbz#1870202.patch
@@ -0,0 +1,110 @@
+From 4a97145c3a76a4d9ebf52b3905410a0bd7bec856 Mon Sep 17 00:00:00 2001
+From: Rob Crittenden <rcritten@redhat.com>
+Date: Tue, 4 Aug 2020 15:09:56 -0400
+Subject: [PATCH] Set mode of /etc/ipa/ca.crt to 0644 in CA-less installations
+
+It was previously being set to 0444 which triggered a warning
+in freeipa-healthcheck.
+
+Even root needs DAC_OVERRIDE capability to write to a 0o444 file
+which may not be available in some environments.
+
+https://pagure.io/freeipa/issue/8441
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ ipaserver/install/certs.py          | 2 +-
+ ipaserver/install/server/install.py | 5 ++---
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
+index 22ee79bd1..51d9f9221 100644
+--- a/ipaserver/install/certs.py
++++ b/ipaserver/install/certs.py
+@@ -329,7 +329,7 @@ class CertDB:
+         ipautil.backup_file(cacert_fname)
+         root_nicknames = self.find_root_cert(nickname)[:-1]
+         with open(cacert_fname, "w") as f:
+-            os.fchmod(f.fileno(), stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
++            os.fchmod(f.fileno(), 0o644)
+             for root in root_nicknames:
+                 result = self.run_certutil(["-L", "-n", root, "-a"],
+                                            capture_output=True)
+diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
+index b53c58e2a..6a593602f 100644
+--- a/ipaserver/install/server/install.py
++++ b/ipaserver/install/server/install.py
+@@ -891,9 +891,8 @@ def install(installer):
+ 
+         ca.install_step_0(False, None, options, custodia=custodia)
+     else:
+-        # Put the CA cert where other instances expect it
+-        x509.write_certificate(http_ca_cert, paths.IPA_CA_CRT)
+-        os.chmod(paths.IPA_CA_CRT, 0o444)
++        # /etc/ipa/ca.crt is created as a side-effect of
++        # dsinstance::enable_ssl() via export_ca_cert()
+ 
+         if not options.no_pkinit:
+             x509.write_certificate(http_ca_cert, paths.KDC_CA_BUNDLE_PEM)
+-- 
+2.26.2
+
+From da2079ce2cc841aec56da872131112eb24326f81 Mon Sep 17 00:00:00 2001
+From: Rob Crittenden <rcritten@redhat.com>
+Date: Tue, 4 Aug 2020 15:12:20 -0400
+Subject: [PATCH] ipatests: Check permissions of /etc/ipa/ca.crt new
+ installations
+
+It should be 0644 root:root for both CA-ful and CA-less installs.
+
+https://pagure.io/freeipa/issue/8441
+
+Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
+---
+ ipatests/test_integration/test_caless.py       |  8 ++++++++
+ ipatests/test_integration/test_installation.py | 10 ++++++++++
+ 2 files changed, 18 insertions(+)
+
+diff --git a/ipatests/test_integration/test_caless.py b/ipatests/test_integration/test_caless.py
+index 1ea7d9896..16dfbb320 100644
+--- a/ipatests/test_integration/test_caless.py
++++ b/ipatests/test_integration/test_caless.py
+@@ -394,6 +394,14 @@ class CALessBase(IntegrationTest):
+                          host, cert_from_ldap.public_bytes(x509.Encoding.PEM))
+             assert cert_from_ldap == expected_cacrt
+ 
++            result = host.run_command(
++                ["/usr/bin/stat", "-c", "%U:%G:%a", paths.IPA_CA_CRT]
++            )
++            (owner, group, mode) = result.stdout_text.strip().split(':')
++            assert owner == "root"
++            assert group == "root"
++            assert mode == "644"
++
+             # Verify certmonger was not started
+             result = host.run_command(['getcert', 'list'], raiseonerr=False)
+             assert result.returncode == 0
+diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py
+index 100a5a766..fb1990083 100644
+--- a/ipatests/test_integration/test_installation.py
++++ b/ipatests/test_integration/test_installation.py
+@@ -346,6 +346,16 @@ class TestInstallCA(IntegrationTest):
+         status = tasks.wait_for_request(self.master, request_id[0], 300)
+         assert status == "MONITORING"
+ 
++    def test_ipa_ca_crt_permissions(self):
++        """Verify that /etc/ipa/ca.cert is mode 0644 root:root"""
++        result = self.master.run_command(
++            ["/usr/bin/stat", "-c", "%U:%G:%a", paths.IPA_CA_CRT]
++        )
++        out = str(result.stdout_text.strip())
++        (owner, group, mode) = out.split(':')
++        assert mode == "644"
++        assert owner == "root"
++        assert group == "root"
+ 
+ class TestInstallWithCA_KRA1(InstallTestBase1):
+ 
+-- 
+2.26.2
+
diff --git a/SPECS/ipa.spec b/SPECS/ipa.spec
index 137df90..ef6b018 100644
--- a/SPECS/ipa.spec
+++ b/SPECS/ipa.spec
@@ -53,7 +53,7 @@
 %endif
 
 # Include SELinux subpackage
-%if 0%{?fedora} >= 30 || 0%{?rhel} > 8
+%if 0%{?fedora} >= 30 || 0%{?rhel} >= 8
     %global with_selinux 1
     %global selinuxtype targeted
     %global modulename ipa
@@ -67,11 +67,11 @@
 # 0.7.16: https://github.com/drkjam/netaddr/issues/71
 %global python_netaddr_version 0.7.19
 # Require 4.7.0 which brings Python 3 bindings
-%global samba_version 4.12.3-0
+%global samba_version 4.12.3-12
 %global slapi_nis_version 0.56.4
 # Require 3.14.3-24 - Allow ipa_ods_exporter_t domain to read krb5_keytab files
 # SELinux context for /etc/named directory, RHBZ#1759495
-%global selinux_policy_version 3.14.3-43
+%global selinux_policy_version 3.14.3-52
 %global slapi_nis_version 0.56.1-4
 %global python_ldap_version 3.1.0-1
 # python3-lib389
@@ -112,11 +112,9 @@
 # Fedora
 %endif
 
-# Require Dogtag PKI 10.6.8-3 (10.6.7 was never pushed to stable)
-# 10.6.7 fixes UpdateNumberRange clone installation issue
-# https://pagure.io/freeipa/issue/7654 and empty token issue
-# and https://pagure.io/dogtagpki/issue/3073
-%global pki_version 10.8.0
+# PKIConnection has been modified to always validate certs.
+# https://pagure.io/freeipa/issue/8379
+%global pki_version 10.9.0-0.4
 
 # https://pagure.io/certmonger/issue/90
 %global certmonger_version 0.79.7-3
@@ -151,7 +149,7 @@
 
 Name:           %{package_name}
 Version:        %{IPA_VERSION}
-Release:        4%{?dist}
+Release:        10%{?dist}
 Summary:        The Identity, Policy and Audit system
 
 License:        GPLv3+
@@ -170,6 +168,18 @@ Patch0001:      0001-WebUI-Fix-IPA-Error-3007-RequirmentError-while-addin_rhbz#1
 Patch0002:      0002-EPN-does-not-ship-its-default-configuration_rhbz#1847999.patch
 Patch0003:      0003-Use-256-bit-AJP-secret_rhbz#1849914.patch
 Patch0004:      0004-baseuser-fix-ipanthomedirectorydrive-option-name_rhbz#1851411.patch
+Patch0005:      0005-selinux-don-t-audit-rules-deny-fetching-trust-topology_rhbz#1845596.patch
+Patch0006:      0006-fix-iPAddress-cert-issuance-for-1-host-service_rhbz#1846352.patch
+Patch0007:      0007-Specify-cert_paths-when-calling-PKIConnection_rhbz#1849155.patch
+Patch0008:      0008-Add-missing-SELinux-rule-for-ipa-custodia.sock_rhbz#1857157.patch
+Patch0009:      0009-ipa-client-install-use-the-authselect-backup-during_rhbz#1810179.patch
+Patch0010:      0010-Replace-SSLCertVerificationError-with-CertificateErr_rhbz#1858318.patch
+Patch0011:      0011-Fix-AVC-denial-during-ipa-adtrust-install---add-agents_rhbz#1859213.patch
+Patch0012:      0012-CAless-installation-set-the-perms-on-KDC-cert-file_rhbz#1863616.patch
+Patch0013:      0013-IPA-EPN-Use-a-helper-to-retrieve-LDAP-attributes-fro_rhbz#1866938.patch
+Patch0014:      0014-IPA-EPN-enhance-input-validation_rhbz#1866291.patch
+Patch0015:      0015-IPA-EPN-Fix-SMTP-connection-error-handling_rhbz#1863079.patch
+Patch0016:      0016-Set-mode-of-etc-ipa-ca.crt-to-0644-in-CA-less-instal_rhbz#1870202.patch
 Patch1001:      1001-Change-branding-to-IPA-and-Identity-Management.patch
 Patch1002:      1002-4.8.0-Remove-csrgen.patch
 Patch1003:      1003-Revert-WebUI-use-python3-rjsmin-to-minify-JavaScript.patch
@@ -497,7 +507,7 @@ Requires: %{name}-common = %{version}-%{release}
 Requires: samba >= %{samba_version}
 Requires: samba-winbind
 Requires: libsss_idmap
-Obsoletes: ipa-idoverride-memberof-plugin
+Obsoletes: ipa-idoverride-memberof-plugin <= 0.1
 
 Requires(post): python3
 Requires: python3-samba
@@ -565,6 +575,9 @@ Obsoletes: %{alt_name}-admintools < 4.4.1
 Obsoletes: %{name}-admintools < 4.4.1
 Provides: %{name}-admintools = %{version}-%{release}
 
+# Conflict with crypto-policies < 20200629-1 to get AD-SUPPORT policy module
+Conflicts: crypto-policies < 20200629-1
+
 %description client
 IPA is an integrated solution to provide centrally managed Identity (users,
 hosts, services), Authentication (SSO, 2FA), and Authorization
@@ -1517,6 +1530,55 @@ fi
 
 
 %changelog
+* Wed Aug 19 2020 Thomas Woerner <twoerner@redhat.com> - 4.8.7-10
+- Set mode of /etc/ipa/ca.crt to 0644 in CA-less installations
+  Resolves: RHBZ#1870202
+
+* Mon Aug 17 2020 Thomas Woerner <twoerner@redhat.com> - 4.8.7-9
+- CAless installation: set the perms on KDC cert file
+  Resolves: RHBZ#1863616
+- EPN: handle empty attributes
+  Resolves: RHBZ#1866938
+- IPA-EPN: enhance input validation
+  Resolves: RHBZ#1866291
+- EPN: enhance input validation
+  Resolves: RHBZ#1863079
+- Require new samba build 4.12.3-52
+  Related: RHBZ#1868558
+- Require new selinux-policy build 3.14.3-52
+  Related: RHBZ#1869311
+
+* Fri Jul 31 2020 Thomas Woerner <twoerner@redhat.com> - 4.8.7-8
+- [WebUI] IPA Error 3007: RequirmentError" while adding members in
+  "User ID overrides" tab (updated)
+  Resolves: RHBZ#1757045
+- ipa-client-install: use the authselect backup during uninstall
+  Resolves: RHBZ#1810179
+- Replace SSLCertVerificationError with CertificateError for py36
+  Resolves: RHBZ#1858318
+- Fix AVC denial during ipa-adtrust-install --add-agents
+  Resolves: RHBZ#1859213
+
+* Wed Jul 15 2020 Thomas Woerner <twoerner@redhat.com> - 4.8.7-7
+- replica install failing with avc denial for custodia component
+  Resolves: RHBZ#1857157
+
+* Tue Jul 14 2020 Thomas Woerner <twoerner@redhat.com> - 4.8.7-6
+- selinux don't audit rules deny fetching trust topology
+  Resolves: RHBZ#1845596
+- fix iPAddress cert issuance for >1 host/service
+  Resolves: RHBZ#1846352
+- Specify cert_paths when calling PKIConnection
+  Resolves: RHBZ#1849155
+- Update crypto policy to allow AD-SUPPORT when installing IPA
+  Resolves: RHBZ#1851139
+- Add version to ipa-idoverride-memberof obsoletes
+  Related: RHBZ#1846434
+
+* Thu Jul 02 2020 Thomas Woerner <twoerner@redhat.com> - 4.8.7-5
+- Add missing ipa-selinux package
+  Resolves: RHBZ#1853263
+
 * Mon Jun 29 2020 Thomas Woerner <twoerner@redhat.com> - 4.8.7-4
 - Remove client-epn left over files for ONLY_CLIENT
   Related: RHBZ#1847999