URL: https://github.com/freeipa/freeipa/pull/1111
Author: stlaz
 Title: #1111: ipalib.x509 autumn cleanup
Action: opened

PR body:
"""
This is a cleanup of the x509 module which removes an ugly hack that prevents a 
circular dependency and the `strip_header()` function which is properly 
replaced by the `load_unknown_x509_certificate()` function where needed.
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/1111/head:pr1111
git checkout pr1111
From 087bda72c1f5a54aa4571ed930089ac4dff1e2a3 Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka <slazn...@redhat.com>
Date: Mon, 25 Sep 2017 09:54:53 +0200
Subject: [PATCH 1/2] x509: remove the strip_header() function

We don't need the strip_header() function, to load an unknown
x509 certificate, load_unknown_x509_certificate() should be used.
---
 ipaclient/plugins/cert.py                |  3 ++-
 ipaclient/plugins/certmap.py             |  2 +-
 ipalib/x509.py                           | 15 ---------------
 ipatests/test_integration/test_caless.py | 13 ++++++-------
 ipatests/test_xmlrpc/testcert.py         | 19 +++++++++++++++++--
 5 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/ipaclient/plugins/cert.py b/ipaclient/plugins/cert.py
index d5daaf3a15..19b8bb9317 100644
--- a/ipaclient/plugins/cert.py
+++ b/ipaclient/plugins/cert.py
@@ -209,6 +209,7 @@ def forward(self, *args, **options):
                 raise errors.MutuallyExclusiveError(
                     reason=_("cannot specify both raw certificate and file"))
             if 'certificate' not in options and 'file' in options:
-                options['certificate'] = x509.strip_header(options.pop('file'))
+                options['certificate'] = x509.load_unknown_x509_certificate(
+                                            options.pop('file'))
 
         return super(cert_find, self).forward(*args, **options)
diff --git a/ipaclient/plugins/certmap.py b/ipaclient/plugins/certmap.py
index 50a594f396..981ba292f6 100644
--- a/ipaclient/plugins/certmap.py
+++ b/ipaclient/plugins/certmap.py
@@ -40,7 +40,7 @@ def forward(self, *args, **options):
                 raise errors.MutuallyExclusiveError(
                     reason=_("cannot specify both raw certificate and file"))
             if args:
-                args = [x509.strip_header(args[0])]
+                args = [x509.load_unknown_x509_certificate(args[0])]
             elif 'certificate' in options:
                 args = [options.pop('certificate')]
             else:
diff --git a/ipalib/x509.py b/ipalib/x509.py
index 0b3a423ce3..9e2b365ea2 100644
--- a/ipalib/x509.py
+++ b/ipalib/x509.py
@@ -88,21 +88,6 @@ def subject_base():
 
     return _subject_base
 
-def strip_header(pem):
-    """
-    Remove the header and footer from a certificate.
-    """
-    regexp = (
-        u"^-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----"
-    )
-    if isinstance(pem, bytes):
-        regexp = regexp.encode('ascii')
-    s = re.search(regexp, pem, re.MULTILINE | re.DOTALL)
-    if s is not None:
-        return s.group(1)
-    else:
-        return pem
-
 
 @crypto_utils.register_interface(crypto_x509.Certificate)
 class IPACertificate(object):
diff --git a/ipatests/test_integration/test_caless.py b/ipatests/test_integration/test_caless.py
index 994396dd7b..4037a5e514 100644
--- a/ipatests/test_integration/test_caless.py
+++ b/ipatests/test_integration/test_caless.py
@@ -359,10 +359,9 @@ def verify_installation(self):
             expected_cacrt = f.read()
         logger.debug('Expected /etc/ipa/ca.crt contents:\n%s',
                      expected_cacrt)
-        expected_binary_cacrt = base64.b64decode(x509.strip_header(
-            expected_cacrt))
+        expected_cacrt = x509.load_unknown_x509_certificate(expected_cacrt)
         logger.debug('Expected binary CA cert:\n%r',
-                     expected_binary_cacrt)
+                     expected_cacrt)
         for host in [self.master] + self.replicas:
             # Check the LDAP entry
             ldap = host.ldap_connect()
@@ -372,7 +371,7 @@ def verify_installation(self):
             cert_from_ldap = entry.single_value['cACertificate']
             logger.debug('CA cert from LDAP on %s:\n%r',
                          host, cert_from_ldap)
-            assert cert_from_ldap == expected_binary_cacrt
+            assert cert_from_ldap == expected_cacrt
 
             # Verify certmonger was not started
             result = host.run_command(['getcert', 'list'], raiseonerr=False)
@@ -383,10 +382,10 @@ def verify_installation(self):
             remote_cacrt = host.get_file_contents(paths.IPA_CA_CRT)
             logger.debug('%s:/etc/ipa/ca.crt contents:\n%s',
                          host, remote_cacrt)
-            binary_cacrt = base64.b64decode(x509.strip_header(remote_cacrt))
+            cacrt = x509.load_unknown_x509_certificate(remote_cacrt)
             logger.debug('%s: Decoded /etc/ipa/ca.crt:\n%r',
-                         host, binary_cacrt)
-            assert expected_binary_cacrt == binary_cacrt
+                         host, cacrt)
+            assert expected_cacrt == cacrt
 
 
 class TestServerInstall(CALessBase):
diff --git a/ipatests/test_xmlrpc/testcert.py b/ipatests/test_xmlrpc/testcert.py
index 151919180b..6ea5a50eef 100644
--- a/ipatests/test_xmlrpc/testcert.py
+++ b/ipatests/test_xmlrpc/testcert.py
@@ -30,6 +30,7 @@
 import shutil
 import six
 import base64
+import re
 
 from ipalib import api, x509
 from ipaserver.plugins import rabase
@@ -40,6 +41,20 @@
     unicode = str
 
 
+def strip_cert_header(pem):
+    """
+    Remove the header and footer from a certificate.
+    """
+    regexp = (
+        r"^-----BEGIN CERTIFICATE-----(.*?)-----END CERTIFICATE-----"
+    )
+    s = re.search(regexp, pem, re.MULTILINE | re.DOTALL)
+    if s is not None:
+        return s.group(1)
+    else:
+        return pem
+
+
 def get_testcert(subject, principal):
     """Get the certificate, creating it if it doesn't exist"""
     reqdir = tempfile.mkdtemp(prefix="tmp-")
