On Mon 01 Apr 2013 10:01:14 PM CEST, Rob Crittenden wrote:
Tomas Babej wrote:
On Tue 19 Feb 2013 08:37:26 PM CET, Rob Crittenden wrote:
Tomas Babej wrote:
On 02/04/2013 04:21 PM, Rob Crittenden wrote:
Tomas Babej wrote:
On 01/30/2013 05:12 PM, Tomas Babej wrote:
Hi,

The checks make sure that SELinux is:
  - installed and enabled (on server install)
  - installed and enabled OR not installed (on client install)

Please note that client installs with SELinux not installed are
allowed since freeipa-client package has no dependency on SELinux.
(any objections to this approach?)

The (unsupported) option --allow-no-selinux has been added. It can
used to bypass the checks.

Parts of platform-dependant code were refactored to use newly added
is_selinux_enabled() function.

https://fedorahosted.org/freeipa/ticket/3359

Tomas

I forgot to edit the man pages. Thanks Rob!

Updated patch attached.

Tomas

After a bit of off-line discussion I don't think we're quite ready
yet
to require SELinux by default on client installations (even with a
flag to work around it). The feeling is this would be disruptive to
existing automation.

Can you still do the check but not enforce it, simply display a big
warning if SELinux is disabled?

rob


Sure, here is the updated patch.

I edited the commit message, RFE description and man pages
according to
the new behaviour.

Tomas

The patch looks good, I'm just wondering about one thing. The default
value for is_selinux_enabled() is True in ipapython/services.py.in.

So this means that any non-Red Hat/non-Fedora system, by default, is
going to assume that SELinux is enabled.

My hesitation has to when we call check_selinux_status(). It may
incorrectly error out. I suspect that the user would have to work
around this using --allow-selinux-disabled but this wouldn't make a
lot of sense since they actually do have SELinux disabled.

Yes, you're right. And the error message would not even be helpful since
it would tell the user to install policycoreutils package. This would be
the
case both with server and client installs when selinux would not be
installed
at all.

What do you think?

rob

Well we have 2 options as I see it:

1.) We can either return None as default, and add checks to
check_selinux_status, restore_context and install scripts that would
ensure that we behave properly when is_selinux_enabled() is not
implemented.

2.) We can remove the default value, since it would cause forementioned
crash and add comment that this function needs to be implemented
properly in every platform file.

I'm probably for option 2, there's no need to clutter the code with
checks
that compensate for improper platform file implementations.

Tomas

I agree with you on option 2.

rob

I updated the patch accordingly.

Tomas
>From 1d8d6b6315d109e936464aac4ee23d35bcd3d84f Mon Sep 17 00:00:00 2001
From: Tomas Babej <tba...@redhat.com>
Date: Thu, 24 Jan 2013 15:37:21 -0500
Subject: [PATCH] Add checks for SELinux in install scripts

The checks make sure that SELinux is:
  - installed and enabled, otherwise the installation aborts
    (on server install)
  - installed and enabled OR not installed, otherwise
    the warning message is displayed (on client install)

The (unsupported) option --allow-selinux-disabled has been added. It can
used to bypass the checks. Documented in man pages altered accordingly.

Parts of platform-dependant code were refactored to use newly added
is_selinux_enabled() function.

https://fedorahosted.org/freeipa/ticket/3359
---
 install/tools/ipa-server-install          | 11 +++++++
 install/tools/man/ipa-server-install.1    |  3 ++
 ipa-client/ipa-install/ipa-client-install | 17 ++++++++++
 ipa-client/man/ipa-client-install.1       |  3 ++
 ipapython/platform/fedora16/__init__.py   |  3 +-
 ipapython/platform/fedora16/selinux.py    |  3 ++
 ipapython/platform/fedora18/__init__.py   |  3 +-
 ipapython/platform/redhat/__init__.py     | 53 +++++++++++++++++--------------
 ipapython/services.py.in                  |  7 ++++
 9 files changed, 78 insertions(+), 25 deletions(-)

diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index a289941e43acb52fc30bbf3750652f0868e92651..483665b1b3e50996f5a6db30819f57dff53db8e2 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -159,6 +159,8 @@ def parse_options():
                       help="do not configure OpenSSH client")
     basic_group.add_option("--no-sshd", dest="conf_sshd", default=True, action="store_false",
                       help="do not configure OpenSSH server")
