diff options
-rw-r--r-- | ipaplatform/base/tasks.py | 19 | ||||
-rw-r--r-- | ipaplatform/fedora/tasks.py | 53 | ||||
-rw-r--r-- | ipapython/errors.py | 47 | ||||
-rw-r--r-- | ipaserver/install/adtrustinstance.py | 62 | ||||
-rw-r--r-- | ipaserver/install/httpinstance.py | 90 |
5 files changed, 152 insertions, 119 deletions
diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py index a4ef0ded0..408447e43 100644 --- a/ipaplatform/base/tasks.py +++ b/ipaplatform/base/tasks.py @@ -132,4 +132,23 @@ class BaseTaskNamespace(object): return + def set_selinux_booleans(self, required_settings, backup_func=None): + """Set the specified SELinux booleans + + :param required_settings: A dictionary mapping the boolean names + to desired_values. + The desired value can be 'on' or 'off'. + + :param backup_func: A function called for each boolean with two + arguments: the name and the previous value + + If SELinux is disabled, return False; on success returns True. + + If setting the booleans fails, + an ipapython.errors.SetseboolError is raised. + """ + + return + + task_namespace = BaseTaskNamespace() diff --git a/ipaplatform/fedora/tasks.py b/ipaplatform/fedora/tasks.py index 926c0ea66..9f4a76b82 100644 --- a/ipaplatform/fedora/tasks.py +++ b/ipaplatform/fedora/tasks.py @@ -24,7 +24,6 @@ This module contains default Fedora-specific implementations of system tasks. ''' import os -import shutil import stat import socket import sys @@ -35,8 +34,9 @@ from subprocess import CalledProcessError from nss.error import NSPRError from pyasn1.error import PyAsn1Error -from ipapython.ipa_log_manager import root_logger +from ipapython.ipa_log_manager import root_logger, log_mgr from ipapython import ipautil +import ipapython.errors from ipalib import x509 # FIXME: do not import from ipalib @@ -45,6 +45,9 @@ from ipaplatform.fedora.authconfig import FedoraAuthConfig from ipaplatform.base.tasks import BaseTaskNamespace +log = log_mgr.get_logger(__name__) + + class FedoraTaskNamespace(BaseTaskNamespace): def restore_context(self, filepath, restorecon=paths.SBIN_RESTORECON): @@ -326,4 +329,50 @@ class FedoraTaskNamespace(BaseTaskNamespace): except OSError: pass + def set_selinux_booleans(self, required_settings, backup_func=None): + def get_setsebool_args(changes): + args = [paths.SETSEBOOL, "-P"] + args.extend(["%s=%s" % update for update in changes.iteritems()]) + + return args + + if (os.path.exists(paths.SELINUXENABLED)): + try: + ipautil.run([paths.SELINUXENABLED]) + except ipautil.CalledProcessError: + # selinuxenabled returns 1 if not enabled + return False + else: + return False + + updated_vars = {} + failed_vars = {} + for setting, state in required_settings.iteritems(): + try: + (stdout, stderr, rc) = ipautil.run([paths.GETSEBOOL, setting]) + original_state = stdout.split()[2] + if backup_func is not None: + backup_func(setting, original_state) + + if original_state != state: + updated_vars[setting] = state + except ipautil.CalledProcessError, e: + log.error("Cannot get SELinux boolean '%s': %s", setting, e) + failed_vars[setting] = state + + if updated_vars: + args = get_setsebool_args(updated_vars) + try: + ipautil.run(args) + except ipautil.CalledProcessError: + failed_vars.update(updated_vars) + + if failed_vars: + raise ipapython.errors.SetseboolError( + failed=failed_vars, + command=' '.join(get_setsebool_args(failed_vars))) + + return True + + tasks = FedoraTaskNamespace() diff --git a/ipapython/errors.py b/ipapython/errors.py new file mode 100644 index 000000000..9fc28359c --- /dev/null +++ b/ipapython/errors.py @@ -0,0 +1,47 @@ +# Authors: Petr Viktorin <pviktori@redhat.com> +# +# Copyright (C) 2014 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. +# + + +class SetseboolError(StandardError): + """Raised when setting a SELinux boolean fails + + :param failed: Dictionary mapping boolean names to intended values + to their intended values, for booleans that cound not be set + :param command: Command the user can run to set the booleans + + The initializer arguments are copied to attributes of the same name. + """ + def __init__(self, failed, command): + message = "Could not set SELinux booleans: %s" % ' '.join( + '%s=%s' % (name, value) for name, value in failed.items()) + super(SetseboolError, self).__init__(message) + self.failed = failed + self.command = command + + def format_service_warning(self, service_name): + """Format warning for display when this is raised from service install + """ + return '\n'.join([ + 'WARNING: %(err)s', + '', + 'The %(service)s may not function correctly until ', + 'the booleans are successfully changed with the command:', + ' %(cmd)s', + 'Try updating the policycoreutils and selinux-policy packages.' + ]) % {'err': self, 'service': service_name, 'cmd': self.command} diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py index 38b080131..4ba14d4a4 100644 --- a/ipaserver/install/adtrustinstance.py +++ b/ipaserver/install/adtrustinstance.py @@ -36,23 +36,17 @@ from ipalib.util import normalize_zone from ipapython.dn import DN from ipapython import sysrestore from ipapython import ipautil -from ipapython.ipa_log_manager import * +from ipapython.ipa_log_manager import root_logger +import ipapython.errors import ipaclient.ipachangeconf from ipaplatform import services from ipaplatform.paths import paths +from ipaplatform.tasks import tasks ALLOWED_NETBIOS_CHARS = string.ascii_uppercase + string.digits -SELINUX_WARNING = """ -WARNING: could not set selinux boolean(s) %(var)s to true. The adtrust -service may not function correctly until this boolean is successfully -change with the command: - /usr/sbin/setsebool -P %(var)s true -Try updating the policycoreutils and selinux-policy packages. -""" - UPGRADE_ERROR = """ Entry %(dn)s does not exist. This means upgrade from IPA 2.x to 3.x did not went well and required S4U2Proxy @@ -60,6 +54,9 @@ configuration was not set up properly. Please run ipa-ldap-updater manually and re-run ipa-adtrust-instal again afterwards. """ +SELINUX_BOOLEAN_SETTINGS = {'samba_portmapper': 'on'} + + def check_inst(): for smbfile in [paths.SMBD, paths.NET]: if not os.path.exists(smbfile): @@ -148,7 +145,6 @@ class ADTRUSTInstance(service.Service): # Constants self.smb_conf = paths.SMB_CONF self.samba_keytab = paths.SAMBA_KEYTAB - self.selinux_booleans = ["samba_portmapper"] self.cifs_hosts = [] # Values obtained from API.env @@ -611,35 +607,11 @@ class ADTRUSTInstance(service.Service): add_rr(zone, win_srv, "SRV", rec) def __configure_selinux_for_smbd(self): - selinux = False try: - if (os.path.exists(paths.SELINUXENABLED)): - ipautil.run([paths.SELINUXENABLED]) - selinux = True - except ipautil.CalledProcessError: - # selinuxenabled returns 1 if not enabled - pass - - if selinux: - # Don't assume all booleans are available - sebools = [] - for var in self.selinux_booleans: - try: - (stdout, stderr, returncode) = ipautil.run([paths.GETSEBOOL, var]) - if stdout and not stderr and returncode == 0: - self.backup_state(var, stdout.split()[2]) - sebools.append(var) - except: - pass - - if sebools: - bools = [var + "=true" for var in sebools] - args = [paths.SETSEBOOL, "-P"] - args.extend(bools); - try: - ipautil.run(args) - except: - self.print_msg(SELINUX_WARNING % dict(var=','.join(sebools))) + tasks.set_selinux_booleans(SELINUX_BOOLEAN_SETTINGS, + self.backup_state) + except ipapython.errors.SetseboolError as e: + self.print_msg(e.format_service_warning('adtrust service')) def __mod_krb5_conf(self): """ @@ -909,14 +881,12 @@ class ADTRUSTInstance(service.Service): # we should not restore smb.conf # Restore the state of affected selinux booleans - for var in self.selinux_booleans: - sebool_state = self.restore_state(var) - if not sebool_state is None: - try: - ipautil.run([paths.SETSEBOOL, - "-P", var, sebool_state]) - except Exception: - self.print_msg(SELINUX_WARNING % dict(var=var)) + boolean_states = {name: self.restore_state(name) + for name in SELINUX_BOOLEAN_SETTINGS} + try: + tasks.set_selinux_booleans(boolean_states) + except ipapython.errors.SetseboolError as e: + self.print_msg('WARNING: ' + str(e)) # Remove samba's credentials cache krb5cc_samba = paths.KRB5CC_SAMBA diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index 329dbb076..367c536b9 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -22,7 +22,6 @@ import os.path import tempfile import pwd import shutil -import stat import re import service @@ -31,12 +30,18 @@ import installutils from ipapython import sysrestore from ipapython import ipautil from ipapython import dogtag -from ipapython.ipa_log_manager import * +from ipapython.ipa_log_manager import root_logger +import ipapython.errors from ipaserver.install import sysupgrade from ipalib import api from ipaplatform.tasks import tasks from ipaplatform.paths import paths -from ipalib.constants import CACERT + + +SELINUX_BOOLEAN_SETTINGS = dict( + httpd_can_network_connect='on', + httpd_manage_ipa='on', +) def httpd_443_configured(): @@ -135,67 +140,11 @@ class HTTPInstance(service.Service): self.ldap_enable('HTTP', self.fqdn, self.dm_password, self.suffix) def configure_selinux_for_httpd(self): - def get_setsebool_args(changes): - if len(changes) == 1: - # workaround https://bugzilla.redhat.com/show_bug.cgi?id=825163 - updates = changes.items()[0] - else: - updates = ["%s=%s" % update for update in changes.iteritems()] - - args = [paths.SETSEBOOL, "-P"] - args.extend(updates) - - return args - - selinux = False try: - if (os.path.exists(paths.SELINUXENABLED)): - ipautil.run([paths.SELINUXENABLED]) - selinux = True - except ipautil.CalledProcessError: - # selinuxenabled returns 1 if not enabled - pass - - if selinux: - # Don't assume all vars are available - updated_vars = {} - failed_vars = {} - required_settings = (("httpd_can_network_connect", "on"), - ("httpd_manage_ipa", "on")) - for setting, state in required_settings: - try: - (stdout, stderr, returncode) = ipautil.run([paths.GETSEBOOL, setting]) - original_state = stdout.split()[2] - self.backup_state(setting, original_state) - - if original_state != state: - updated_vars[setting] = state - except ipautil.CalledProcessError, e: - root_logger.debug("Cannot get SELinux boolean '%s': %s", setting, e) - failed_vars[setting] = state - - # Allow apache to connect to the dogtag UI and the session cache - # This can still fail even if selinux is enabled. Execute these - # together so it is speedier. - if updated_vars: - args = get_setsebool_args(updated_vars) - try: - ipautil.run(args) - except ipautil.CalledProcessError: - failed_vars.update(updated_vars) - - if failed_vars: - args = get_setsebool_args(failed_vars) - names = [update[0] for update in updated_vars] - message = ['WARNING: could not set the following SELinux boolean(s):'] - for update in failed_vars.iteritems(): - message.append(' %s -> %s' % update) - message.append('The web interface may not function correctly until the booleans') - message.append('are successfully changed with the command:') - message.append(' '.join(args)) - message.append('Try updating the policycoreutils and selinux-policy packages.') - - self.print_msg("\n".join(message)) + tasks.set_selinux_booleans(SELINUX_BOOLEAN_SETTINGS, + self.backup_state) + except ipapython.errors.SetseboolError as e: + self.print_msg(e.format_service_warning('web interface')) def __create_http_keytab(self): installutils.kadmin_addprinc(self.principal) @@ -412,14 +361,13 @@ class HTTPInstance(service.Service): installutils.remove_file(paths.HTTPD_IPA_CONF) installutils.remove_file(paths.HTTPD_IPA_PKI_PROXY_CONF) - for var in ["httpd_can_network_connect", "httpd_manage_ipa"]: - sebool_state = self.restore_state(var) - if not sebool_state is None: - try: - ipautil.run([paths.SETSEBOOL, "-P", var, sebool_state]) - except ipautil.CalledProcessError, e: - self.print_msg("Cannot restore SELinux boolean '%s' back to '%s': %s" \ - % (var, sebool_state, e)) + # Restore SELinux boolean states + boolean_states = {name: self.restore_state(name) + for name in SELINUX_BOOLEAN_SETTINGS} + try: + tasks.set_selinux_booleans(boolean_states) + except ipapython.errors.SetseboolError as e: + self.print_msg('WARNING: ' + str(e)) if not running is None and running: self.start() |