@@ -48,7 +63,7 @@ def get_testcert(subject, principal):
                              principal)
     finally:
         shutil.rmtree(reqdir)
-    return x509.strip_header(_testcert)
+    return strip_cert_header(_testcert.decode('utf-8'))
 
 
 def run_certutil(reqdir, args, stdin=None):
@@ -99,4 +114,4 @@ def makecert(reqdir, subject, principal):
     res = api.Command['cert_request'](csr, principal=principal, add=True)
     cert = x509.load_der_x509_certificate(
         base64.b64decode(res['result']['certificate']))
-    return cert.public_bytes(x509.Encoding.PEM).decode('utf-8')
+    return cert.public_bytes(x509.Encoding.PEM)

From 0e05a1c6321e8cf3ccbc28cb2855f8fe9ddb355e Mon Sep 17 00:00:00 2001
From: Stanislav Laznicka <slazn...@redhat.com>
Date: Mon, 25 Sep 2017 09:58:07 +0200
Subject: [PATCH 2/2] x509: remove subject_base() function

The x509.subject_base() function is only used in tests. During
the recent certificate refactoring, we had to get rid of the
ipalib.x509 import from the module scope so that there were no
circular dependecies and add it exactly to this funcion which
is not used in the production code.

Note that we cannot move the x509 module from ipalib to ipapython
yet because it still needs to import ipalib.errors.
---
 ipalib/x509.py                              | 13 -------------
 ipatests/test_xmlrpc/test_cert_plugin.py    |  4 ++--
 ipatests/test_xmlrpc/test_host_plugin.py    |  6 +++---
 ipatests/test_xmlrpc/test_service_plugin.py | 18 +++++++++---------
 ipatests/test_xmlrpc/testcert.py            | 14 ++++++++++++++
 5 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/ipalib/x509.py b/ipalib/x509.py
index 9e2b365ea2..fa6a6f12a5 100644
--- a/ipalib/x509.py
+++ b/ipalib/x509.py
@@ -51,7 +51,6 @@
 import six
 
 from ipalib import errors
-from ipapython.dn import DN
 from ipapython.dnsutil import DNSName
 
 if six.PY3:
@@ -76,18 +75,6 @@
 SAN_UPN = '1.3.6.1.4.1.311.20.2.3'
 SAN_KRB5PRINCIPALNAME = '1.3.6.1.5.2.2'
 
