ipaplatform: Do not require custom Authconfig implementations from platform modules

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

Reviewed-By: Petr Viktorin <pviktori@redhat.com>
This commit is contained in:
Tomas Babej 2014-05-27 09:13:59 +02:00 committed by Petr Viktorin
parent 6a4cd8a4e3
commit 5f31f2d35f
6 changed files with 219 additions and 154 deletions

View File

@ -50,6 +50,8 @@ try:
from ipapython.dn import DN from ipapython.dn import DN
from ipapython.ssh import SSHPublicKey from ipapython.ssh import SSHPublicKey
from ipalib.rpc import delete_persistent_client_session_data from ipalib.rpc import delete_persistent_client_session_data
from ipaplatform.tasks import tasks
except ImportError: except ImportError:
print >> sys.stderr, """\ print >> sys.stderr, """\
There was a problem importing one of the required Python modules. The There was a problem importing one of the required Python modules. The
@ -144,7 +146,7 @@ def parse_options():
basic_group.add_option("--no-dns-sshfp", dest="create_sshfp", default=True, action="store_false", basic_group.add_option("--no-dns-sshfp", dest="create_sshfp", default=True, action="store_false",
help="do not automatically create DNS SSHFP records") help="do not automatically create DNS SSHFP records")
basic_group.add_option("--noac", dest="no_ac", default=False, action="store_true", 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") help="do not modify the nsswitch.conf and PAM configuration")
basic_group.add_option("-f", "--force", dest="force", action="store_true", basic_group.add_option("-f", "--force", dest="force", action="store_true",
default=False, help="force setting of LDAP/Kerberos conf") default=False, help="force setting of LDAP/Kerberos conf")
basic_group.add_option("-d", "--debug", dest="debug", action="store_true", basic_group.add_option("-d", "--debug", dest="debug", action="store_true",
@ -563,30 +565,10 @@ def uninstall(options, env):
sshd_config = os.path.join(ipaservices.knownservices.sshd.get_config_dir(), "sshd_config") sshd_config = os.path.join(ipaservices.knownservices.sshd.get_config_dir(), "sshd_config")
was_sshd_configured = fstore.has_file(sshd_config) was_sshd_configured = fstore.has_file(sshd_config)
try: try:
auth_config = ipaservices.authconfig() tasks.restore_pre_ipa_client_configuration(fstore,
if statestore.has_state('authconfig'): statestore,
# disable only those configurations that we enabled during install was_sssd_installed,
for conf in ('ldap', 'krb5', 'sssd', 'sssdauth', 'mkhomedir'): was_sssd_configured)
cnf = statestore.restore_state('authconfig', conf)
# Do not disable sssd, as this can cause issues with its later
# uses. Remove it from statestore however, so that it becomes
# empty at the end of uninstall process.
if cnf and conf != 'sssd':
auth_config.disable(conf)
else:
# There was no authconfig status store
# It means the code was upgraded after original install
# Fall back to old logic
auth_config.disable("ldap").\
disable("krb5")
if not(was_sssd_installed and was_sssd_configured):
# Only disable sssdauth. Disabling sssd would cause issues
# with its later uses.
auth_config.disable("sssdauth")
auth_config.disable("mkhomedir")
auth_config.add_option("update")
auth_config.execute()
except Exception, e: except Exception, e:
root_logger.error( root_logger.error(
"Failed to remove krb5/LDAP configuration: %s", str(e)) "Failed to remove krb5/LDAP configuration: %s", str(e))
@ -1461,7 +1443,7 @@ def configure_nisdomain(options, domain):
ipaservices.knownservices.domainname.is_enabled()) ipaservices.knownservices.domainname.is_enabled())
# Set the new NIS domain name # Set the new NIS domain name
set_nisdomain(domain) tasks.set_nisdomain(domain)
# Enable and start the domainname service # Enable and start the domainname service
ipaservices.knownservices.domainname.enable() ipaservices.knownservices.domainname.enable()
@ -1478,7 +1460,7 @@ def unconfigure_nisdomain():
else: else:
root_logger.info('Unconfiguring the NIS domain.') root_logger.info('Unconfiguring the NIS domain.')
set_nisdomain(old_nisdomain) tasks.set_nisdomain(old_nisdomain)
# Restore the configuration of the domainname service # Restore the configuration of the domainname service
enabled = statestore.restore_state('domainname', 'enabled') enabled = statestore.restore_state('domainname', 'enabled')
@ -1486,14 +1468,6 @@ def unconfigure_nisdomain():
ipaservices.knownservices.domainname.disable() ipaservices.knownservices.domainname.disable()
def set_nisdomain(nisdomain):
# Let authconfig setup the permanent configuration
auth_config = ipaservices.authconfig()
auth_config.add_parameter("nisdomain", nisdomain)
auth_config.add_option("update")
auth_config.execute()
def resolve_ipaddress(server): def resolve_ipaddress(server):
""" Connect to the server's LDAP port in order to determine what ip """ Connect to the server's LDAP port in order to determine what ip
address this machine uses as "public" ip (relative to the server). address this machine uses as "public" ip (relative to the server).
@ -2723,27 +2697,12 @@ def install(options, env, fstore, statestore):
if not options.no_ac: if not options.no_ac:
# Modify nsswitch/pam stack # Modify nsswitch/pam stack
auth_config = ipaservices.authconfig() tasks.modify_nsswitch_pam_stack(sssd=options.sssd,
if options.sssd: mkhomedir=options.mkhomedir,
statestore.backup_state('authconfig', 'sssd', True) statestore=statestore)
statestore.backup_state('authconfig', 'sssdauth', True)
auth_config.enable("sssd").\
enable("sssdauth")
message = "SSSD enabled"
conf = 'SSSD'
else:
statestore.backup_state('authconfig', 'ldap', True)
auth_config.enable("ldap").\
enable("forcelegacy")
message = "LDAP enabled"
if options.mkhomedir: root_logger.info("%s enabled", "SSSD" if options.sssd else "LDAP")
statestore.backup_state('authconfig', 'mkhomedir', True)
auth_config.enable("mkhomedir")
auth_config.add_option("update")
auth_config.execute()
root_logger.info("%s", message)
if options.sssd: if options.sssd:
sssd = ipaservices.service('sssd') sssd = ipaservices.service('sssd')
try: try:
@ -2758,13 +2717,7 @@ def install(options, env, fstore, statestore):
"Failed to enable automatic startup of the SSSD daemon: %s", e) "Failed to enable automatic startup of the SSSD daemon: %s", e)
if not options.sssd: if not options.sssd:
#Modify pam to add pam_krb5 only when sssd is not in use tasks.modify_pam_to_use_krb5(statestore)
auth_config.reset()
statestore.backup_state('authconfig', 'krb5', True)
auth_config.enable("krb5").\
add_option("update").\
add_option("nostart")
auth_config.execute()
root_logger.info("Kerberos 5 enabled") root_logger.info("Kerberos 5 enabled")
# Update non-SSSD LDAP configuration after authconfig calls as it would # Update non-SSSD LDAP configuration after authconfig calls as it would

