Blame SOURCES/0006-fix-iPAddress-cert-issuance-for-1-host-service_rhbz#1846352.patch

2ff659
From 128500198d3782a76616cf1d971d5aeb17e8c1da Mon Sep 17 00:00:00 2001
2ff659
From: Fraser Tweedale <ftweedal@redhat.com>
2ff659
Date: Thu, 11 Jun 2020 22:42:38 +1000
2ff659
Subject: [PATCH] fix iPAddress cert issuance for >1 host/service
2ff659
2ff659
The 'cert_request' command accumulates DNS names from the CSR,
2ff659
before checking that all IP addresses in the CSR are reachable from
2ff659
those DNS names.  Before adding a DNS name to the set, we check that
2ff659
that it corresponds to the FQDN of a known host/service principal
2ff659
(including principal aliases).  When a DNS name maps to a
2ff659
"alternative" principal (i.e.  not the one given via the 'principal'
2ff659
argument), this check was not being performed correctly.
2ff659
Specifically, we were looking for the 'krbprincipalname' field on
2ff659
the RPC response object directly, instead of its 'result' field.
2ff659
2ff659
To resolve the issue, dereference the RPC response to its 'result'
2ff659
field before invoking the '_dns_name_matches_principal' subroutine.
2ff659
2ff659
Fixes: https://pagure.io/freeipa/issue/8368
2ff659
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
2ff659
---
2ff659
 ipaserver/plugins/cert.py                     |  6 +-
2ff659
 .../test_cert_request_ip_address.py           | 62 +++++++++++++++++--
2ff659
 2 files changed, 61 insertions(+), 7 deletions(-)
2ff659
2ff659
diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py
2ff659
index d353bc3ea..fe7ea34f5 100644
2ff659
--- a/ipaserver/plugins/cert.py
2ff659
+++ b/ipaserver/plugins/cert.py
2ff659
@@ -827,13 +827,13 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
2ff659
                 try:
2ff659
                     if principal_type == HOST:
2ff659
                         alt_principal_obj = api.Command['host_show'](
2ff659
-                            name, all=True)
2ff659
+                            name, all=True)['result']
2ff659
                     elif principal_type == KRBTGT:
2ff659
                         alt_principal = kerberos.Principal(
2ff659
                             (u'host', name), principal.realm)
2ff659
                     elif principal_type == SERVICE:
2ff659
                         alt_principal_obj = api.Command['service_show'](
2ff659
-                            alt_principal, all=True)
2ff659
+                            alt_principal, all=True)['result']
2ff659
                 except errors.NotFound:
2ff659
                     # We don't want to issue any certificates referencing
2ff659
                     # machines we don't know about. Nothing is stored in this
2ff659
@@ -866,7 +866,7 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
2ff659
                         pass
2ff659
 
2ff659
                     # Now check write access and caacl
2ff659
-                    altdn = alt_principal_obj['result']['dn']
2ff659
+                    altdn = alt_principal_obj['dn']
2ff659
                     if not ldap.can_write(altdn, "usercertificate"):
