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 0db599ed71fbabcaacff0082eb369b2a737df866 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 1a8d34da39090d948447d8cb355d01513c434bdf 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

Add optional key fips_mode to Env object in tests.

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

diff --git a/ipatests/test_ipalib/test_config.py b/ipatests/test_ipalib/test_config.py
index 1df9a39..53b60ef 100644
--- a/ipatests/test_ipalib/test_config.py
+++ b/ipatests/test_ipalib/test_config.py
@@ -562,6 +562,7 @@ def test_finalize_core(self):
 
         # Test using DEFAULT_CONFIG:
         defaults = dict(constants.DEFAULT_CONFIG)
+        defaults['fips_mode'] = object
         (o, home) = self.finalize_core(None, **defaults)
         assert list(o) == sorted(defaults)
         for (key, value) in defaults.items():

From 5c3bab0961e871dd332fd89a2e876ed2deeed803 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 0d3a69f..783a716 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -512,6 +512,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()
 
@@ -524,7 +531,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 e5bc6ff9cfee1f4686b2ead0ab05e2650379d738 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 783a716..216ed55 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
@@ -511,29 +512,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):
@@ -745,6 +754,7 @@ def install_check(installer):
                          ldap_uri=ldapuri)
     remote_api.finalize()
     installer._remote_api = remote_api
+
     conn = remote_api.Backend.ldap2
     replman = None
     try:
@@ -1083,7 +1093,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 28c57e48423e77756eb152068db44933cd0540f7 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 | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index 216ed55..e8b8185 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -529,6 +529,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
@@ -1095,6 +1116,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