+    basic_group.add_option("--allow-selinux-disabled", dest="selinux_disabled", action="store_true",
+                      default=False, help="allow installation with SELinux disabled (not supported)")
     basic_group.add_option("-d", "--debug", dest="debug", action="store_true",
                       default=False, help="print debugging information")
     basic_group.add_option("-U", "--unattended", dest="unattended", action="store_true",
@@ -645,6 +647,13 @@ def main():
             print "CA is not installed yet. To install with an external CA is a two-stage process.\nFirst run the installer with --external-ca."
             sys.exit(1)
 
+    is_selinux_disabled = not ipaservices.is_selinux_enabled()
+    if (not options.selinux_disabled) and is_selinux_disabled:
+        print("Installation with SELinux disabled is not supported. \n"
+              "Put SELinux either in permissive / enabled mode or use"
+              " --allow-selinux-disabled option.")
+        sys.exit(1)
+
     # This will override any settings passed in on the cmdline
     if ipautil.file_exists(ANSWER_CACHE):
         if options.dm_password is not None:
@@ -1145,6 +1154,8 @@ def main():
             args.append("--no-dns-sshfp")
         if options.trust_sshfp:
             args.append("--ssh-trust-dns")
+        if options.selinux_disabled:
+            args.append("--allow-selinux-disabled")
         if not options.conf_ssh:
             args.append("--no-ssh")
         if not options.conf_sshd:
diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
index 7460868e328a40f7f07f7ea753f499d9dda1e45f..7300757e67fbe857595f3fbeed4f960d13902d27 100644
--- a/install/tools/man/ipa-server-install.1
+++ b/install/tools/man/ipa-server-install.1
@@ -75,6 +75,9 @@ Do not configure OpenSSH client.
 \fB\-\-no\-sshd\fR
 Do not configure OpenSSH server.
 .TP
+\fB\-\-allow\-selinux\-disabled\fR
+Allow installation with SELinux disabled. This is unsupported. Please consider setting SELinux to permissive / enforcing mode.
+.TP
 \fB\-d\fR, \fB\-\-debug\fR
 Enable debug logging when more verbose output is needed
 .TP
diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index 6be4a90132792dceede92445360f741e397ae9ba..0c9cc176aaff2fd8c23e551560d6e655e0cd5d48 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -130,6 +130,8 @@ def parse_options():
                       help="do not automatically create DNS SSHFP records")
     basic_group.add_option("--noac", dest="no_ac", default=False, action="store_true",
                       help="do not use Authconfig to modify the nsswitch.conf and PAM configuration")
+    basic_group.add_option("--allow-selinux-disabled", dest="selinux_disabled", action="store_true",
+                      default=False, help="supress warning message when SELinux is disabled")
     basic_group.add_option("-f", "--force", dest="force", action="store_true",
                       default=False, help="force setting of LDAP/Kerberos conf")
     basic_group.add_option("-d", "--debug", dest="debug", action="store_true",
@@ -2387,7 +2389,9 @@ def main():
 
     if not os.getegid() == 0:
         sys.exit("\nYou must be root to run ipa-client-install.\n")
+
     ipaservices.check_selinux_status()
+
     logging_setup(options)
     root_logger.debug(
         '%s was invoked with options: %s', sys.argv[0], safe_options)
@@ -2411,6 +2415,19 @@ def main():
             "using 'ipa-client-install --uninstall'.")
         return CLIENT_ALREADY_CONFIGURED
 
+    # We want to allow clients with no SELinux installed, therefore use
+    # is_selinux_enabled with allow_not_installed flag set to true
+    is_selinux_disabled = not ipaservices.is_selinux_enabled(
+                                  allow_not_installed=True)
+
+    if (not options.selinux_disabled) and is_selinux_disabled:
+        root_logger.warning("Installation with SELinux disabled is not "
+                            "recommended.")
+        root_logger.warning("Putting SELinux either in permissive/enabled mode "
+                            "is advised for higher security.")
+        root_logger.info("To supress this warning message, use "
+                         "--allow-selinux-disabled option.")
+
     rval = install(options, env, fstore, statestore)
     if rval == CLIENT_INSTALL_ERROR:
         if options.force:
