Jan Cholasta wrote:
On 26.4.2011 22:52, Rob Crittenden wrote:
The goal is to not import foreign certificates.

This caused a bunch of tests to fail because we had a hardcoded server
certificate. Instead a developer will need to run make-testcert to
create a server certificate generated by the local CA to test against.

ticket 1134

rob


NACK

The certificate isn't verified in host-add.

I suspect that certificates signed by an intermediate CA (i.e. when the
certificate chain length > 2) are considered invalid. Is that the
desired behavior?

That will work as long as the issuer is the IPA CA. I see that if we are given a service cert issued by another CA in the chain things could go badly. I'm not sure this is something to really worry about though.


make-testcert fails with:

Traceback (most recent call last):
File "./make-testcert", line 126, in <module>
sys.exit(makecert(reqdir))
File "./make-testcert", line 105, in makecert
add=True)
File "./make-testcert", line 66, in run
result = self.execute(method, *args, **options)
File "/home/jcholast/freeipa/ipalib/backend.py", line 142, in execute
raise error #pylint: disable=E0702
ipalib.errors.CommandError: unknown command 'cert_request'

This is probably an error on my part (tried running in on both my
machine without IPA installed and on VM with IPA installed with no
luck), but nonetheless it should be fixed to fail gracefully so that the
tests in "make test" have a chance to run. Similarly, the tests which
use the test certificate created by make-testcert should be skipped if
the certificate isn't available.

You need to take the certificate databases from a self-signed install and copy them to ~/.ipa/alias/ in order to do certificate testing. There is documentation on how to do this in tests/test_xmlrpc/test_cert.py

I think this should be mandatory as certificates are a main feature of v2.

rob
>From 82059ce0d929de5b79a2114f12454a9709564902 Mon Sep 17 00:00:00 2001
From: Rob Crittenden <rcrit...@redhat.com>
Date: Tue, 26 Apr 2011 16:45:19 -0400
Subject: [PATCH] Require an imported certificate's issuer to match our issuer.

The goal is to not import foreign certificates.

This caused a bunch of tests to fail because we had a hardcoded server
certificate. Instead a developer will need to run make-testcert to
create a server certificate generated by the local CA to test against.

ticket 1134
---
 Makefile                                 |    1 +
 ipalib/plugins/host.py                   |    7 ++
 ipalib/plugins/service.py                |   27 ++++++-
 make-testcert                            |  133 ++++++++++++++++++++++++++++++
 tests/test_xmlrpc/test_host_plugin.py    |   41 +++++----
 tests/test_xmlrpc/test_service_plugin.py |   48 +++++++----
 tests/test_xmlrpc/xmlrpc_test.py         |    6 ++
 7 files changed, 226 insertions(+), 37 deletions(-)
 create mode 100755 make-testcert

diff --git a/Makefile b/Makefile
index d12bb43..3e21ef4 100644
--- a/Makefile
+++ b/Makefile
@@ -82,6 +82,7 @@ lint:
 
 test:
 	$(MAKE) -C install/po test_lang
+	./make-testcert
 	./make-test
 
 release-update:
diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
index a602df4..7a89cdc 100644
--- a/ipalib/plugins/host.py
+++ b/ipalib/plugins/host.py
@@ -85,6 +85,7 @@ from ipalib.plugins.service import normalize_certificate
 from ipalib.plugins.service import set_certificate_attrs
 from ipalib.plugins.service import make_pem, check_writable_file
 from ipalib.plugins.service import write_certificate
+from ipalib.plugins.service import verify_cert_subject
 from ipalib.plugins.dns import dns_container_exists, _record_types
 from ipalib.plugins.dns import add_forward_record
 from ipalib import _, ngettext
@@ -378,6 +379,11 @@ class host_add(LDAPCreate):
                 # save the password so it can be displayed in post_callback
                 setattr(context, 'randompassword', entry_attrs['userpassword'])
             del entry_attrs['random']
+        cert = options.get('usercertificate')
+        if cert:
+            cert = normalize_certificate(cert)
+            verify_cert_subject(ldap, keys[-1], cert)
+            entry_attrs['usercertificate'] = cert
         entry_attrs['managedby'] = dn
         return dn
 
