URL: https://github.com/freeipa/freeipa/pull/1581
Author: Rezney
 Title: #1581: [Backport][ipa-4-5]- Ca > ext  > ca backport-4-6
Action: opened

PR body:
"""
Backport of https://github.com/freeipa/freeipa/pull/1372

"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/1581/head:pr1581
git checkout pr1581
From 7e69ea7fe118aeb2a9d2f765fcccf4b496da43cf 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 3b39fe5487..2b21eceb76 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 b2ed6af5adaf082dd93afdebd564f56c3650d348 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 d9ba187d92..f2789a11ca 100644
--- a/ipatests/pytest_plugins/integration/tasks.py
+++ b/ipatests/pytest_plugins/integration/tasks.py
@@ -42,6 +42,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
 
@@ -1382,3 +1383,30 @@ def add_dns_zone(master, zone, skip_overlap_check=False,
                                     host.hostname + ".", '--a-rec', host.ip])
     else:
         logger.debug('Zone %s already added.', zone)
+
+
+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 2842f63b4beefcc580402decdb57160f3167d428 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 8fcc90b481b36a4525f15b4a450793b604807d91 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                                 | 0
 .../integration}/create_external_ca.py                                | 0
 ipatests/test_integration/test_caless.py                              | 4 ++--
 3 files changed, 2 insertions(+), 2 deletions(-)
 rename ipatests/{test_integration => pytest_plugins/integration}/create_caless_pki.py (100%)
 rename ipatests/{test_integration => pytest_plugins/integration}/create_external_ca.py (100%)

diff --git a/ipatests/test_integration/create_caless_pki.py b/ipatests/pytest_plugins/integration/create_caless_pki.py
similarity index 100%
rename from ipatests/test_integration/create_caless_pki.py
rename to ipatests/pytest_plugins/integration/create_caless_pki.py
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 09973dd1f8..36592af5d7 100644
--- a/ipatests/test_integration/test_caless.py
+++ b/ipatests/test_integration/test_caless.py
@@ -32,9 +32,9 @@
 from ipaplatform.paths import paths
 from ipapython.dn import DN
 from ipatests.test_integration.base import IntegrationTest
-from ipatests.test_integration import create_caless_pki
-from ipatests.test_integration.create_external_ca import ExternalCA
 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
 
 if six.PY3:
_______________________________________________
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