diff --git a/ipa-client/man/ipa-client-install.1 b/ipa-client/man/ipa-client-install.1
index d98318eeda1d6b60d4a6bcb1321db03bfabe15a8..1495aadc7d5199853812ac43f975305d33b86477 100644
--- a/ipa-client/man/ipa-client-install.1
+++ b/ipa-client/man/ipa-client-install.1
@@ -106,6 +106,9 @@ Do not configure OpenSSH client.
 \fB\-\-no\-sshd\fR
 Do not configure OpenSSH server.
 .TP
+\fB\-\-allow\-selinux\-disabled\fR
+Supress warning message about disabled SELinux.
+.TP
 \fB\-\-no\-dns\-sshfp\fR
 Do not automatically create DNS SSHFP records.
 .TP
diff --git a/ipapython/platform/fedora16/__init__.py b/ipapython/platform/fedora16/__init__.py
index 26a6afd286f83f7c2781f1edf3e80fec8ebff06e..36a1baa67bf692678cdc1f48f23a801557086ab3 100644
--- a/ipapython/platform/fedora16/__init__.py
+++ b/ipapython/platform/fedora16/__init__.py
@@ -38,7 +38,7 @@ from ipapython.platform.fedora16.service import f16_service, Fedora16Services
 #                         and restorecon is installed.
 __all__ = ['authconfig', 'service', 'knownservices',
     'backup_and_replace_hostname', 'restore_context', 'check_selinux_status',
-    'restore_network_configuration', 'timedate_services']
+    'restore_network_configuration', 'timedate_services','is_selinux_enabled']
 
 # Just copy a referential list of timedate services
 timedate_services = list(base.timedate_services)
@@ -49,4 +49,5 @@ knownservices = Fedora16Services()
 backup_and_replace_hostname = redhat.backup_and_replace_hostname
 restore_context = selinux.restore_context
 check_selinux_status = selinux.check_selinux_status
+is_selinux_enabled = selinux.is_selinux_enabled
 restore_network_configuration = redhat.restore_network_configuration
diff --git a/ipapython/platform/fedora16/selinux.py b/ipapython/platform/fedora16/selinux.py
index cf71a38e43355420b5ff7fbedbfea6e9e82c2d1c..70ac9fbbaf694937197c06b17110069df17fea14 100644
--- a/ipapython/platform/fedora16/selinux.py
+++ b/ipapython/platform/fedora16/selinux.py
@@ -24,3 +24,6 @@ def restore_context(filepath, restorecon='/usr/sbin/restorecon'):
 
 def check_selinux_status(restorecon='/usr/sbin/restorecon'):
     return redhat.check_selinux_status(restorecon)
+
+def is_selinux_enabled(allow_not_installed=False):
+    return redhat.is_selinux_enabled(allow_not_installed=allow_not_installed)
diff --git a/ipapython/platform/fedora18/__init__.py b/ipapython/platform/fedora18/__init__.py
index d12bdcad5eb53881db5fe94cef97f2fafe2c6442..09f8207ec72906e41a125b3a1037c5f2397626e1 100644
--- a/ipapython/platform/fedora18/__init__.py
+++ b/ipapython/platform/fedora18/__init__.py
@@ -44,7 +44,7 @@ from ipapython.platform import fedora16, base
 #                         and restorecon is installed.
 __all__ = ['authconfig', 'service', 'knownservices',
     'backup_and_replace_hostname', 'restore_context', 'check_selinux_status',
-    'restore_network_configuration', 'timedate_services']
+    'restore_network_configuration', 'timedate_services','is_selinux_enabled']
 
 # Just copy a referential list of timedate services
 timedate_services = list(base.timedate_services)
@@ -111,3 +111,4 @@ service = fedora16.service
 knownservices = fedora16.knownservices
 restore_context = fedora16.restore_context
 check_selinux_status = fedora16.check_selinux_status