@@ -574,6 +580,7 @@ class host_mod(LDAPUpdate):
                 entry_attrs['objectclass'] = obj_classes
         cert = normalize_certificate(entry_attrs.get('usercertificate'))
         if cert:
+            verify_cert_subject(ldap, keys[-1], cert)
             (dn, entry_attrs_old) = ldap.get_entry(dn, ['usercertificate'])
             if 'usercertificate' in entry_attrs_old:
                 oldcert = normalize_certificate(entry_attrs_old.get('usercertificate')[0])
diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py
index 2f47e06..8595627 100644
--- a/ipalib/plugins/service.py
+++ b/ipalib/plugins/service.py
@@ -206,6 +206,25 @@ def normalize_certificate(cert):
 
     return cert
 
+def verify_cert_subject(ldap, hostname, cert):
+    """
+    Verify that the certificate issuer we're adding matches the issuer
+    base of our installation.
+
+    This assumes the certificate has already been normalized.
+
+    This raises an exception on errors and returns nothing otherwise.
+    """
+    cert = x509.load_certificate(cert, datatype=x509.DER)
+    subject = str(cert.subject)
+    issuer = str(cert.issuer)
+
+    # Handle both supported forms of issuer, from selfsign and dogtag.
+    if ((issuer != 'CN=%s Certificate Authority' % api.env.realm) and
+        (issuer != 'CN=Certificate Authority,O=%s' % api.env.realm)):
+        raise errors.CertificateOperationError(error=_('Issuer "%(issuer)s" does not match the expected issuer') % \
+        {'issuer' : issuer})
+
 def set_certificate_attrs(entry_attrs):
     """
     Set individual attributes from some values from a certificate.
@@ -342,7 +361,9 @@ class service_add(LDAPCreate):
 
         cert = options.get('usercertificate')
         if cert:
-            entry_attrs['usercertificate'] = normalize_certificate(cert)
+            cert = normalize_certificate(cert)
+            verify_cert_subject(ldap, hostname, cert)
+            entry_attrs['usercertificate'] = cert
 
         if not options.get('force', False):
              # We know the host exists if we've gotten this far but we
@@ -406,9 +427,11 @@ class service_mod(LDAPUpdate):
 
     def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
         if 'usercertificate' in options:
+            (service, hostname, realm) = split_principal(keys[-1])
             cert = options.get('usercertificate')
-            cert = normalize_certificate(cert)
             if cert:
+                cert = normalize_certificate(cert)
+                verify_cert_subject(ldap, hostname, cert)
                 (dn, entry_attrs_old) = ldap.get_entry(dn, ['usercertificate'])
                 if 'usercertificate' in entry_attrs_old:
                     # FIXME: what to do here? do we revoke the old cert?
diff --git a/make-testcert b/make-testcert
new file mode 100755
index 0000000..f3e7aa3
--- /dev/null
+++ b/make-testcert
@@ -0,0 +1,133 @@
+#!/usr/bin/python
+#
+# Authors:
+#   Rob Crittenden <rcrit...@redhat.com>
+#
+# Copyright (C) 2011  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Generate a custom certificate used in the service unit tests. The certificate
+will be created in tests/test_xmlrpc/service.crt
+"""
+import sys
+import os
+import tempfile
+import shutil
+import nss.nss as nss
+from ipalib import api, x509, backend, errors
+from ipaserver.plugins import rabase
+from ipapython import ipautil
+
+CERTPATH = 'tests/test_xmlrpc/service.crt'
+
+def run_certutil(reqdir, args, stdin=None):
+    """
+    Run an NSS certutil command
+    """
+    new_args = ["/usr/bin/certutil", "-d", reqdir]
+    new_args = new_args + args
+    return ipautil.run(new_args, stdin)
+
+def generateCSR(reqdir, pwname, subject):
+    """
+    Create a CSR for the given subject.
+    """
+    run_certutil(reqdir, ["-R", "-s", subject,
+                       "-o", '%s/req' % reqdir,
+                       "-z", "/etc/group",
+                       "-f", pwname,
+                       "-a",
+                       ])
+    fp = open('%s/req' % reqdir, "r")
+    data = fp.read()
+    fp.close()
+    return data
+
+class client(backend.Executioner):
+    """
+    A simple-minded IPA client that can execute remote commands.
+    """
+
+    def run(self, method, *args, **options):
+        self.create_context()
+        result = self.execute(method, *args, **options)
+        return result
+
+
+def makecert(reqdir):
+    """
+    Generate a service certificate that can be used during unit testing.
+    """
+    cfg = dict(
+        context='cli',
+        in_server=False,
+        debug=False,
+        verbose=0,
+    )
+
+    api.bootstrap(**cfg)
+    api.register(client)
+    api.finalize()
+
+    # This needs to be imported after the API is initialized
+    from ipalib.plugins.service import make_pem
+
+    ra = rabase.rabase()
+    if not os.path.exists(ra.sec_dir) and api.env.xmlrpc_uri == 'http://localhost:8888/ipa/xml':
+        sys.exit('The in-tree self-signed CA is not configured, see tests/test_xmlrpc/test_cert.py')
+
+    pwname = reqdir + "/pwd"
+
+    # Create an empty password file
+    fp = open(pwname, "w")
+    fp.write("\n")
+    fp.close()
+
+    # Generate NSS cert database to store the private key for our CSR
+    run_certutil(reqdir, ["-N", "-f", pwname])
+
+    cert = None
+    subject = 'CN=%s,O=%s' % (api.env.host, api.env.realm)
+    princ = 'unittest/%s@%s' % (api.env.host, api.env.realm)
+    csr = unicode(generateCSR(reqdir, pwname, subject))
+
+    try:
+        res = api.Backend.client.run('cert_request', csr, principal=princ,
+            add=True)
+        cert = make_pem(res['result']['certificate'])
+        fd = open(CERTPATH, 'w')
+        fd.write(cert)
+        fd.close()
+    except errors.NotFound:
+        return "certificate request failed"
+
+    nss.nss_init_nodb()
+    c = x509.load_certificate(cert, x509.PEM)
+    print c
+
+    return 0
+
+reqdir = None
+
+if os.path.exists(CERTPATH):
+    print "Test certificate %s exists, skipping." % CERTPATH
+    sys.exit(0)
+try:
+    reqdir = tempfile.mkdtemp(prefix = "tmp-")
+    sys.exit(makecert(reqdir))
+finally:
+    shutil.rmtree(reqdir)
diff --git a/tests/test_xmlrpc/test_host_plugin.py b/tests/test_xmlrpc/test_host_plugin.py
index 18f813d..842c940 100644
--- a/tests/test_xmlrpc/test_host_plugin.py
+++ b/tests/test_xmlrpc/test_host_plugin.py
@@ -22,8 +22,9 @@
 Test the `ipalib.plugins.host` module.
 """
 
-from ipalib import api, errors
-from tests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid
+from ipalib import api, errors, x509
+from tests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid, fuzzy_digits
+from tests.test_xmlrpc.xmlrpc_test import fuzzy_hash, fuzzy_date
 from tests.test_xmlrpc import objectclasses
 import base64
 
@@ -39,8 +40,12 @@ fqdn3 = u'testhost2.%s' % api.env.domain
 short3 = u'testhost2'
 dn3 = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn3, api.env.basedn)
 
-servercert = 'MIICbzCCAdigAwIBAgICA/4wDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDgwOTE1MDIyN1oXDTIwMDgwOTE1MDIyN1owKTEMMAoGA1UEChMDSVBBMRkwFwYDVQQDExBwdW1hLmdyZXlvYWsuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwYbfEOQPgGenPn9vt1JFKvWm/Je3y2tawGWA3LXDuqfFJyYtZ8ib3TcBUOnLk9WK5g2qCwHaNlei7bj8ggIfr5hegAVe10cun+wYErjnYo7hsHYd+57VZezeipWrXu+7NoNd4+c4A5lk4A/xJay9j3bYx2oOM8BEox4xWYoWge1ljPrc5JK46f0X7AGW4F2VhnKPnf8rwSuzI1U8VGjutyM9TWNy3m9KMWeScjyG/ggIpOjUDMV7HkJL0Di61lznR9jXubpiEC7gWGbTp84eGl/Nn9bgK1AwHfJ2lHwfoY4uiL7ge1gyP6EvuUlHoBzdb7pekiX28iePjW3iEG9IawIDAQABoyIwIDARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4GBACRESLemRV9BPxfEgbALuxH5oE8jQm8WZ3pm2pALbpDlAd9wQc3yVf6RtkfVthyDnM18bg7IhxKpd77/p3H8eCnS8w5MLVRda6ktUC6tGhFTS4QKAf0WyDGTcIgkXbeDw0OPAoNHivoXbIXIIRxlw/XgaSaMzJQDBG8iROsN4kCv'
-
+# We can use the same cert we generated for the service tests
+fd = open('tests/test_xmlrpc/service.crt', 'r')
+servercert = fd.readlines()
+servercert = ''.join(servercert)
+servercert = x509.strip_header(servercert)
+fd.close()
 
 class test_host(Declarative):
 
@@ -223,13 +228,13 @@ class test_host(Declarative):
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
                     managedby_host=[u'%s' % fqdn1],
                     usercertificate=[base64.b64decode(servercert)],
-                    valid_not_before=u'Mon Aug 09 15:02:27 2010 UTC',
-                    valid_not_after=u'Sun Aug 09 15:02:27 2020 UTC',
-                    subject=u'CN=puma.greyoak.com,O=IPA',
-                    serial_number=u'1022',
-                    md5_fingerprint=u'ef:63:31:e4:33:54:8d:fd:fe:c8:66:57:09:03:5f:09',
-                    sha1_fingerprint=u'e3:33:2c:d9:7c:e9:77:74:2a:ac:3b:b8:76:b0:86:29:98:43:58:11',
-                    issuer=u'CN=IPA Test Certificate Authority',
+                    valid_not_before=fuzzy_date,
+                    valid_not_after=fuzzy_date,
+                    subject=u'CN=puma.greyoak.com,O=%s' % api.env.realm,
+                    serial_number=fuzzy_digits,
+                    md5_fingerprint=fuzzy_hash,
+                    sha1_fingerprint=fuzzy_hash,
+                    issuer=u'CN=%s Certificate Authority' % api.env.realm,
                 ),
             ),
         ),
@@ -250,13 +255,13 @@ class test_host(Declarative):
                     has_keytab=False,
                     managedby_host=[u'%s' % fqdn1],
                     usercertificate=[base64.b64decode(servercert)],
-                    valid_not_before=u'Mon Aug 09 15:02:27 2010 UTC',
-                    valid_not_after=u'Sun Aug 09 15:02:27 2020 UTC',
-                    subject=u'CN=puma.greyoak.com,O=IPA',
-                    serial_number=u'1022',
-                    md5_fingerprint=u'ef:63:31:e4:33:54:8d:fd:fe:c8:66:57:09:03:5f:09',
-                    sha1_fingerprint=u'e3:33:2c:d9:7c:e9:77:74:2a:ac:3b:b8:76:b0:86:29:98:43:58:11',
-                    issuer=u'CN=IPA Test Certificate Authority',
+                    valid_not_before=fuzzy_date,
+                    valid_not_after=fuzzy_date,
+                    subject=u'CN=puma.greyoak.com,O=%s' % api.env.realm,
+                    serial_number=fuzzy_digits,
+                    md5_fingerprint=fuzzy_hash,
+                    sha1_fingerprint=fuzzy_hash,
+                    issuer=u'CN=%s Certificate Authority' % api.env.realm,
                 ),
             ),
         ),
diff --git a/tests/test_xmlrpc/test_service_plugin.py b/tests/test_xmlrpc/test_service_plugin.py
index 7c13eb4..169c45c 100644
--- a/tests/test_xmlrpc/test_service_plugin.py
+++ b/tests/test_xmlrpc/test_service_plugin.py
@@ -21,8 +21,9 @@
 Test the `ipalib/plugins/service.py` module.
 """
 