-_subject_base = None
-
-def subject_base():
-    from ipalib import api
-    global _subject_base
-
-    if _subject_base is None:
-        config = api.Command['config_show']()['result']
-        _subject_base = DN(config['ipacertificatesubjectbase'][0])
-
-    return _subject_base
-
 
 @crypto_utils.register_interface(crypto_x509.Certificate)
 class IPACertificate(object):
diff --git a/ipatests/test_xmlrpc/test_cert_plugin.py b/ipatests/test_xmlrpc/test_cert_plugin.py
index 0de5b75346..4b962aafd8 100644
--- a/ipatests/test_xmlrpc/test_cert_plugin.py
+++ b/ipatests/test_xmlrpc/test_cert_plugin.py
@@ -30,11 +30,11 @@
 import tempfile
 from ipalib import api
 from ipalib import errors
-from ipalib import x509
 from ipaplatform.paths import paths
 from ipapython import ipautil
 from ipapython.dn import DN
 from ipapython.ipautil import run
+from ipatests.test_xmlrpc.testcert import subject_base
 from ipatests.test_xmlrpc.xmlrpc_test import XMLRPC_test
 from nose.tools import raises, assert_raises
 
@@ -109,7 +109,7 @@ def setup(self):
         # Create our temporary NSS database
         self.run_certutil(["-N", "-f", self.pwname])
 
-        self.subject = DN(('CN', self.host_fqdn), x509.subject_base())
+        self.subject = DN(('CN', self.host_fqdn), subject_base())
 
     def teardown(self):
         shutil.rmtree(self.reqdir, ignore_errors=True)
diff --git a/ipatests/test_xmlrpc/test_host_plugin.py b/ipatests/test_xmlrpc/test_host_plugin.py
index eab5bf7b51..b67fcaaf04 100644
--- a/ipatests/test_xmlrpc/test_host_plugin.py
+++ b/ipatests/test_xmlrpc/test_host_plugin.py
@@ -41,7 +41,7 @@
 from ipatests.test_xmlrpc.test_user_plugin import get_group_dn
 from ipatests.test_xmlrpc import objectclasses
 from ipatests.test_xmlrpc.tracker.host_plugin import HostTracker
-from ipatests.test_xmlrpc.testcert import get_testcert
+from ipatests.test_xmlrpc.testcert import get_testcert, subject_base
 from ipatests.util import assert_deepequal
 from ipaplatform.paths import paths
 
@@ -97,7 +97,7 @@
 hostgroup1_dn = DN(('cn',hostgroup1),('cn','hostgroups'),('cn','accounts'),
                     api.env.basedn)
 
-host_cert = get_testcert(DN(('CN', api.env.host), x509.subject_base()),
+host_cert = get_testcert(DN(('CN', api.env.host), subject_base()),
                          'host/%s@%s' % (api.env.host, api.env.realm))
 
 
@@ -237,7 +237,7 @@ def test_update_simple(self, host):
                         serial_number_hex=fuzzy_hex,
                         sha1_fingerprint=fuzzy_hash,
                         sha256_fingerprint=fuzzy_hash,
-                        subject=DN(('CN', api.env.host), x509.subject_base()),
+                        subject=DN(('CN', api.env.host), subject_base()),
                         valid_not_before=fuzzy_date,
                         valid_not_after=fuzzy_date,
                     ))
