URL: https://github.com/freeipa/freeipa/pull/1583 Author: Rezney Title: #1583: [Backport][ipa-4-5]- Ca > ext > ca backport-4-5 Action: opened
PR body: """ Backport of #1372 """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/1583/head:pr1583 git checkout pr1583
From 6621b290c2d033c9d48657a971133a6d1f7e0489 Mon Sep 17 00:00:00 2001 From: Michal Reznik <mrez...@redhat.com> Date: Wed, 6 Dec 2017 11:34:47 +0100 Subject: [PATCH 1/4] paths: add IPA_CACERT_MANAGE and IPA_CERTUPDATE constants Add IPA_CACERT_MANAGE and IPA_CERTUPDATE constants which will be used in test_external_ca test suite. https://pagure.io/freeipa/issue/7302 Reviewed-By: Florence Blanc-Renaud <fren...@redhat.com> --- ipaplatform/base/paths.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index 42240a7106..ac7dcde63c 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -271,6 +271,8 @@ class BasePathNamespace(object): DNSSEC_TOKENS_DIR = "/var/lib/ipa/dnssec/tokens" DNSSEC_SOFTHSM_PIN = "/var/lib/ipa/dnssec/softhsm_pin" IPA_CA_CSR = "/var/lib/ipa/ca.csr" + IPA_CACERT_MANAGE = "/usr/sbin/ipa-cacert-manage" + IPA_CERTUPDATE = "/usr/sbin/ipa-certupdate" PKI_CA_PUBLISH_DIR = "/var/lib/ipa/pki-ca/publish" REPLICA_INFO_TEMPLATE = "/var/lib/ipa/replica-info-%s" REPLICA_INFO_GPG_TEMPLATE = "/var/lib/ipa/replica-info-%s.gpg" From 295a4d47f4a6aed6f776f5ac48f029e4c9f51555 Mon Sep 17 00:00:00 2001 From: Michal Reznik <mrez...@redhat.com> Date: Wed, 6 Dec 2017 11:49:09 +0100 Subject: [PATCH 2/4] test_tasks: add sign_ca_and_transport() function Add sign_ca_and_transport() function which will sign provided csr and transport root CA and signed IPA CA to the host. https://pagure.io/freeipa/issue/7302 Reviewed-By: Florence Blanc-Renaud <fren...@redhat.com> --- ipatests/pytest_plugins/integration/tasks.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ipatests/pytest_plugins/integration/tasks.py b/ipatests/pytest_plugins/integration/tasks.py index 421bddb72d..91b6a1d377 100644 --- a/ipatests/pytest_plugins/integration/tasks.py +++ b/ipatests/pytest_plugins/integration/tasks.py @@ -41,6 +41,7 @@ from ipalib.constants import ( DEFAULT_CONFIG, DOMAIN_SUFFIX_NAME, DOMAIN_LEVEL_0) +from .create_external_ca import ExternalCA from .env_config import env_to_script from .host import Host @@ -1339,3 +1340,30 @@ def ldappasswd_user_change(user, oldpw, newpw, master): args = [paths.LDAPPASSWD, '-D', userdn, '-w', oldpw, '-a', oldpw, '-s', newpw, '-x', '-H', master_ldap_uri] master.run_command(args) + + +def sign_ca_and_transport(host, csr_name, root_ca_name, ipa_ca_name): + """ + Sign ipa csr and save signed CA together with root CA back to the host. + Returns root CA and IPA CA paths on the host. + """ + + test_dir = host.config.test_dir + + # Get IPA CSR as bytes + ipa_csr = host.get_file_contents(csr_name) + + external_ca = ExternalCA() + # Create root CA + root_ca = external_ca.create_ca() + # Sign CSR + ipa_ca = external_ca.sign_csr(ipa_csr) + + root_ca_fname = os.path.join(test_dir, root_ca_name) + ipa_ca_fname = os.path.join(test_dir, ipa_ca_name) + + # Transport certificates (string > file) to master + host.put_file_contents(root_ca_fname, root_ca) + host.put_file_contents(ipa_ca_fname, ipa_ca) + + return (root_ca_fname, ipa_ca_fname) From f107246c8141d24c99beed7bb0d2053566895ce7 Mon Sep 17 00:00:00 2001 From: Michal Reznik <mrez...@redhat.com> Date: Wed, 6 Dec 2017 11:53:35 +0100 Subject: [PATCH 3/4] test_external_ca: selfsigned->ext_ca->selfsigned Add selfsigned > external_ca > selfsigned test case. Covers Pagure issue #7106 https://pagure.io/freeipa/issue/7302 Reviewed-By: Florence Blanc-Renaud <fren...@redhat.com> --- ipatests/test_integration/test_external_ca.py | 125 ++++++++++++++++++++++---- 1 file changed, 106 insertions(+), 19 deletions(-) diff --git a/ipatests/test_integration/test_external_ca.py b/ipatests/test_integration/test_external_ca.py index e3c44100e4..6d23f06de9 100644 --- a/ipatests/test_integration/test_external_ca.py +++ b/ipatests/test_integration/test_external_ca.py @@ -15,11 +15,53 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -import os +import re +import time from ipatests.pytest_plugins.integration import tasks from ipatests.test_integration.base import IntegrationTest -from ipatests.test_integration.create_external_ca import ExternalCA +from ipaplatform.paths import paths + +from itertools import chain, repeat + +IPA_CA = 'ipa_ca.crt' +ROOT_CA = 'root_ca.crt' + +# string to identify PKI restart in the journal +PKI_START_STR = 'Started pki_tomcatd' + + +def check_CA_flag(host, nssdb=paths.PKI_TOMCAT_ALIAS_DIR, + cn='example.test'): + """ + Check if external CA (by default 'example.test' in our test env) has + CA flag in nssdb. + """ + result = host.run_command(['certutil', '-L', '-d', nssdb]) + text = result.stdout_text + + # match CN in cert nickname and C flag in SSL section of NSS flags table + match_CA_flag = re.compile('.*{}.*\s+C'.format(cn)) + match = re.search(match_CA_flag, text) + + return match + + +def match_in_journal(host, string, since='today', services=('certmonger',)): + """ + Returns match object for the particular string. + """ + # prepend '-u' before every service name + service_args = list(chain.from_iterable(list(zip(repeat('-u'), services)))) + command_args = ['journalctl', '--since={}'.format(since)] + service_args + result = host.run_command(command_args) + + output = result.stdout_text + + traceback = re.compile(string) + match = re.search(traceback, output) + + return match class TestExternalCA(IntegrationTest): @@ -40,23 +82,9 @@ def test_external_ca(self): '--external-ca' ]) - test_dir = self.master.config.test_dir - - # Get IPA CSR as bytes - ipa_csr = self.master.get_file_contents('/root/ipa.csr') - - external_ca = ExternalCA() - # Create root CA - root_ca = external_ca.create_ca() - # Sign CSR - ipa_ca = external_ca.sign_csr(ipa_csr) - - root_ca_fname = os.path.join(test_dir, 'root_ca.crt') - ipa_ca_fname = os.path.join(test_dir, 'ipa_ca.crt') - - # Transport certificates (string > file) to master - self.master.put_file_contents(root_ca_fname, root_ca) - self.master.put_file_contents(ipa_ca_fname, ipa_ca) + # Sign CA, transport it to the host and get ipa a root ca paths. + root_ca_fname, ipa_ca_fname = tasks.sign_ca_and_transport( + self.master, paths.ROOT_IPA_CSR, ROOT_CA, IPA_CA) # Step 2 of ipa-server-install self.master.run_command([ @@ -71,3 +99,62 @@ def test_external_ca(self): tasks.kinit_admin(self.master) result = self.master.run_command(['ipa', 'user-show', 'admin']) assert 'User login: admin' in result.stdout_text + + +class TestSelfExternalSelf(IntegrationTest): + """ + Test self-signed > external CA > self-signed test case. + """ + def test_install_master(self): + result = tasks.install_master(self.master) + assert result.returncode == 0 + + def test_switch_to_external_ca(self): + + result = self.master.run_command([paths.IPA_CACERT_MANAGE, 'renew', + '--external-ca']) + assert result.returncode == 0 + + # Sign CA, transport it to the host and get ipa a root ca paths. + root_ca_fname, ipa_ca_fname = tasks.sign_ca_and_transport( + self.master, paths.IPA_CA_CSR, ROOT_CA, IPA_CA) + + # renew CA with externally signed one + result = self.master.run_command([paths.IPA_CACERT_MANAGE, 'renew', + '--external-cert-file={}'. + format(ipa_ca_fname), + '--external-cert-file={}'. + format(root_ca_fname)]) + assert result.returncode == 0 + + # update IPA certificate databases + result = self.master.run_command([paths.IPA_CERTUPDATE]) + assert result.returncode == 0 + + # Check if external CA have "C" flag after the switch + result = check_CA_flag(self.master) + assert bool(result), ('External CA does not have "C" flag') + + def test_switch_back_to_self_signed(self): + + # for journalctl --since + switch_time = time.strftime('%H:%M:%S') + # switch back to self-signed CA + result = self.master.run_command([paths.IPA_CACERT_MANAGE, 'renew', + '--self-signed']) + assert result.returncode == 0 + + # Confirm there is no traceback in the journal + result = match_in_journal(self.master, since=switch_time, + string='Traceback') + assert not bool(result), ('"Traceback" keyword found in the journal.' + 'Please check further') + + # Check if pki-tomcatd was started after switching back. + result = match_in_journal(self.master, since=switch_time, + string=PKI_START_STR) + assert bool(result), ('pki_tomcatd not started after switching back to' + 'self-signed CA') + + result = self.master.run_command([paths.IPA_CERTUPDATE]) + assert result.returncode == 0 From 2d21d3351733584481b7b99d11f4204d458c620f Mon Sep 17 00:00:00 2001 From: Michal Reznik <mrez...@redhat.com> Date: Thu, 7 Dec 2017 14:46:06 +0100 Subject: [PATCH 4/4] tests: move CA related modules to pytest_plugins Till now both create_caless_pki.py and create_external_ca.py were stored in test_integration folder. However when trying to import e.g. "from create_external_ca import ExternalCA" from tasks.py where all other integration test`s support functions lives we get "AttributeError: module 'pytest' has no attribute 'config' as pytest was not completely initialized at the moment of the import. https://pagure.io/freeipa/issue/7302 Reviewed-By: Florence Blanc-Renaud <fren...@redhat.com> --- .../integration/create_caless_pki.py | 558 +++++++++++++++++++++ .../integration}/create_external_ca.py | 0 ipatests/test_integration/test_caless.py | 2 + 3 files changed, 560 insertions(+) create mode 100644 ipatests/pytest_plugins/integration/create_caless_pki.py rename ipatests/{test_integration => pytest_plugins/integration}/create_external_ca.py (100%) diff --git a/ipatests/pytest_plugins/integration/create_caless_pki.py b/ipatests/pytest_plugins/integration/create_caless_pki.py new file mode 100644 index 0000000000..9a2e8e26b6 --- /dev/null +++ b/ipatests/pytest_plugins/integration/create_caless_pki.py @@ -0,0 +1,558 @@ +# Copyright (c) 2015-2017, Jan Cholasta <jchol...@redhat.com> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +import collections +import datetime +import itertools +import os +import os.path +import six + +from cryptography import x509 +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import rsa +from cryptography.x509.oid import NameOID +from pyasn1.type import univ, char, namedtype, tag +from pyasn1.codec.der import encoder as der_encoder +from pyasn1.codec.native import decoder as native_decoder + +if six.PY3: + unicode = str + +DAY = datetime.timedelta(days=1) +YEAR = 365 * DAY + +# we get the variables from ca_less test +domain = None +realm = None +server1 = None +server2 = None +client = None +password = None +cert_dir = None + +CertInfo = collections.namedtuple('CertInfo', 'nick key cert counter') + + +class PrincipalName(univ.Sequence): + '''See RFC 4120 for details''' + componentType = namedtype.NamedTypes( + namedtype.NamedType( + 'name-type', + univ.Integer().subtype( + explicitTag=tag.Tag( + tag.tagClassContext, + tag.tagFormatSimple, + 0, + ), + ), + ), + namedtype.NamedType( + 'name-string', + univ.SequenceOf(char.GeneralString()).subtype( + explicitTag=tag.Tag( + tag.tagClassContext, + tag.tagFormatSimple, + 1, + ), + ), + ), + ) + + +class KRB5PrincipalName(univ.Sequence): + '''See RFC 4556 for details''' + componentType = namedtype.NamedTypes( + namedtype.NamedType( + 'realm', + char.GeneralString().subtype( + explicitTag=tag.Tag( + tag.tagClassContext, + tag.tagFormatSimple, + 0, + ), + ), + ), + namedtype.NamedType( + 'principalName', + PrincipalName().subtype( + explicitTag=tag.Tag( + tag.tagClassContext, + tag.tagFormatSimple, + 1, + ), + ), + ), + ) + + +def profile_ca(builder, ca_nick, ca): + now = datetime.datetime.utcnow() + + builder = builder.not_valid_before(now) + builder = builder.not_valid_after(now + 10 * YEAR) + + crl_uri = u'file://{}.crl'.format(os.path.join(cert_dir, ca_nick)) + + builder = builder.add_extension( + x509.KeyUsage( + digital_signature=True, + content_commitment=True, + key_encipherment=False, + data_encipherment=False, + key_agreement=False, + key_cert_sign=True, + crl_sign=True, + encipher_only=False, + decipher_only=False, + ), + critical=True, + ) + builder = builder.add_extension( + x509.BasicConstraints(ca=True, path_length=None), + critical=True, + ) + builder = builder.add_extension( + x509.CRLDistributionPoints([ + x509.DistributionPoint( + full_name=[x509.UniformResourceIdentifier(crl_uri)], + relative_name=None, + crl_issuer=None, + reasons=None, + ), + ]), + critical=False, + ) + + public_key = builder._public_key + + builder = builder.add_extension( + x509.SubjectKeyIdentifier.from_public_key(public_key), + critical=False, + ) + # here we get "ca" only for "ca1/subca" CA + if not ca: + builder = builder.add_extension( + x509.AuthorityKeyIdentifier.from_issuer_public_key(public_key), + critical=False, + ) + else: + ski = ca.cert.extensions.get_extension_for_class( + x509.SubjectKeyIdentifier) + builder = builder.add_extension( + x509.AuthorityKeyIdentifier + .from_issuer_subject_key_identifier(ski), + critical=False, + ) + return builder + + +def profile_server(builder, ca_nick, ca, + warp=datetime.timedelta(days=0), dns_name=None, + badusage=False, wildcard=False): + now = datetime.datetime.utcnow() + warp + + builder = builder.not_valid_before(now) + builder = builder.not_valid_after(now + YEAR) + + crl_uri = u'file://{}.crl'.format(os.path.join(cert_dir, ca_nick)) + + builder = builder.add_extension( + x509.CRLDistributionPoints([ + x509.DistributionPoint( + full_name=[x509.UniformResourceIdentifier(crl_uri)], + relative_name=None, + crl_issuer=None, + reasons=None, + ), + ]), + critical=False, + ) + + if dns_name is not None: + builder = builder.add_extension( + x509.SubjectAlternativeName([x509.DNSName(dns_name)]), + critical=False, + ) + + if badusage: + builder = builder.add_extension( + x509.KeyUsage( + digital_signature=False, + content_commitment=False, + key_encipherment=False, + data_encipherment=True, + key_agreement=True, + key_cert_sign=False, + crl_sign=False, + encipher_only=False, + decipher_only=False + ), + critical=False + ) + + if wildcard: + names = [x509.DNSName(u'*.' + domain)] + server_split = server1.split('.', 1) + if len(server_split) == 2 and domain != server_split[1]: + names.append(x509.DNSName(u'*.' + server_split[1])) + builder = builder.add_extension( + x509.SubjectAlternativeName(names), + critical=False, + ) + + return builder + + +def profile_kdc(builder, ca_nick, ca, + warp=datetime.timedelta(days=0), dns_name=None, + badusage=False): + now = datetime.datetime.utcnow() + warp + + builder = builder.not_valid_before(now) + builder = builder.not_valid_after(now + YEAR) + + crl_uri = u'file://{}.crl'.format(os.path.join(cert_dir, ca_nick)) + + builder = builder.add_extension( + x509.ExtendedKeyUsage([x509.ObjectIdentifier('1.3.6.1.5.2.3.5')]), + critical=False, + ) + + name = { + 'realm': realm, + 'principalName': { + 'name-type': 2, + 'name-string': ['krbtgt', realm], + }, + } + name = native_decoder.decode(name, asn1Spec=KRB5PrincipalName()) + name = der_encoder.encode(name) + + names = [x509.OtherName(x509.ObjectIdentifier('1.3.6.1.5.2.2'), name)] + if dns_name is not None: + names += [x509.DNSName(dns_name)] + + builder = builder.add_extension( + x509.SubjectAlternativeName(names), + critical=False, + ) + + builder = builder.add_extension( + x509.CRLDistributionPoints([ + x509.DistributionPoint( + full_name=[x509.UniformResourceIdentifier(crl_uri)], + relative_name=None, + crl_issuer=None, + reasons=None, + ), + ]), + critical=False, + ) + + if badusage: + builder = builder.add_extension( + x509.KeyUsage( + digital_signature=False, + content_commitment=False, + key_encipherment=False, + data_encipherment=True, + key_agreement=True, + key_cert_sign=False, + crl_sign=False, + encipher_only=False, + decipher_only=False + ), + critical=False + ) + + return builder + + +def gen_cert(profile, nick_base, subject, ca=None, **kwargs): + key = rsa.generate_private_key( + public_exponent=65537, + key_size=2048, + backend=default_backend(), + ) + public_key = key.public_key() + + counter = itertools.count(1) + + if ca is not None: + ca_nick, ca_key, ca_cert, ca_counter = ca + nick = os.path.join(ca_nick, nick_base) + issuer = ca_cert.subject + else: + nick = ca_nick = nick_base + ca_key = key + ca_counter = counter + issuer = subject + + serial = next(ca_counter) + + builder = x509.CertificateBuilder() + builder = builder.serial_number(serial) + builder = builder.issuer_name(issuer) + builder = builder.subject_name(subject) + builder = builder.public_key(public_key) + builder = profile(builder, ca_nick, ca, **kwargs) + + cert = builder.sign( + private_key=ca_key, + algorithm=hashes.SHA256(), + backend=default_backend(), + ) + + key_pem = key.private_bytes( + serialization.Encoding.PEM, + serialization.PrivateFormat.PKCS8, + serialization.BestAvailableEncryption(password.encode()), + ) + cert_pem = cert.public_bytes(serialization.Encoding.PEM) + try: + os.makedirs(os.path.dirname(os.path.join(cert_dir, nick))) + except OSError: + pass + with open(os.path.join(cert_dir, nick + '.key'), 'wb') as f: + f.write(key_pem) + with open(os.path.join(cert_dir, nick + '.crt'), 'wb') as f: + f.write(cert_pem) + + return CertInfo(nick, key, cert, counter) + + +def revoke_cert(ca, serial): + now = datetime.datetime.utcnow() + + crl_builder = x509.CertificateRevocationListBuilder() + crl_builder = crl_builder.issuer_name(ca.cert.subject) + crl_builder = crl_builder.last_update(now) + crl_builder = crl_builder.next_update(now + DAY) + + crl_filename = os.path.join(cert_dir, ca.nick + '.crl') + + try: + f = open(crl_filename, 'rb') + except IOError: + pass + else: + with f: + crl_pem = f.read() + + crl = x509.load_pem_x509_crl(crl_pem, default_backend()) + + for revoked_cert in crl: + crl_builder = crl_builder.add_revoked_certificate(revoked_cert) + + builder = x509.RevokedCertificateBuilder() + builder = builder.serial_number(serial) + builder = builder.revocation_date(now) + + revoked_cert = builder.build(default_backend()) + + crl_builder = crl_builder.add_revoked_certificate(revoked_cert) + + crl = crl_builder.sign( + private_key=ca.key, + algorithm=hashes.SHA256(), + backend=default_backend(), + ) + + crl_pem = crl.public_bytes(serialization.Encoding.PEM) + + with open(crl_filename, 'wb') as f: + f.write(crl_pem) + + +def gen_server_certs(nick_base, hostname, org, ca=None): + gen_cert(profile_server, nick_base, + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.COMMON_NAME, hostname) + ]), + ca + ) + gen_cert(profile_server, nick_base + u'-badname', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.COMMON_NAME, u'not-' + hostname) + ]), + ca + ) + gen_cert(profile_server, nick_base + u'-altname', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.COMMON_NAME, u'alt-' + hostname) + ]), + ca, dns_name=hostname + ) + gen_cert(profile_server, nick_base + u'-expired', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, + u'Expired'), + x509.NameAttribute(NameOID.COMMON_NAME, hostname) + ]), + ca, warp=-2 * YEAR + ) + gen_cert(profile_server, nick_base + u'-badusage', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, + u'Bad Usage'), + x509.NameAttribute(NameOID.COMMON_NAME, hostname) + ]), + ca, badusage=True + ) + revoked = gen_cert(profile_server, nick_base + u'-revoked', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, + u'Revoked'), + x509.NameAttribute(NameOID.COMMON_NAME, hostname) + ]), + ca + ) + revoke_cert(ca, revoked.cert.serial_number) + + +def gen_kdc_certs(nick_base, hostname, org, ca=None): + gen_cert(profile_kdc, nick_base + u'-kdc', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'KDC'), + x509.NameAttribute(NameOID.COMMON_NAME, hostname) + ]), + ca + ) + gen_cert(profile_kdc, nick_base + u'-kdc-badname', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'KDC'), + x509.NameAttribute(NameOID.COMMON_NAME, u'not-' + hostname) + ]), + ca + ) + gen_cert(profile_kdc, nick_base + u'-kdc-altname', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'KDC'), + x509.NameAttribute(NameOID.COMMON_NAME, u'alt-' + hostname) + ]), + ca, dns_name=hostname + ) + gen_cert(profile_kdc, nick_base + u'-kdc-expired', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, + u'Expired KDC'), + x509.NameAttribute(NameOID.COMMON_NAME, hostname) + ]), + ca, warp=-2 * YEAR + ) + gen_cert(profile_kdc, nick_base + u'-kdc-badusage', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, + u'Bad Usage KDC'), + x509.NameAttribute(NameOID.COMMON_NAME, hostname) + ]), + ca, badusage=True + ) + revoked = gen_cert(profile_kdc, nick_base + u'-kdc-revoked', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, + u'Revoked KDC'), + x509.NameAttribute(NameOID.COMMON_NAME, hostname) + ]), + ca + ) + revoke_cert(ca, revoked.cert.serial_number) + + +def gen_subtree(nick_base, org, ca=None): + subca = gen_cert(profile_ca, nick_base, + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.COMMON_NAME, u'CA') + ]), + ca + ) + gen_cert(profile_server, u'wildcard', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.COMMON_NAME, u'*.' + domain) + ]), + subca, wildcard=True + ) + gen_server_certs(u'server', server1, org, subca) + gen_server_certs(u'replica', server2, org, subca) + gen_server_certs(u'client', client, org, subca) + gen_cert(profile_kdc, u'kdcwildcard', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, org), + x509.NameAttribute(NameOID.COMMON_NAME, u'*.' + domain) + ]), + subca + ) + gen_kdc_certs(u'server', server1, org, subca) + gen_kdc_certs(u'replica', server2, org, subca) + gen_kdc_certs(u'client', client, org, subca) + return subca + + +def create_pki(): + + gen_cert(profile_server, u'server-selfsign', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Self-signed'), + x509.NameAttribute(NameOID.COMMON_NAME, server1) + ]) + ) + gen_cert(profile_server, u'replica-selfsign', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Self-signed'), + x509.NameAttribute(NameOID.COMMON_NAME, server2) + ]) + ) + gen_cert(profile_server, u'noca', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'No-CA'), + x509.NameAttribute(NameOID.COMMON_NAME, server1) + ]) + ) + gen_cert(profile_kdc, u'server-kdc-selfsign', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Self-signed'), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'KDC'), + x509.NameAttribute(NameOID.COMMON_NAME, server1) + ]) + ) + gen_cert(profile_kdc, u'replica-kdc-selfsign', + x509.Name([ + x509.NameAttribute(NameOID.ORGANIZATION_NAME, u'Self-signed'), + x509.NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, u'KDC'), + x509.NameAttribute(NameOID.COMMON_NAME, server2) + ]) + ) + ca1 = gen_subtree(u'ca1', u'Example Organization') + gen_subtree(u'subca', u'Subsidiary Example Organization', ca1) + gen_subtree(u'ca2', u'Other Example Organization') + ca3 = gen_subtree(u'ca3', u'Unknown Organization') + os.unlink(os.path.join(cert_dir, ca3.nick + '.key')) + os.unlink(os.path.join(cert_dir, ca3.nick + '.crt')) diff --git a/ipatests/test_integration/create_external_ca.py b/ipatests/pytest_plugins/integration/create_external_ca.py similarity index 100% rename from ipatests/test_integration/create_external_ca.py rename to ipatests/pytest_plugins/integration/create_external_ca.py diff --git a/ipatests/test_integration/test_caless.py b/ipatests/test_integration/test_caless.py index 041f09f3bb..b06c506d8a 100644 --- a/ipatests/test_integration/test_caless.py +++ b/ipatests/test_integration/test_caless.py @@ -32,6 +32,8 @@ from ipapython.dn import DN from ipatests.test_integration.base import IntegrationTest from ipatests.pytest_plugins.integration import tasks +from ipatests.pytest_plugins.integration.create_external_ca import ExternalCA +from ipatests.pytest_plugins.integration import create_caless_pki from ipalib.constants import DOMAIN_LEVEL_0 _DEFAULT = object()
_______________________________________________ FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org