-from ipalib import api, errors
-from tests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid
+from ipalib import api, errors, x509
+from tests.test_xmlrpc.xmlrpc_test import Declarative, fuzzy_uuid, fuzzy_hash
+from tests.test_xmlrpc.xmlrpc_test import fuzzy_digits, fuzzy_date
 from tests.test_xmlrpc import objectclasses
 import base64
 
@@ -37,7 +38,13 @@ host1dn = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn1, api.env.basedn)
 host2dn = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn2, api.env.basedn)
 host3dn = u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn3.lower(), api.env.basedn)
 
-servercert = 'MIICbzCCAdigAwIBAgICA/4wDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDgwOTE1MDIyN1oXDTIwMDgwOTE1MDIyN1owKTEMMAoGA1UEChMDSVBBMRkwFwYDVQQDExBwdW1hLmdyZXlvYWsuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwYbfEOQPgGenPn9vt1JFKvWm/Je3y2tawGWA3LXDuqfFJyYtZ8ib3TcBUOnLk9WK5g2qCwHaNlei7bj8ggIfr5hegAVe10cun+wYErjnYo7hsHYd+57VZezeipWrXu+7NoNd4+c4A5lk4A/xJay9j3bYx2oOM8BEox4xWYoWge1ljPrc5JK46f0X7AGW4F2VhnKPnf8rwSuzI1U8VGjutyM9TWNy3m9KMWeScjyG/ggIpOjUDMV7HkJL0Di61lznR9jXubpiEC7gWGbTp84eGl/Nn9bgK1AwHfJ2lHwfoY4uiL7ge1gyP6EvuUlHoBzdb7pekiX28iePjW3iEG9IawIDAQABoyIwIDARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4GBACRESLemRV9BPxfEgbALuxH5oE8jQm8WZ3pm2pALbpDlAd9wQc3yVf6RtkfVthyDnM18bg7IhxKpd77/p3H8eCnS8w5MLVRda6ktUC6tGhFTS4QKAf0WyDGTcIgkXbeDw0OPAoNHivoXbIXIIRxlw/XgaSaMzJQDBG8iROsN4kCv'
+fd = open('tests/test_xmlrpc/service.crt', 'r')
+servercert = fd.readlines()
+servercert = ''.join(servercert)
+servercert = x509.strip_header(servercert)
+fd.close()
+
+badservercert = 'MIICbzCCAdigAwIBAgICA/4wDQYJKoZIhvcNAQEFBQAwKTEnMCUGA1UEAxMeSVBBIFRlc3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MB4XDTEwMDgwOTE1MDIyN1oXDTIwMDgwOTE1MDIyN1owKTEMMAoGA1UEChMDSVBBMRkwFwYDVQQDExBwdW1hLmdyZXlvYWsuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwYbfEOQPgGenPn9vt1JFKvWm/Je3y2tawGWA3LXDuqfFJyYtZ8ib3TcBUOnLk9WK5g2qCwHaNlei7bj8ggIfr5hegAVe10cun+wYErjnYo7hsHYd+57VZezeipWrXu+7NoNd4+c4A5lk4A/xJay9j3bYx2oOM8BEox4xWYoWge1ljPrc5JK46f0X7AGW4F2VhnKPnf8rwSuzI1U8VGjutyM9TWNy3m9KMWeScjyG/ggIpOjUDMV7HkJL0Di61lznR9jXubpiEC7gWGbTp84eGl/Nn9bgK1AwHfJ2lHwfoY4uiL7ge1gyP6EvuUlHoBzdb7pekiX28iePjW3iEG9IawIDAQABoyIwIDARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4GBACRESLemRV9BPxfEgbALuxH5oE8jQm8WZ3pm2pALbpDlAd9wQc3yVf6RtkfVthyDnM18bg7IhxKpd77/p3H8eCnS8w5MLVRda6ktUC6tGhFTS4QKAf0WyDGTcIgkXbeDw0OPAoNHivoXbIXIIRxlw/XgaSaMzJQDBG8iROsN4kCv'
 
 
 class test_host(Declarative):
