URL: https://github.com/freeipa/freeipa/pull/437
Author: tomaskrizek
 Title: #437: FIPS: replica install check
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/437/head:pr437
git checkout pr437
From 85cd763e945167db48a675fead0d1bcf29c57440 Mon Sep 17 00:00:00 2001
From: Tomas Krizek <tkri...@redhat.com>
Date: Mon, 6 Feb 2017 13:08:11 +0100
Subject: [PATCH 1/5] Add fips_mode variable to env

Variable fips_mode indicating whether machine is running in
FIPS-enabled mode was added to env.

https://fedorahosted.org/freeipa/ticket/5695
---
 ipalib/config.py | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/ipalib/config.py b/ipalib/config.py
index 20591db..c7caeef 100644
--- a/ipalib/config.py
+++ b/ipalib/config.py
@@ -44,6 +44,10 @@
 from ipalib.constants import CONFIG_SECTION
 from ipalib.constants import OVERRIDE_ERROR, SET_ERROR, DEL_ERROR
 from ipalib import errors
+try:
+    from ipaplatform.tasks import tasks
+except ImportError:
+    tasks = None
 
 if six.PY3:
     unicode = str
@@ -440,6 +444,10 @@ def _bootstrap(self, **overrides):
         self.bin = path.dirname(self.script)
         self.home = os.environ.get('HOME', None)
 
+        # Set fips_mode only if ipaplatform module was loaded
+        if tasks is not None:
+            self.fips_mode = tasks.is_fips_enabled()
+
         # Merge in overrides:
         self._merge(**overrides)
 

From 131f4108b101c700d6f98b401e63b03396bd4886 Mon Sep 17 00:00:00 2001
From: Tomas Krizek <tkri...@redhat.com>
Date: Wed, 8 Feb 2017 16:53:44 +0100
Subject: [PATCH 2/5] test_config: fix tests for env.fips_mode

Remove optional key fips_mode from Env object.

https://fedorahosted.org/freeipa/ticket/5695
---
 ipatests/test_ipalib/test_config.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ipatests/test_ipalib/test_config.py b/ipatests/test_ipalib/test_config.py
index 1df9a39..095f188 100644
--- a/ipatests/test_ipalib/test_config.py
+++ b/ipatests/test_ipalib/test_config.py
@@ -563,7 +563,7 @@ def test_finalize_core(self):
         # Test using DEFAULT_CONFIG:
         defaults = dict(constants.DEFAULT_CONFIG)
         (o, home) = self.finalize_core(None, **defaults)
-        assert list(o) == sorted(defaults)
+        assert set(o).issuperset(set(defaults))
         for (key, value) in defaults.items():
             if value is object:
                 continue

From 5410a14a59cdd2e0340ee6936f2ca641b55392c1 Mon Sep 17 00:00:00 2001
From: Tomas Krizek <tkri...@redhat.com>
Date: Mon, 6 Feb 2017 17:17:49 +0100
Subject: [PATCH 3/5] check_remote_version: update exception and docstring

Refactor function to use ScriptError exception and provide docstring.
---
 ipaserver/install/server/replicainstall.py | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index 7d7a499..ad43aa2 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -509,6 +509,13 @@ def promote_openldap_conf(hostname, master):
 
 
 def check_remote_version(api):
+    """
+    Perform a check to verify remote server's version
+
+    :param api: remote API
+
+    :raises: ``ScriptError`` if the checks fails
+    """
     client = rpc.jsonclient(api)
     client.finalize()
 
@@ -521,7 +528,7 @@ def check_remote_version(api):
     remote_version = parse_version(env['version'])
     api_version = parse_version(api.env.version)
     if remote_version > api_version:
-        raise RuntimeError(
+        raise ScriptError(
             "Cannot install replica of a server of higher version ({}) than"
             "the local version ({})".format(remote_version, api_version))
 

From ecac6ac6cb879e2f5f392a6fa243e40faf5f1117 Mon Sep 17 00:00:00 2001
From: Tomas Krizek <tkri...@redhat.com>
Date: Tue, 7 Feb 2017 10:42:54 +0100
Subject: [PATCH 4/5] replicainstall: add context manager for rpc client

Abstract creating rpc client into a context manager to allow re-use.
---
 ipaserver/install/server/replicainstall.py | 33 ++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index ad43aa2..4a8b9d6 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -4,6 +4,7 @@
 
 from __future__ import print_function
 
+import contextlib
 import dns.exception as dnsexception
 import dns.name as dnsname
 import dns.resolver as dnsresolver
@@ -508,29 +509,37 @@ def promote_openldap_conf(hostname, master):
         root_logger.info("Failed to update {}: {}".format(ldap_conf, e))
 
 
-def check_remote_version(api):
+@contextlib.contextmanager
+def rpc_client(api):
     """
-    Perform a check to verify remote server's version
+    Context manager for JSON RPC client.
 
-    :param api: remote API
-
-    :raises: ``ScriptError`` if the checks fails
+    :param api: api to initiate the RPC client
     """
     client = rpc.jsonclient(api)
     client.finalize()
-
     client.connect()
+
     try:
-        env = client.forward(u'env', u'version')['result']
+        yield client
     finally:
         client.disconnect()
 
+
+def check_remote_version(client, local_version):
+    """
+    Verify remote server's version is not higher than this server's version
+
+    :param client: RPC client
+    :param local_version: API version of local server
+    :raises: ScriptError: if the checks fails
+    """
+    env = client.forward(u'env', u'version')['result']
     remote_version = parse_version(env['version'])
-    api_version = parse_version(api.env.version)
-    if remote_version > api_version:
+    if remote_version > local_version:
         raise ScriptError(
             "Cannot install replica of a server of higher version ({}) than"
-            "the local version ({})".format(remote_version, api_version))
+            "the local version ({})".format(remote_version, local_version))
 
 
 def common_check(no_ntp):
@@ -754,6 +763,7 @@ def install_check(installer):
                          ldap_uri=ldapuri)
     remote_api.finalize()
     installer._remote_api = remote_api
+
     conn = remote_api.Backend.ldap2
     replman = None
     try:
@@ -1086,7 +1096,8 @@ def promote_check(installer):
     remote_api.finalize()
     installer._remote_api = remote_api
 
-    check_remote_version(remote_api)
+    with rpc_client(remote_api) as client:
+        check_remote_version(client, api.env.version)
 
     conn = remote_api.Backend.ldap2
     replman = None

From 3c816db3ba6460c5fe86b40b525b656ab55814a1 Mon Sep 17 00:00:00 2001
From: Tomas Krizek <tkri...@redhat.com>
Date: Tue, 7 Feb 2017 12:00:09 +0100
Subject: [PATCH 5/5] FIPS: perform replica installation check

Check status of remote server's FIPS mode and proceed with
installation only if it matches the current replica's FIPS mode.

https://fedorahosted.org/freeipa/ticket/5695
---
 ipaserver/install/server/replicainstall.py | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index 4a8b9d6..99595f4 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -526,6 +526,27 @@ def rpc_client(api):
         client.disconnect()
 
 
+def check_remote_fips_mode(client, local_fips_mode):
+    """
+    Verify remote server's fips-mode is the same as this server's fips-mode
+
+    :param client: RPC client
+    :param local_fips_mode: boolean indicating whether FIPS mode is turned on
+    :raises: ScriptError: if the checks fails
+    """
+    env = client.forward(u'env', u'fips_mode')['result']
+    remote_fips_mode = env.get('fips_mode', False)
+    if local_fips_mode != remote_fips_mode:
+        if local_fips_mode:
+            raise ScriptError(
+                "Cannot join FIPS-enabled replica into existing topology: "
+                "FIPS is not enabled on the master server.")
+        else:
+            raise ScriptError(
+                "Cannot join replica into existing FIPS-enabled topology: "
+                "FIPS has to be enabled locally first.")
+
+
 def check_remote_version(client, local_version):
     """
     Verify remote server's version is not higher than this server's version
@@ -675,6 +696,9 @@ def install_check(installer):
     filename = installer.replica_file
     installer._enrollment_performed = False
 
+    if api.env.fips_mode:
+        raise ScriptError("FIPS is not supported in domain level 0")
+
     # check FIPS, selinux status, http and DS ports, NTP conflicting services
     common_check(options.no_ntp)
 
@@ -1098,6 +1122,7 @@ def promote_check(installer):
 
     with rpc_client(remote_api) as client:
         check_remote_version(client, api.env.version)
+        check_remote_fips_mode(client, api.env.fips_mode)
 
     conn = remote_api.Backend.ldap2
     replman = None
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to