tests: Create the testing service certificate on demand

Replace the make-testcert command with a module that creates
the certificate when it is first needed.
As a result the tests are more self-contained, and can be run from
a read-only location (such as installed from a system package).

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Petr Viktorin
2014-03-05 16:46:21 +01:00
parent 5ae737e160
commit 68f4af3122
6 changed files with 121 additions and 166 deletions

1
.gitignore vendored
View File

@@ -64,7 +64,6 @@ freeipa2-dev-doc
/ipa-client/ipa-join
/ipa-client/ipa-rmkeytab
/ipatests/test_xmlrpc/service.crt
/ipatests/setup.py
/ipapython/setup.py

View File

@@ -113,7 +113,6 @@ lint: bootstrap-autogen
test:
./make-testcert
./make-test
release-update:

View File

@@ -28,11 +28,12 @@ from ipapython import ipautil
from ipalib import api, errors, x509
from ipapython.dn import DN
from nose.tools import raises, assert_raises
from nose.plugins.skip import Skip, SkipTest
from nose.plugins.skip import SkipTest
from ipatests.test_xmlrpc.xmlrpc_test import (Declarative, XMLRPC_test,
fuzzy_uuid, fuzzy_digits, fuzzy_hash, fuzzy_date, fuzzy_issuer,
fuzzy_hex)
from ipatests.test_xmlrpc import objectclasses
from ipatests.test_xmlrpc.testcert import get_testcert
import base64
@@ -55,13 +56,6 @@ dn4 = DN(('fqdn',fqdn4),('cn','computers'),('cn','accounts'),
api.env.basedn)
invalidfqdn1 = u'foo_bar.lab.%s' % api.env.domain
# We can use the same cert we generated for the service tests
fd = open('ipatests/test_xmlrpc/service.crt', 'r')
servercert = fd.readlines()
servercert = ''.join(servercert)
servercert = x509.strip_header(servercert)
fd.close()
sshpubkey = u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGAX3xAeLeaJggwTqMjxNwa6XHBUAikXPGMzEpVrlLDCZtv00djsFTBi38PkgxBJVkgRWMrcBsr/35lq7P6w8KGIwA8GI48Z0qBS2NBMJ2u9WQ2hjLN6GdMlo77O0uJY3251p12pCVIS/bHRSq8kHO2No8g7KA9fGGcagPfQH+ee3t7HUkpbQkFTmbPPN++r3V8oVUk5LxbryB3UIIVzNmcSIn3JrXynlvui4MixvrtX6zx+O/bBo68o8/eZD26QrahVbA09fivrn/4h3TM019Eu/c2jOdckfU3cHUV/3Tno5d6JicibyaoDDK7S/yjdn5jhaz8MSEayQvFkZkiF0L public key test'
sshpubkeyfp = u'13:67:6B:BF:4E:A2:05:8E:AE:25:8B:A1:31:DE:6F:1B public key test (ssh-rsa)'
@@ -254,7 +248,7 @@ class test_host(Declarative):
dict(
desc='Update %r' % fqdn1,
command=('host_mod', [fqdn1], dict(description=u'Updated host 1',
usercertificate=servercert)),
usercertificate=get_testcert())),
expected=dict(
value=fqdn1,
summary=u'Modified host "%s"' % fqdn1,
@@ -264,7 +258,7 @@ class test_host(Declarative):
l=[u'Undisclosed location 1'],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
managedby_host=[u'%s' % fqdn1],
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
valid_not_before=fuzzy_date,
valid_not_after=fuzzy_date,
subject=DN(('CN',api.env.host),x509.subject_base()),
@@ -295,7 +289,7 @@ class test_host(Declarative):
has_keytab=False,
has_password=False,
managedby_host=[u'%s' % fqdn1],
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
valid_not_before=fuzzy_date,
valid_not_after=fuzzy_date,
subject=DN(('CN',api.env.host),x509.subject_base()),
@@ -493,7 +487,7 @@ class test_host(Declarative):
l=[u'Undisclosed location 1'],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
managedby_host=[u'%s' % fqdn1],
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
valid_not_before=fuzzy_date,
valid_not_after=fuzzy_date,
subject=DN(('CN',api.env.host),x509.subject_base()),
@@ -522,7 +516,7 @@ class test_host(Declarative):
l=[u'Undisclosed location 1'],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
managedby_host=[u'%s' % fqdn1],
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
valid_not_before=fuzzy_date,
valid_not_after=fuzzy_date,
subject=DN(('CN',api.env.host),x509.subject_base()),
@@ -560,7 +554,7 @@ class test_host(Declarative):
l=[u'Undisclosed location 1'],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
managedby_host=[u'%s' % fqdn1],
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
valid_not_before=fuzzy_date,
valid_not_after=fuzzy_date,
subject=DN(('CN',api.env.host),x509.subject_base()),

View File

@@ -26,6 +26,7 @@ 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
from ipatests.test_xmlrpc import objectclasses
from ipatests.test_xmlrpc.testcert import get_testcert
import base64
from ipapython.dn import DN
@@ -39,11 +40,6 @@ host1dn = DN(('fqdn',fqdn1),('cn','computers'),('cn','accounts'),api.env.basedn)
host2dn = DN(('fqdn',fqdn2),('cn','computers'),('cn','accounts'),api.env.basedn)
host3dn = DN(('fqdn',fqdn3),('cn','computers'),('cn','accounts'),api.env.basedn)
fd = open('ipatests/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'
@@ -68,7 +64,7 @@ class test_service(Declarative):
dict(
desc='Try to update non-existent %r' % service1,
command=('service_mod', [service1], dict(usercertificate=servercert)),
command=('service_mod', [service1], dict(usercertificate=get_testcert())),
expected=errors.NotFound(
reason=u'%s: service not found' % service1),
),
@@ -380,12 +376,12 @@ class test_service(Declarative):
dict(
desc='Update %r' % service1,
command=('service_mod', [service1], dict(usercertificate=servercert)),
command=('service_mod', [service1], dict(usercertificate=get_testcert())),
expected=dict(
value=service1,
summary=u'Modified service "%s"' % service1,
result=dict(
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
krbprincipalname=[service1],
managedby_host=[fqdn1],
valid_not_before=fuzzy_date,
@@ -420,7 +416,7 @@ class test_service(Declarative):
value=service1,
summary=u'Modified service "%s"' % service1,
result=dict(
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
krbprincipalname=[service1],
managedby_host=[fqdn1],
ipakrbauthzdata=[u'MS-PAC'],
@@ -445,7 +441,7 @@ class test_service(Declarative):
summary=None,
result=dict(
dn=service1dn,
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
krbprincipalname=[service1],
has_keytab=False,
managedby_host=[fqdn1],
@@ -472,7 +468,7 @@ class test_service(Declarative):
value=service1,
summary=u'Modified service "%s"' % service1,
result=dict(
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
krbprincipalname=[service1],
managedby_host=[fqdn1],
ipakrbauthzdata=[u'MS-PAC'],
@@ -499,7 +495,7 @@ class test_service(Declarative):
value=service1,
summary=u'Modified service "%s"' % service1,
result=dict(
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
krbprincipalname=[service1],
managedby_host=[fqdn1],
ipakrbauthzdata=[u'MS-PAC'],
@@ -524,7 +520,7 @@ class test_service(Declarative):
value=service1,
summary=u'Modified service "%s"' % service1,
result=dict(
usercertificate=[base64.b64decode(servercert)],
usercertificate=[base64.b64decode(get_testcert())],
krbprincipalname=[service1],
managedby_host=[fqdn1],
ipakrbauthzdata=[u'MS-PAC'],
@@ -564,7 +560,7 @@ class test_service(Declarative):
dict(
desc='Try to update non-existent %r' % service1,
command=('service_mod', [service1], dict(usercertificate=servercert)),
command=('service_mod', [service1], dict(usercertificate=get_testcert())),
expected=errors.NotFound(
reason=u'%s: service not found' % service1),
),

View File

@@ -0,0 +1,103 @@
#
# Authors:
# Rob Crittenden <rcritten@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/>.
"""
Provide a custom certificate used in the service tests.
The certificate in cached in a global variable so it only has to be created
once per test run.
"""
import os
import tempfile
import shutil
from ipalib import api, x509
from ipaserver.plugins import rabase
from ipapython import ipautil
from ipapython.dn import DN
_testcert = None
def get_testcert():
"""Get the certificate, creating it if it doesn't exist"""
global _testcert
if _testcert is None:
reqdir = tempfile.mkdtemp(prefix="tmp-")
try:
_testcert = makecert(reqdir)
finally:
shutil.rmtree(reqdir)
return x509.strip_header(_testcert)
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 generate_csr(reqdir, pwname, subject):
"""
Create a CSR for the given subject.
"""
req_path = os.path.join(reqdir, 'req')
run_certutil(reqdir, ["-R", "-s", subject,
"-o", req_path,
"-z", "/etc/group",
"-f", pwname,
"-a"])
with open(req_path, "r") as fp:
return fp.read()
def makecert(reqdir):
"""
Generate a service certificate that can be used during unit testing.
"""
ra = rabase.rabase()
if (not os.path.exists(ra.sec_dir) and
api.env.xmlrpc_uri == 'http://localhost:8888/ipa/xml'):
raise AssertionError('The self-signed CA is not configured, '
'see ipatests/test_xmlrpc/test_cert.py')
pwname = os.path.join(reqdir, "pwd")
# Create an empty password file
with open(pwname, "w") as fp:
fp.write("\n")
# Generate NSS cert database to store the private key for our CSR
run_certutil(reqdir, ["-N", "-f", pwname])
res = api.Command['config_show']()
subject_base = res['result']['ipacertificatesubjectbase'][0]
cert = None
subject = DN(('CN', api.env.host), subject_base)
princ = 'unittest/%s@%s' % (api.env.host, api.env.realm)
csr = unicode(generate_csr(reqdir, pwname, str(subject)))
res = api.Command['cert_request'](csr, principal=princ, add=True)
return x509.make_pem(res['result']['certificate'])

View File

@@ -1,136 +0,0 @@
#!/usr/bin/python2
#
# Authors:
# Rob Crittenden <rcritten@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 ipatests/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
from ipapython.dn import DN
CERTPATH = 'ipatests/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()
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 ipatests/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])
res = api.Backend.client.run('config_show')
subject_base = res['result']['ipacertificatesubjectbase'][0]
cert = None
subject = DN(('CN', api.env.host), subject_base)
princ = 'unittest/%s@%s' % (api.env.host, api.env.realm)
csr = unicode(generateCSR(reqdir, pwname, str(subject)))
try:
res = api.Backend.client.run('cert_request', csr, principal=princ,
add=True)
cert = x509.make_pem(res['result']['certificate'])
fd = open(CERTPATH, 'w')
fd.write(cert)
fd.close()
except errors.NotFound:
return "certificate request failed"
except errors.CommandError:
return "You need to set enable_ra=True in ~/.ipa/default.conf"
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)