View File

@ -0,0 +1,102 @@
# Authors:
# Alexander Bokovoy <abokovoy@redhat.com>
# Tomas Babej <tbabej@redhat.com>
#
# Copyright (C) 2011-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 AuthConfig(object):
"""
AuthConfig class implements system-independent interface to configure
system authentication resources. In Red Hat systems this is done with
authconfig(8) utility.
AuthConfig class is nothing more than a tool to gather configuration
options and execute their processing. These options then converted by
an actual implementation to series of a system calls to appropriate
utilities performing real configuration.
IPA *expects* names of AuthConfig's options to follow authconfig(8)
naming scheme!
Actual implementation should be done in ipapython/platform/<platform>.py
by inheriting from platform.AuthConfig and redefining build_args()
and execute() methods.
from ipapython.platform import platform
class PlatformAuthConfig(platform.AuthConfig):
def build_args():
...
def execute():
...
authconfig = PlatformAuthConfig
....
See ipapython/platform/redhat.py for a sample implementation that uses
authconfig(8) as its backend.
From IPA code perspective, the authentication configuration should be
done with use of ipapython.services.authconfig:
from ipapython import services as ipaservices
auth_config = ipaservices.authconfig()
auth_config.disable("ldap")
auth_config.disable("krb5")
auth_config.disable("sssd")
auth_config.disable("sssdauth")
auth_config.disable("mkhomedir")
auth_config.add_option("update")
auth_config.enable("nis")
auth_config.add_parameter("nisdomain","foobar")
auth_config.execute()
If you need to re-use existing AuthConfig instance for multiple runs,
make sure to call 'AuthConfig.reset()' between the runs.
"""
def __init__(self):
self.parameters = {}
def enable(self, option):
self.parameters[option] = True
return self
def disable(self, option):
self.parameters[option] = False
return self
def add_option(self, option):
self.parameters[option] = None
return self
def add_parameter(self, option, value):
self.parameters[option] = [value]
return self
def build_args(self):
# do nothing
return None
def execute(self):
# do nothing
return None
def reset(self):
self.parameters = {}
return self

