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

Reply via email to