diff --git a/ipatests/test_xmlrpc/test_service_plugin.py b/ipatests/test_xmlrpc/test_service_plugin.py
index 514ca5b26f..b50b1bb0a2 100644
--- a/ipatests/test_xmlrpc/test_service_plugin.py
+++ b/ipatests/test_xmlrpc/test_service_plugin.py
@@ -21,12 +21,12 @@
 Test the `ipaserver/plugins/service.py` module.
 """
 
-from ipalib import api, errors, x509
+from ipalib import api, errors
 from ipatests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid, fuzzy_hash
 from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_digits, fuzzy_date, fuzzy_issuer
 from ipatests.test_xmlrpc.xmlrpc_test import fuzzy_hex, XMLRPC_test
 from ipatests.test_xmlrpc import objectclasses
-from ipatests.test_xmlrpc.testcert import get_testcert
+from ipatests.test_xmlrpc.testcert import get_testcert, subject_base
 from ipatests.test_xmlrpc.test_user_plugin import get_user_result, get_group_dn
 
 from ipatests.test_xmlrpc.tracker.service_plugin import ServiceTracker
@@ -50,7 +50,7 @@
 role1 = u'Test Role'
 role1_dn = DN(('cn', role1), api.env.container_rolegroup, api.env.basedn)
 
-servercert= get_testcert(DN(('CN', api.env.host), x509.subject_base()),
+servercert= get_testcert(DN(('CN', api.env.host), subject_base()),
                          'unittest/%s@%s' % (api.env.host, api.env.realm))
 randomissuercert = (
     "MIICbzCCAdigAwIBAgICA/4wDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3Q"
@@ -485,7 +485,7 @@ class test_service(Declarative):
                     managedby_host=[fqdn1],
                     valid_not_before=fuzzy_date,
                     valid_not_after=fuzzy_date,
-                    subject=DN(('CN',api.env.host),x509.subject_base()),
+                    subject=DN(('CN',api.env.host),subject_base()),
                     serial_number=fuzzy_digits,
                     serial_number_hex=fuzzy_hex,
                     sha1_fingerprint=fuzzy_hash,
@@ -522,7 +522,7 @@ class test_service(Declarative):
                     ipakrbauthzdata=[u'MS-PAC'],
                     valid_not_before=fuzzy_date,
                     valid_not_after=fuzzy_date,
-                    subject=DN(('CN',api.env.host),x509.subject_base()),
+                    subject=DN(('CN',api.env.host),subject_base()),
                     serial_number=fuzzy_digits,
                     serial_number_hex=fuzzy_hex,
                     sha1_fingerprint=fuzzy_hash,
@@ -551,7 +551,7 @@ class test_service(Declarative):
                     # test case.
                     valid_not_before=fuzzy_date,
                     valid_not_after=fuzzy_date,
-                    subject=DN(('CN',api.env.host),x509.subject_base()),
+                    subject=DN(('CN',api.env.host),subject_base()),
                     serial_number=fuzzy_digits,
                     serial_number_hex=fuzzy_hex,
                     sha1_fingerprint=fuzzy_hash,
@@ -576,7 +576,7 @@ class test_service(Declarative):
                     ipakrbauthzdata=[u'MS-PAC'],
                     valid_not_before=fuzzy_date,
                     valid_not_after=fuzzy_date,
-                    subject=DN(('CN',api.env.host),x509.subject_base()),
+                    subject=DN(('CN',api.env.host),subject_base()),
                     serial_number=fuzzy_digits,
                     serial_number_hex=fuzzy_hex,
                     sha1_fingerprint=fuzzy_hash,
@@ -604,7 +604,7 @@ class test_service(Declarative):
                     ipakrbauthzdata=[u'MS-PAC'],
                     valid_not_before=fuzzy_date,
                     valid_not_after=fuzzy_date,
-                    subject=DN(('CN',api.env.host),x509.subject_base()),
+                    subject=DN(('CN',api.env.host),subject_base()),
                     serial_number=fuzzy_digits,
                     serial_number_hex=fuzzy_hex,
                     sha1_fingerprint=fuzzy_hash,
@@ -630,7 +630,7 @@ class test_service(Declarative):
                     ipakrbauthzdata=[u'MS-PAC'],
                     valid_not_before=fuzzy_date,
                     valid_not_after=fuzzy_date,
-                    subject=DN(('CN',api.env.host),x509.subject_base()),
+                    subject=DN(('CN',api.env.host),subject_base()),
                     serial_number=fuzzy_digits,
                     serial_number_hex=fuzzy_hex,
                     sha1_fingerprint=fuzzy_hash,
diff --git a/ipatests/test_xmlrpc/testcert.py b/ipatests/test_xmlrpc/testcert.py
index 6ea5a50eef..3874d75f29 100644
--- a/ipatests/test_xmlrpc/testcert.py
+++ b/ipatests/test_xmlrpc/testcert.py
@@ -35,12 +35,26 @@
 from ipalib import api, x509
 from ipaserver.plugins import rabase
 from ipapython import ipautil
+from ipapython.dn import DN
 from ipaplatform.paths import paths
 
 if six.PY3:
     unicode = str
 
 
+_subject_base = None
+
+
+def subject_base():
+    global _subject_base
+
+    if _subject_base is None:
+        config = api.Command['config_show']()['result']
+        _subject_base = DN(config['ipacertificatesubjectbase'][0])
+
+    return _subject_base
+
+
 def strip_cert_header(pem):
     """
     Remove the header and footer from a certificate.
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org

Reply via email to