View File

@ -60,3 +60,21 @@ def restore_network_configuration(fstore, statestore):
def backup_and_replace_hostname(fstore, statestore, hostname): def backup_and_replace_hostname(fstore, statestore, hostname):
return return
def restore_pre_ipa_client_configuration(fstore, statestore,
was_sssd_installed,
was_sssd_configured):
return
def set_nisdomain(nisdomain):
return
def modify_nsswitch_pam_stack(sssd, mkhomedir, statestore):
return
def modify_pam_to_use_krb5(statestore):
return

View File

@ -1,7 +1,8 @@
# Authors: Simo Sorce <ssorce@redhat.com> # Authors: Simo Sorce <ssorce@redhat.com>
# Alexander Bokovoy <abokovoy@redhat.com> # Alexander Bokovoy <abokovoy@redhat.com>
# Tomas Babej <tbabej@redhat.com>
# #
# Copyright (C) 2007-2011 Red Hat # Copyright (C) 2007-2014 Red Hat
# see file 'COPYING' for use and warranty information # see file 'COPYING' for use and warranty information
# #
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
@ -11,24 +12,26 @@
# #
# This program is distributed in the hope that it will be useful, # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of # but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details. # GNU General Public License for more details.
# #
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from ipapython import ipautil from ipapython import ipautil
from ipapython.platform import base from ipaplatform.base.authconfig import AuthConfig
class RedHatAuthConfig(base.AuthConfig):
class FedoraAuthConfig(AuthConfig):
""" """
AuthConfig class implements system-independent interface to configure AuthConfig class implements system-independent interface to configure
system authentication resources. In Red Hat-produced systems this is done with system authentication resources. In Red Hat-produced systems this is done
authconfig(8) utility. with authconfig(8) utility.
""" """
def __build_args(self):
def build_args(self):
args = [] args = []
for (option, value) in self.parameters.items(): for (option, value) in self.parameters.items():
if type(value) is bool: if type(value) is bool:
if value: if value:
@ -41,9 +44,13 @@ class RedHatAuthConfig(base.AuthConfig):
elif value is None: elif value is None:
args.append("--%s" % (option)) args.append("--%s" % (option))
else: else:
args.append("--%s%s" % (option,value)) args.append("--%s%s" % (option, value))
return args return args
def execute(self): def execute(self, update=True):
args = self.__build_args() if update:
ipautil.run(["/usr/sbin/authconfig"]+args) self.add_option("update")
args = self.build_args()
ipautil.run(["/usr/sbin/authconfig"] + args)

View File