@@ -346,6 +353,13 @@ class test_host(Declarative):
 
 
         dict(
+            desc='Update %r with a bad certificate' % service1,
+            command=('service_mod', [service1], dict(usercertificate=badservercert)),
+            expected=errors.CertificateOperationError(error='exact error msg not needed'),
+        ),
+
+
+        dict(
             desc='Update %r' % service1,
             command=('service_mod', [service1], dict(usercertificate=servercert)),
             expected=dict(
@@ -355,13 +369,13 @@ class test_host(Declarative):
                     usercertificate=[base64.b64decode(servercert)],
                     krbprincipalname=[service1],
                     managedby_host=[fqdn1],
-                    valid_not_before=u'Mon Aug 09 15:02:27 2010 UTC',
-                    valid_not_after=u'Sun Aug 09 15:02:27 2020 UTC',
-                    subject=u'CN=puma.greyoak.com,O=IPA',
-                    serial_number=u'1022',
-                    md5_fingerprint=u'ef:63:31:e4:33:54:8d:fd:fe:c8:66:57:09:03:5f:09',
-                    sha1_fingerprint=u'e3:33:2c:d9:7c:e9:77:74:2a:ac:3b:b8:76:b0:86:29:98:43:58:11',
-                    issuer=u'CN=IPA Test Certificate Authority',
+                    valid_not_before=fuzzy_date,
+                    valid_not_after=fuzzy_date,
+                    subject=u'CN=puma.greyoak.com,O=%s' % api.env.realm,
+                    serial_number=fuzzy_digits,
+                    md5_fingerprint=fuzzy_hash,
+                    sha1_fingerprint=fuzzy_hash,
+                    issuer=u'CN=%s Certificate Authority' % api.env.realm,
                 ),
             ),
         ),
