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

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