@ -25,6 +25,7 @@ This module contains default Fedora-specific implementations of system tasks.
import os import os
import ipautil import ipautil
from ipaplatform.fedora.authconfig import FedoraAuthConfig
from ipaplatform.base.tasks import * from ipaplatform.base.tasks import *
@ -76,3 +77,67 @@ def check_selinux_status(restorecon='/sbin/restorecon'):
raise RuntimeError('SELinux is enabled but %s does not exist.\n' raise RuntimeError('SELinux is enabled but %s does not exist.\n'
'Install the policycoreutils package and start the ' 'Install the policycoreutils package and start the '
'installation again.' % restorecon) 'installation again.' % restorecon)
def restore_pre_ipa_client_configuration(fstore, statestore,
was_sssd_installed,
was_sssd_configured):
auth_config = FedoraAuthConfig()
if statestore.has_state('authconfig'):
# disable only those configurations that we enabled during install
for conf in ('ldap', 'krb5', 'sssd', 'sssdauth', 'mkhomedir'):
cnf = statestore.restore_state('authconfig', conf)
# Do not disable sssd, as this can cause issues with its later
# uses. Remove it from statestore however, so that it becomes
# empty at the end of uninstall process.
if cnf and conf != 'sssd':
auth_config.disable(conf)
else:
# There was no authconfig status store
# It means the code was upgraded after original install
# Fall back to old logic
auth_config.disable("ldap")
auth_config.disable("krb5")
if not(was_sssd_installed and was_sssd_configured):
# Only disable sssdauth. Disabling sssd would cause issues
# with its later uses.
auth_config.disable("sssdauth")
auth_config.disable("mkhomedir")
auth_config.execute()
def set_nisdomain(nisdomain):
# Let authconfig setup the permanent configuration
auth_config = FedoraAuthConfig()
auth_config.add_parameter("nisdomain", nisdomain)
auth_config.execute()
def modify_nsswitch_pam_stack(sssd, mkhomedir, statestore):
auth_config = FedoraAuthConfig()
if sssd:
statestore.backup_state('authconfig', 'sssd', True)
statestore.backup_state('authconfig', 'sssdauth', True)
auth_config.enable("sssd")
auth_config.enable("sssdauth")
else:
statestore.backup_state('authconfig', 'ldap', True)
auth_config.enable("ldap")
auth_config.enable("forcelegacy")
if mkhomedir:
statestore.backup_state('authconfig', 'mkhomedir', True)
auth_config.enable("mkhomedir")
auth_config.execute()
def modify_pam_to_use_krb5(statestore):
auth_config = FedoraAuthConfig()
statestore.backup_state('authconfig', 'krb5', True)
auth_config.enable("krb5")
auth_config.add_option("nostart")
auth_config.execute()

View File

@ -22,87 +22,7 @@ FIREFOX_INSTALL_DIRS = ["/usr/lib64/firefox", "/usr/lib/firefox"]
# /firefox/install/dir/FIREFOX_PREFERENCES_REL_PATH # /firefox/install/dir/FIREFOX_PREFERENCES_REL_PATH
FIREFOX_PREFERENCES_REL_PATH = "browser/defaults/preferences" FIREFOX_PREFERENCES_REL_PATH = "browser/defaults/preferences"
class AuthConfig(object):
"""
AuthConfig class implements system-independent interface to configure
system authentication resources. In Red Hat systems this is done with
authconfig(8) utility.
AuthConfig class is nothing more than a tool to gather configuration
options and execute their processing. These options then converted by
an actual implementation to series of a system calls to appropriate
utilities performing real configuration.
IPA *expects* names of AuthConfig's options to follow authconfig(8)
naming scheme!
Actual implementation should be done in ipapython/platform/<platform>.py
by inheriting from platform.AuthConfig and redefining __build_args()
and execute() methods.
from ipapython.platform import platform
class PlatformAuthConfig(platform.AuthConfig):
def __build_args():
...
def execute():
...
authconfig = PlatformAuthConfig
....
See ipapython/platform/redhat.py for a sample implementation that uses
authconfig(8) as its backend.
From IPA code perspective, the authentication configuration should be
done with use of ipapython.services.authconfig:
from ipapython import services as ipaservices
auth_config = ipaservices.authconfig()
auth_config.disable("ldap").\
disable("krb5").\
disable("sssd").\
disable("sssdauth").\
disable("mkhomedir").\
add_option("update").\
enable("nis").\
add_parameter("nisdomain","foobar")
auth_config.execute()
If you need to re-use existing AuthConfig instance for multiple runs,
make sure to call 'AuthConfig.reset()' between the runs.
"""
def __init__(self):
self.parameters = {}
def enable(self, option):
self.parameters[option] = True
return self
def disable(self, option):
self.parameters[option] = False
return self
def add_option(self, option):
self.parameters[option] = None
return self
def add_parameter(self, option, value):
self.parameters[option] = [value]
return self
def __build_args(self):
# do nothing
return None
def execute(self):
# do nothing
return None
def reset(self):
self.parameters = {}
return self