@@ -381,13 +395,13 @@ class test_host(Declarative):
                     managedby_host=[fqdn1],
                     # These values come from the servercert that is in this
                     # test case.
-                    valid_not_before=u'Mon Aug 09 15:02:27 2010 UTC',
-                    valid_not_after=u'Sun Aug 09 15:02:27 2020 UTC',
-                    subject=u'CN=puma.greyoak.com,O=IPA',
-                    serial_number=u'1022',
-                    md5_fingerprint=u'ef:63:31:e4:33:54:8d:fd:fe:c8:66:57:09:03:5f:09',
-                    sha1_fingerprint=u'e3:33:2c:d9:7c:e9:77:74:2a:ac:3b:b8:76:b0:86:29:98:43:58:11',
-                    issuer=u'CN=IPA Test Certificate Authority',
+                    valid_not_before=fuzzy_date,
+                    valid_not_after=fuzzy_date,
+                    subject=u'CN=puma.greyoak.com,O=%s' % api.env.realm,
+                    serial_number=fuzzy_digits,
+                    md5_fingerprint=fuzzy_hash,
+                    sha1_fingerprint=fuzzy_hash,
+                    issuer=u'CN=%s Certificate Authority' % api.env.realm,
                 ),
             ),
         ),
diff --git a/tests/test_xmlrpc/xmlrpc_test.py b/tests/test_xmlrpc/xmlrpc_test.py
index 7543fde..7b6a741 100644
--- a/tests/test_xmlrpc/xmlrpc_test.py
+++ b/tests/test_xmlrpc/xmlrpc_test.py
@@ -44,6 +44,12 @@ fuzzy_netgroupdn = Fuzzy(
     'ipauniqueid=[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12},cn=ng,cn=alt,%s' % api.env.basedn
 )
 
+# Matches a hash signature, not enforcing length
+fuzzy_hash = Fuzzy('^([a-f0-9][a-f0-9]:)+[a-f0-9][a-f0-9]$', type=basestring)
+
+# Matches a date, like Tue Apr 26 17:45:35 2016 UTC
+fuzzy_date = Fuzzy('^[a-zA-Z]{3} [a-zA-Z]{3} \d{2} \d{2}:\d{2}:\d{2} \d{4} UTC$')
+
 try:
     if not api.Backend.xmlclient.isconnected():
         api.Backend.xmlclient.connect(fallback=False)
-- 
1.7.4

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to