+is_selinux_enabled = fedora16.is_selinux_enabled
diff --git a/ipapython/platform/redhat/__init__.py b/ipapython/platform/redhat/__init__.py
index f7680e7ec510d3a2fde4febc88be15fe8d9f98d5..135d3628ed9b908a88c30bd0e6f00d1fc3ff5cf0 100644
--- a/ipapython/platform/redhat/__init__.py
+++ b/ipapython/platform/redhat/__init__.py
@@ -48,7 +48,7 @@ from ipapython.platform.redhat.service import redhat_service, RedHatServices
 #                         and restorecon is installed.
 __all__ = ['authconfig', 'service', 'knownservices',
     'backup_and_replace_hostname', 'restore_context', 'check_selinux_status',
-    'restore_network_configuration', 'timedate_services']
+    'restore_network_configuration', 'timedate_services','is_selinux_enabled']
 
 # Just copy a referential list of timedate services
 timedate_services = list(base.timedate_services)
@@ -67,17 +67,8 @@ def restore_context(filepath, restorecon='/sbin/restorecon'):
 
     ipautil.run() will do the logging.
     """
-    try:
-        if (os.path.exists('/usr/sbin/selinuxenabled')):
-            ipautil.run(["/usr/sbin/selinuxenabled"])
-        else:
-            # No selinuxenabled, no SELinux
-            return
-    except ipautil.CalledProcessError:
-        # selinuxenabled returns 1 if not enabled
-        return
 
-    if (os.path.exists(restorecon)):
+    if is_selinux_enabled() and os.path.exists(restorecon):
         ipautil.run([restorecon, filepath], raiseonerr=False)
 
 def backup_and_replace_hostname(fstore, statestore, hostname):
@@ -114,18 +105,34 @@ def check_selinux_status(restorecon='/sbin/restorecon'):
     This function returns nothing but may raise a Runtime exception
     if SELinux is enabled but restorecon is not available.
     """
-    try:
-        if (os.path.exists('/usr/sbin/selinuxenabled')):
-            ipautil.run(["/usr/sbin/selinuxenabled"])
-        else:
-            # No selinuxenabled, no SELinux
-            return
-    except ipautil.CalledProcessError:
-        # selinuxenabled returns 1 if not enabled
-        return
-
-    if not os.path.exists(restorecon):
-        raise RuntimeError('SELinux is enabled but %s does not exist.\nInstall the policycoreutils package and start the installation again.' % restorecon)
+
+    if is_selinux_enabled() and not os.path.exists(restorecon):
+        raise RuntimeError('SELinux is enabled but %s does not exist.\n'
+            'Install the policycoreutils package and start the installation'
+            ' again.' % restorecon)
+
+def is_selinux_enabled(allow_not_installed=False):
+    """"
+    Checks if SELinux is enabled.
+
+    If allow_not_installed is set to True, returns true if and only if SELinux
+    is installed and enabled.
+    With allow_not_installed set to False, returns true if and only if SELinux
+    is installed and enabled, or not installed at all.
+    """
+
+    if os.path.exists('/usr/sbin/selinuxenabled'):
+        (stdout, stderr, rc) = ipautil.run(['/usr/sbin/selinuxenabled'],
+                                           raiseonerr=False,
+                                           capture_output=False)
+    elif allow_not_installed:
+        # SELinux is not required on client installs
+        # Assume that we are on the client with no SELinux
+        return True
+    else:
+        return False
+
+    return (rc == 0)
 
 def restore_network_configuration(fstore, statestore):
     filepath = '/etc/sysconfig/network'
diff --git a/ipapython/services.py.in b/ipapython/services.py.in
index 16b62ca8508d4078e896cd1da6fd664f52a3930e..2cf7619337da2296ddba84ca94476ef2390688e6 100644
--- a/ipapython/services.py.in
+++ b/ipapython/services.py.in
@@ -51,6 +51,13 @@ backup_and_replace_hostname = backup_and_replace_hostname_default
 def check_selinux_status():
     return
 
+# Check if SELinux is installed and enabled (with allow_not_installed=False)
+# or installed and enabled OR not installed (with allow_not_installed=True)
+# Platforms that support SELinux should implement this function.
+# Defaults to passing the check
+def is_selinux_enabled(allow_not_installed=False):
+    return True
+
 from ipapython.platform.base import SVC_LIST_FILE
 def get_svc_list_file():
     return SVC_LIST_FILE
-- 
1.7.11.7

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to