2ff659
                         raise errors.ACIError(info=_(
2ff659
                             "Insufficient privilege to create a certificate "
2ff659
diff --git a/ipatests/test_xmlrpc/test_cert_request_ip_address.py b/ipatests/test_xmlrpc/test_cert_request_ip_address.py
2ff659
index bf4de05bf..c0475d30d 100644
2ff659
--- a/ipatests/test_xmlrpc/test_cert_request_ip_address.py
2ff659
+++ b/ipatests/test_xmlrpc/test_cert_request_ip_address.py
2ff659
@@ -28,10 +28,16 @@ from ipatests.test_xmlrpc.tracker.host_plugin import HostTracker
2ff659
 from ipatests.test_xmlrpc.tracker.user_plugin import UserTracker
2ff659
 from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
2ff659
 
2ff659
-host_fqdn = f'iptest.{api.env.domain}'
2ff659
+host_shortname = 'iptest'
2ff659
+host_fqdn = f'{host_shortname}.{api.env.domain}'
2ff659
 host_princ = f'host/{host_fqdn}'
2ff659
 host_ptr = f'{host_fqdn}.'
2ff659
 
2ff659
+host2_shortname = 'iptest2'
2ff659
+host2_fqdn = f'{host2_shortname}.{api.env.domain}'
2ff659
+host2_princ = f'host/{host2_fqdn}'
2ff659
+host2_ptr = f'{host2_fqdn}.'
2ff659
+
2ff659
 other_fqdn = f'other.{api.env.domain}'
2ff659
 other_ptr = f'{other_fqdn}.'
2ff659
 
2ff659
@@ -39,6 +45,10 @@ ipv4_address = '169.254.0.42'
2ff659
 ipv4_revzone_s = '0.254.169.in-addr.arpa.'
2ff659
 ipv4_revrec_s = '42'
2ff659
 
2ff659
+host2_ipv4_address = '169.254.0.43'
2ff659
+host2_ipv4_revzone_s = '0.254.169.in-addr.arpa.'
2ff659
+host2_ipv4_revrec_s = '43'
2ff659
+
2ff659
 ipv6_address = 'fe80::8f18:bdab:4299:95fa'
2ff659
 ipv6_revzone_s = '0.0.0.0.0.0.0.0.0.0.0.0.0.8.e.f.ip6.arpa.'
2ff659
 ipv6_revrec_s = 'a.f.5.9.9.9.2.4.b.a.d.b.8.1.f.8'
2ff659
@@ -46,7 +56,13 @@ ipv6_revrec_s = 'a.f.5.9.9.9.2.4.b.a.d.b.8.1.f.8'
2ff659
 
2ff659
 @pytest.fixture(scope='class')
2ff659
 def host(request, xmlrpc_setup):
2ff659
-    tr = HostTracker('iptest')
2ff659
+    tr = HostTracker(host_shortname)
2ff659
+    return tr.make_fixture(request)
2ff659
+
2ff659
+
2ff659
+@pytest.fixture(scope='class')
2ff659
+def host2(request, xmlrpc_setup):
2ff659
+    tr = HostTracker(host2_shortname)
2ff659
     return tr.make_fixture(request)
2ff659
 
2ff659
 
2ff659
@@ -88,6 +104,12 @@ def ipv6_revzone(host):
2ff659
     yield from _zone_setup(host, ipv6_revzone_s)
2ff659
 
2ff659
 
2ff659
+@pytest.fixture(scope='class')
2ff659
+def host2_ipv4_ptr(host2, ipv4_revzone):
2ff659
+    yield from _record_setup(
2ff659
+        host2, ipv4_revzone, host2_ipv4_revrec_s, ptrrecord=host2_ptr)
2ff659
+
2ff659
+
2ff659
 @pytest.fixture(scope='class')
2ff659
 def ipv4_ptr(host, ipv4_revzone):
2ff659
     yield from _record_setup(
2ff659
@@ -100,16 +122,22 @@ def ipv6_ptr(host, ipv6_revzone):
2ff659
         host, ipv6_revzone, ipv6_revrec_s, ptrrecord=host_ptr)
2ff659
 
2ff659
 
2ff659
+@pytest.fixture(scope='class')
2ff659
+def host2_ipv4_a(host2):
2ff659
+    yield from _record_setup(
2ff659
+        host2, api.env.domain, host2_shortname, arecord=host2_ipv4_address)
2ff659
+
2ff659
+
2ff659
 @pytest.fixture(scope='class')
2ff659
 def ipv4_a(host):
2ff659
     yield from _record_setup(
2ff659
-        host, api.env.domain, 'iptest', arecord=ipv4_address)
2ff659
+        host, api.env.domain, host_shortname, arecord=ipv4_address)
2ff659
 
2ff659
 
2ff659
 @pytest.fixture(scope='class')
2ff659
 def ipv6_aaaa(host):
2ff659
     yield from _record_setup(
2ff659
-        host, api.env.domain, 'iptest', aaaarecord=ipv6_address)
2ff659
+        host, api.env.domain, host_shortname, aaaarecord=ipv6_address)
2ff659
 
2ff659
 
2ff659
 @pytest.fixture(scope='class')
2ff659
@@ -210,6 +238,12 @@ csr_cname2 = csr([
2ff659
     x509.DNSName(f'cname2.{api.env.domain}'),
2ff659
     x509.IPAddress(ipaddress.ip_address(ipv4_address)),
2ff659
 ])
2ff659
+csr_two_dnsname_two_ip = csr([
2ff659
+    x509.DNSName(host_fqdn),
2ff659
+    x509.IPAddress(ipaddress.ip_address(ipv4_address)),
2ff659
+    x509.DNSName(host2_fqdn),
2ff659
+    x509.IPAddress(ipaddress.ip_address(host2_ipv4_address)),
2ff659
+])
2ff659
 
2ff659
 
2ff659
 @pytest.fixture
2ff659
@@ -449,3 +483,23 @@ class TestIPAddressCNAME(XMLRPC_test):
2ff659
     def test_two_levels(self, host, csr_cname2):
2ff659
         with pytest.raises(errors.ValidationError, match=PAT_FWD):
2ff659
             host.run_command('cert_request', csr_cname2, principal=host_princ)
2ff659
+
2ff659
+
2ff659
+@pytest.mark.tier1
2ff659
+class TestTwoHostsTwoIPAddresses(XMLRPC_test):
2ff659
+    """
2ff659
+    Test certificate issuance with CSR containing two hosts
2ff659
+    and two IP addresses (one for each host).
2ff659
+
2ff659
+    """
2ff659
+    def test_host_exists(
2ff659
+        self, host, host2, ipv4_a, ipv4_ptr, host2_ipv4_a, host2_ipv4_ptr,
2ff659
+    ):
2ff659
+        # for convenience, this test also establishes the DNS
2ff659
+        # record fixtures, which have class scope
2ff659
+        host.ensure_exists()
2ff659
+        host2.ensure_exists()
2ff659
+
2ff659
+    def test_issuance(self, host, csr_two_dnsname_two_ip):
2ff659
+        host.run_command(
2ff659
+            'cert_request', csr_two_dnsname_two_ip, principal=host_princ)
2ff659
-- 
2ff659
2.26.2
2ff659