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