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.ssh import SSHPublicKey
from ipalib.rpc import delete_persistent_client_session_data
from ipaplatform.tasks import tasks
except ImportError:
print >> sys.stderr, """\
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",
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")
help="do not modify the nsswitch.conf and PAM configuration")
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",
@ -563,30 +565,10 @@ def uninstall(options, env):
sshd_config = os.path.join(ipaservices.knownservices.sshd.get_config_dir(), "sshd_config")
was_sshd_configured = fstore.has_file(sshd_config)
try:
auth_config = ipaservices.authconfig()
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").\
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()
tasks.restore_pre_ipa_client_configuration(fstore,
statestore,
was_sssd_installed,
was_sssd_configured)
except Exception, e:
root_logger.error(
"Failed to remove krb5/LDAP configuration: %s", str(e))
@ -1461,7 +1443,7 @@ def configure_nisdomain(options, domain):
ipaservices.knownservices.domainname.is_enabled())
# Set the new NIS domain name
set_nisdomain(domain)
tasks.set_nisdomain(domain)
# Enable and start the domainname service
ipaservices.knownservices.domainname.enable()
@ -1478,7 +1460,7 @@ def unconfigure_nisdomain():
else:
root_logger.info('Unconfiguring the NIS domain.')
set_nisdomain(old_nisdomain)
tasks.set_nisdomain(old_nisdomain)
# Restore the configuration of the domainname service
enabled = statestore.restore_state('domainname', 'enabled')
@ -1486,14 +1468,6 @@ def unconfigure_nisdomain():
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):
""" Connect to the server's LDAP port in order to determine what ip
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:
# Modify nsswitch/pam stack
auth_config = ipaservices.authconfig()
if options.sssd:
statestore.backup_state('authconfig', 'sssd', True)
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"
tasks.modify_nsswitch_pam_stack(sssd=options.sssd,
mkhomedir=options.mkhomedir,
statestore=statestore)
if options.mkhomedir:
statestore.backup_state('authconfig', 'mkhomedir', True)
auth_config.enable("mkhomedir")
root_logger.info("%s enabled", "SSSD" if options.sssd else "LDAP")
auth_config.add_option("update")
auth_config.execute()
root_logger.info("%s", message)
if options.sssd:
sssd = ipaservices.service('sssd')
try:
@ -2758,13 +2717,7 @@ def install(options, env, fstore, statestore):
"Failed to enable automatic startup of the SSSD daemon: %s", e)
if not options.sssd:
#Modify pam to add pam_krb5 only when sssd is not in use
auth_config.reset()
statestore.backup_state('authconfig', 'krb5', True)
auth_config.enable("krb5").\
add_option("update").\
add_option("nostart")
auth_config.execute()
tasks.modify_pam_to_use_krb5(statestore)
root_logger.info("Kerberos 5 enabled")
# 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):
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>
# 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
#
# 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,
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
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
system authentication resources. In Red Hat-produced systems this is done with
authconfig(8) utility.
system authentication resources. In Red Hat-produced systems this is done
with authconfig(8) utility.
"""
def __build_args(self):
def build_args(self):
args = []
for (option, value) in self.parameters.items():
if type(value) is bool:
if value:
@ -41,9 +44,13 @@ class RedHatAuthConfig(base.AuthConfig):
elif value is None:
args.append("--%s" % (option))
else:
args.append("--%s%s" % (option,value))
args.append("--%s%s" % (option, value))
return args
def execute(self):
args = self.__build_args()
ipautil.run(["/usr/sbin/authconfig"]+args)
def execute(self, update=True):
if update:
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 ipautil
from ipaplatform.fedora.authconfig import FedoraAuthConfig
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'
'Install the policycoreutils package and start the '
'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_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