mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
If SELinux is enabled ensure we also have restorecon.
We don't have a specific requires on the policycoreutils package. It gets pulled in as a dependency on the server anyway, but checking there is like a belt and suspenders. On the client we don't require SELinux at all. If SELinux is enabled however we need to set things up properly. This is provided by the policycoreutils package so fail if that isn't available. https://fedorahosted.org/freeipa/ticket/2368
This commit is contained in:
committed by
Martin Kosek
parent
5b465811ce
commit
9e877585e2
@@ -276,6 +276,7 @@ def check_bind():
|
|||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
ipaservices.check_selinux_status()
|
||||||
safe_options, options, filename = parse_options()
|
safe_options, options, filename = parse_options()
|
||||||
standard_logging_setup("/var/log/ipareplica-install.log", debug=options.debug)
|
standard_logging_setup("/var/log/ipareplica-install.log", debug=options.debug)
|
||||||
root_logger.debug('%s was invoked with argument "%s" and options: %s' % (sys.argv[0], filename, safe_options))
|
root_logger.debug('%s was invoked with argument "%s" and options: %s' % (sys.argv[0], filename, safe_options))
|
||||||
|
|||||||
@@ -539,6 +539,8 @@ def main():
|
|||||||
if os.getegid() != 0:
|
if os.getegid() != 0:
|
||||||
sys.exit("Must be root to set up server")
|
sys.exit("Must be root to set up server")
|
||||||
|
|
||||||
|
ipaservices.check_selinux_status()
|
||||||
|
|
||||||
signal.signal(signal.SIGTERM, signal_handler)
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
signal.signal(signal.SIGINT, signal_handler)
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
|
||||||
|
|||||||
@@ -1539,6 +1539,7 @@ def main():
|
|||||||
|
|
||||||
if not os.getegid() == 0:
|
if not os.getegid() == 0:
|
||||||
sys.exit("\nYou must be root to run ipa-client-install.\n")
|
sys.exit("\nYou must be root to run ipa-client-install.\n")
|
||||||
|
ipaservices.check_selinux_status()
|
||||||
logging_setup(options)
|
logging_setup(options)
|
||||||
root_logger.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
|
root_logger.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
|
||||||
root_logger.debug("missing options might be asked for interactively later\n")
|
root_logger.debug("missing options might be asked for interactively later\n")
|
||||||
|
|||||||
@@ -22,25 +22,36 @@ from ipapython.platform import base, redhat, systemd
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
# All what we allow exporting directly from this module
|
# All what we allow exporting directly from this module
|
||||||
# Everything else is made available through these symbols when they directly imported into ipapython.services:
|
# Everything else is made available through these symbols when they are
|
||||||
# authconfig -- class reference for platform-specific implementation of authconfig(8)
|
# directly imported into ipapython.services:
|
||||||
# service -- class reference for platform-specific implementation of a PlatformService class
|
# authconfig -- class reference for platform-specific implementation of
|
||||||
# knownservices -- factory instance to access named services IPA cares about, names are ipapython.services.wellknownservices
|
# authconfig(8)
|
||||||
# backup_and_replace_hostname -- platform-specific way to set hostname and make it persistent over reboots
|
# service -- class reference for platform-specific implementation of a
|
||||||
# restore_context -- platform-sepcific way to restore security context, if applicable
|
# PlatformService class
|
||||||
__all__ = ['authconfig', 'service', 'knownservices', 'backup_and_replace_hostname', 'restore_context']
|
# knownservices -- factory instance to access named services IPA cares about,
|
||||||
|
# names are ipapython.services.wellknownservices
|
||||||
|
# backup_and_replace_hostname -- platform-specific way to set hostname and
|
||||||
|
# make it persistent over reboots
|
||||||
|
# restore_context -- platform-sepcific way to restore security context, if
|
||||||
|
# applicable
|
||||||
|
# check_selinux_status -- platform-specific way to see if SELinux is enabled
|
||||||
|
# and restorecon is installed.
|
||||||
|
__all__ = ['authconfig', 'service', 'knownservices', 'backup_and_replace_hostname', 'restore_context', 'check_selinux_status']
|
||||||
|
|
||||||
# For beginning just remap names to add .service
|
# For beginning just remap names to add .service
|
||||||
# As more services will migrate to systemd, unit names will deviate and
|
# As more services will migrate to systemd, unit names will deviate and
|
||||||
# mapping will be kept in this dictionary
|
# mapping will be kept in this dictionary
|
||||||
system_units = dict(map(lambda x: (x, "%s.service" % (x)), base.wellknownservices))
|
system_units = dict(map(lambda x: (x, "%s.service" % (x)), base.wellknownservices))
|
||||||
|
|
||||||
# Rewrite dirsrv and pki-cad services as they support instances via separate service generator
|
# Rewrite dirsrv and pki-cad services as they support instances via separate
|
||||||
# To make this working, one needs to have both foo@.service and foo.target -- the latter is used
|
# service generator. To make this working, one needs to have both foo@.servic
|
||||||
# when request should be coming for all instances (like stop). systemd, unfortunately, does not allow
|
# and foo.target -- the latter is used when request should be coming for
|
||||||
# to request action for all service instances at once if only foo@.service unit is available.
|
# all instances (like stop). systemd, unfortunately, does not allow one
|
||||||
# To add more, if any of those services need to be started/stopped automagically, one needs to manually
|
# to request action for all service instances at once if only foo@.service
|
||||||
# create symlinks in /etc/systemd/system/foo.target.wants/ (look into systemd.py's enable() code).
|
# unit is available. To add more, if any of those services need to be
|
||||||
|
# started/stopped automagically, one needs to manually create symlinks in
|
||||||
|
# /etc/systemd/system/foo.target.wants/ (look into systemd.py's enable()
|
||||||
|
# code).
|
||||||
system_units['dirsrv'] = 'dirsrv@.service'
|
system_units['dirsrv'] = 'dirsrv@.service'
|
||||||
# Our directory server instance for PKI is dirsrv@PKI-IPA.service
|
# Our directory server instance for PKI is dirsrv@PKI-IPA.service
|
||||||
system_units['pkids'] = 'dirsrv@PKI-IPA.service'
|
system_units['pkids'] = 'dirsrv@PKI-IPA.service'
|
||||||
@@ -53,30 +64,35 @@ class Fedora16Service(systemd.SystemdService):
|
|||||||
service_name = system_units[service_name]
|
service_name = system_units[service_name]
|
||||||
else:
|
else:
|
||||||
if len(service_name.split('.')) == 1:
|
if len(service_name.split('.')) == 1:
|
||||||
# if service_name does not have a dot, it is not foo.service and not a foo.target
|
# if service_name does not have a dot, it is not foo.service
|
||||||
# Thus, not correct service name for systemd, default to foo.service style then
|
# and not a foo.target. Thus, not correct service name for
|
||||||
|
# systemd, default to foo.service style then
|
||||||
service_name = "%s.service" % (service_name)
|
service_name = "%s.service" % (service_name)
|
||||||
super(Fedora16Service, self).__init__(service_name)
|
super(Fedora16Service, self).__init__(service_name)
|
||||||
|
|
||||||
# Special handling of directory server service
|
# Special handling of directory server service
|
||||||
#
|
#
|
||||||
# We need to explicitly enable instances to install proper symlinks as dirsrv.target.wants/
|
# We need to explicitly enable instances to install proper symlinks as
|
||||||
# dependencies. Standard systemd service class does it on #enable() method call. Unfortunately,
|
# dirsrv.target.wants/ dependencies. Standard systemd service class does it
|
||||||
# ipa-server-install does not do explicit dirsrv.enable() because the service startup is handled by ipactl.
|
# on enable() method call. Unfortunately, ipa-server-install does not do
|
||||||
|
# explicit dirsrv.enable() because the service startup is handled by ipactl.
|
||||||
#
|
#
|
||||||
# If we wouldn't do this, our instances will not be started as systemd would not have any clue
|
# If we wouldn't do this, our instances will not be started as systemd would
|
||||||
# about instances (PKI-IPA and the domain we serve) at all. Thus, hook into dirsrv.restart().
|
# not have any clue about instances (PKI-IPA and the domain we serve) at all.
|
||||||
|
# Thus, hook into dirsrv.restart().
|
||||||
class Fedora16DirectoryService(Fedora16Service):
|
class Fedora16DirectoryService(Fedora16Service):
|
||||||
def enable(self, instance_name=""):
|
def enable(self, instance_name=""):
|
||||||
super(Fedora16DirectoryService, self).enable(instance_name)
|
super(Fedora16DirectoryService, self).enable(instance_name)
|
||||||
dirsrv_systemd = "/etc/sysconfig/dirsrv.systemd"
|
dirsrv_systemd = "/etc/sysconfig/dirsrv.systemd"
|
||||||
if os.path.exists(dirsrv_systemd):
|
if os.path.exists(dirsrv_systemd):
|
||||||
# We need to enable LimitNOFILE=8192 in the dirsrv@.service
|
# We need to enable LimitNOFILE=8192 in the dirsrv@.service
|
||||||
# Since 389-ds-base-1.2.10-0.8.a7 the configuration of the service parameters is performed
|
# Since 389-ds-base-1.2.10-0.8.a7 the configuration of the
|
||||||
# via /etc/sysconfig/dirsrv.systemd file which is imported by systemd into dirsrv@.service unit
|
# service parameters is performed via
|
||||||
|
# /etc/sysconfig/dirsrv.systemd file which is imported by systemd
|
||||||
|
# into dirsrv@.service unit
|
||||||
replacevars = {'LimitNOFILE':'8192'}
|
replacevars = {'LimitNOFILE':'8192'}
|
||||||
ipautil.inifile_replace_variables(dirsrv_systemd, 'service', replacevars=replacevars)
|
ipautil.inifile_replace_variables(dirsrv_systemd, 'service', replacevars=replacevars)
|
||||||
redhat.restore_context(dirsrv_systemd)
|
restore_context(dirsrv_systemd)
|
||||||
ipautil.run(["/bin/systemctl", "--system", "daemon-reload"],raiseonerr=False)
|
ipautil.run(["/bin/systemctl", "--system", "daemon-reload"],raiseonerr=False)
|
||||||
|
|
||||||
def restart(self, instance_name="", capture_output=True):
|
def restart(self, instance_name="", capture_output=True):
|
||||||
@@ -93,8 +109,9 @@ class Fedora16DirectoryService(Fedora16Service):
|
|||||||
super(Fedora16DirectoryService, self).restart(instance_name, capture_output=capture_output)
|
super(Fedora16DirectoryService, self).restart(instance_name, capture_output=capture_output)
|
||||||
|
|
||||||
# Enforce restart of IPA services when we do enable it
|
# Enforce restart of IPA services when we do enable it
|
||||||
# This gets around the fact that after ipa-server-install systemd thinks ipa.service is not yet started
|
# This gets around the fact that after ipa-server-install systemd thinks
|
||||||
# but all services were actually started already.
|
# ipa.service is not yet started but all services were actually started
|
||||||
|
# already.
|
||||||
class Fedora16IPAService(Fedora16Service):
|
class Fedora16IPAService(Fedora16Service):
|
||||||
def enable(self, instance_name=""):
|
def enable(self, instance_name=""):
|
||||||
super(Fedora16IPAService, self).enable(instance_name)
|
super(Fedora16IPAService, self).enable(instance_name)
|
||||||
@@ -104,7 +121,8 @@ class Fedora16SSHService(Fedora16Service):
|
|||||||
def get_config_dir(self, instance_name=""):
|
def get_config_dir(self, instance_name=""):
|
||||||
return '/etc/ssh'
|
return '/etc/ssh'
|
||||||
|
|
||||||
# Redirect directory server service through special sub-class due to its special handling of instances
|
# Redirect directory server service through special sub-class due to its
|
||||||
|
# special handling of instances
|
||||||
def f16_service(name):
|
def f16_service(name):
|
||||||
if name == 'dirsrv':
|
if name == 'dirsrv':
|
||||||
return Fedora16DirectoryService(name)
|
return Fedora16DirectoryService(name)
|
||||||
@@ -122,8 +140,13 @@ class Fedora16Services(base.KnownServices):
|
|||||||
# Call base class constructor. This will lock services to read-only
|
# Call base class constructor. This will lock services to read-only
|
||||||
super(Fedora16Services, self).__init__(services)
|
super(Fedora16Services, self).__init__(services)
|
||||||
|
|
||||||
|
def restore_context(filepath, restorecon='/usr/sbin/restorecon'):
|
||||||
|
return redhat.restore_context(filepath, restorecon)
|
||||||
|
|
||||||
|
def check_selinux_status(restorecon='/usr/sbin/restorecon'):
|
||||||
|
return redhat.check_selinux_status(restorecon)
|
||||||
|
|
||||||
authconfig = redhat.authconfig
|
authconfig = redhat.authconfig
|
||||||
service = f16_service
|
service = f16_service
|
||||||
knownservices = Fedora16Services()
|
knownservices = Fedora16Services()
|
||||||
restore_context = redhat.restore_context
|
|
||||||
backup_and_replace_hostname = redhat.backup_and_replace_hostname
|
backup_and_replace_hostname = redhat.backup_and_replace_hostname
|
||||||
|
|||||||
@@ -28,13 +28,22 @@ from ipapython import ipautil
|
|||||||
from ipapython.platform import base
|
from ipapython.platform import base
|
||||||
|
|
||||||
# All what we allow exporting directly from this module
|
# All what we allow exporting directly from this module
|
||||||
# Everything else is made available through these symbols when they directly imported into ipapython.services:
|
# Everything else is made available through these symbols when they are
|
||||||
# authconfig -- class reference for platform-specific implementation of authconfig(8)
|
# directly imported into ipapython.services:
|
||||||
# service -- class reference for platform-specific implementation of a PlatformService class
|
#
|
||||||
# knownservices -- factory instance to access named services IPA cares about, names are ipapython.services.wellknownservices
|
# authconfig -- class reference for platform-specific implementation of
|
||||||
# backup_and_replace_hostname -- platform-specific way to set hostname and make it persistent over reboots
|
# authconfig(8)
|
||||||
# restore_context -- platform-sepcific way to restore security context, if applicable
|
# service -- class reference for platform-specific implementation of a
|
||||||
__all__ = ['authconfig', 'service', 'knownservices', 'backup_and_replace_hostname', 'restore_context']
|
# PlatformService class
|
||||||
|
# knownservices -- factory instance to access named services IPA cares about,
|
||||||
|
# names are ipapython.services.wellknownservices
|
||||||
|
# backup_and_replace_hostname -- platform-specific way to set hostname and
|
||||||
|
# make it persistent over reboots
|
||||||
|
# restore_context -- platform-sepcific way to restore security context, if
|
||||||
|
# applicable
|
||||||
|
# check_selinux_status -- platform-specific way to see if SELinux is enabled
|
||||||
|
# and restorecon is installed.
|
||||||
|
__all__ = ['authconfig', 'service', 'knownservices', 'backup_and_replace_hostname', 'restore_context', 'check_selinux_status']
|
||||||
|
|
||||||
class RedHatService(base.PlatformService):
|
class RedHatService(base.PlatformService):
|
||||||
def stop(self, instance_name="", capture_output=True):
|
def stop(self, instance_name="", capture_output=True):
|
||||||
@@ -130,10 +139,10 @@ authconfig = RedHatAuthConfig
|
|||||||
service = redhat_service
|
service = redhat_service
|
||||||
knownservices = RedHatServices()
|
knownservices = RedHatServices()
|
||||||
|
|
||||||
def restore_context(filepath):
|
def restore_context(filepath, restorecon='/sbin/restorecon'):
|
||||||
"""
|
"""
|
||||||
restore security context on the file path
|
restore security context on the file path
|
||||||
SELinux equivalent is /sbin/restorecon <filepath>
|
SELinux equivalent is /path/to/restorecon <filepath>
|
||||||
|
|
||||||
restorecon's return values are not reliable so we have to
|
restorecon's return values are not reliable so we have to
|
||||||
ignore them (BZ #739604).
|
ignore them (BZ #739604).
|
||||||
@@ -150,8 +159,8 @@ def restore_context(filepath):
|
|||||||
# selinuxenabled returns 1 if not enabled
|
# selinuxenabled returns 1 if not enabled
|
||||||
return
|
return
|
||||||
|
|
||||||
if (os.path.exists('/sbin/restorecon')):
|
if (os.path.exists(restorecon)):
|
||||||
ipautil.run(["/sbin/restorecon", filepath], raiseonerr=False)
|
ipautil.run([restorecon, filepath], raiseonerr=False)
|
||||||
|
|
||||||
def backup_and_replace_hostname(fstore, statestore, hostname):
|
def backup_and_replace_hostname(fstore, statestore, hostname):
|
||||||
old_hostname = socket.gethostname()
|
old_hostname = socket.gethostname()
|
||||||
@@ -168,3 +177,26 @@ def backup_and_replace_hostname(fstore, statestore, hostname):
|
|||||||
statestore.backup_state('network', 'hostname', old_values['HOSTNAME'])
|
statestore.backup_state('network', 'hostname', old_values['HOSTNAME'])
|
||||||
else:
|
else:
|
||||||
statestore.backup_state('network', 'hostname', old_hostname)
|
statestore.backup_state('network', 'hostname', old_hostname)
|
||||||
|
|
||||||
|
def check_selinux_status(restorecon='/sbin/restorecon'):
|
||||||
|
"""
|
||||||
|
We don't have a specific package requirement for policycoreutils
|
||||||
|
which provides restorecon. This is because we don't require
|
||||||
|
SELinux on client installs. However if SELinux is enabled then
|
||||||
|
this package is required.
|
||||||
|
|
||||||
|
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)
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ def restore_context_default(filepath):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Restore security context for a path
|
# Restore security context for a path
|
||||||
# If the platform has security features where context is important, implement your own
|
# If the platform has security features where context is important, implement
|
||||||
# version in platform services
|
# your own version in platform services
|
||||||
restore_context = restore_context_default
|
restore_context = restore_context_default
|
||||||
|
|
||||||
# Default implementation of backup and replace hostname that does nothing
|
# Default implementation of backup and replace hostname that does nothing
|
||||||
@@ -41,8 +41,14 @@ def backup_and_replace_hostname_default(fstore, statestore, hostname):
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Backup and replace system's hostname
|
# Backup and replace system's hostname
|
||||||
# Since many platforms have their own way how to store system's hostname, this method must be
|
# Since many platforms have their own way how to store system's hostname,
|
||||||
# implemented in platform services
|
# this method must be implemented in platform services
|
||||||
backup_and_replace_hostname = backup_and_replace_hostname_default
|
backup_and_replace_hostname = backup_and_replace_hostname_default
|
||||||
|
|
||||||
|
# See if SELinux is enabled and /usr/sbin/restorecon is installed.
|
||||||
|
# Default to a no-op. Those platforms that support SELinux should
|
||||||
|
# implement this function.
|
||||||
|
def check_selinux_status():
|
||||||
|
return
|
||||||
|
|
||||||
from ipapython.platform.SUPPORTED_PLATFORM import *
|
from ipapython.platform.SUPPORTED_PLATFORM import *
|
||||||
|
|||||||
Reference in New Issue
Block a user