Improve error handling in ipa-httpd-kdcproxy

The pre start script 'ipa-httpd-kdcproxy' for httpd.service now handles
connection and authentication errors more gracefully. If the script is
not able to conenct to LDAP, it only prints a warning and exits with
status code 0. All other errors are still reported as fatal error and
result in a non-zero exit code.

This fixes a problem with offline RPM updates. A restart of Apache no
longer fails when LDAP is not running.

Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
Christian Heimes
2015-07-07 16:05:48 +02:00
committed by Tomas Babej
parent 6fa123447f
commit 25d1afdc54

View File

@@ -37,8 +37,26 @@ DEBUG = False
TIME_LIMIT = 2 TIME_LIMIT = 2
class CheckError(Exception): class Error(Exception):
"""An unrecoverable error has occured""" """Base error class"""
class ConfigFileError(Error):
"""Something is wrong with the config file"""
class CheckError(Error):
"""An unrecoverable error has occured
The exit code is 0.
"""
class FatalError(Error):
"""A fatal error has occured
Fatal errors cause the command to exit with a non-null exit code.
"""
class KDCProxyConfig(object): class KDCProxyConfig(object):
@@ -64,14 +82,16 @@ class KDCProxyConfig(object):
self.con.ldapi = True self.con.ldapi = True
self.con.do_bind(timeout=self.time_limit) self.con.do_bind(timeout=self.time_limit)
except errors.NetworkError as e: except errors.NetworkError as e:
msg = 'Failed to get setting from dirsrv: %s' % e msg = 'Unable to connect to dirsrv: %s' % e
self.log.exception(msg) raise CheckError(msg)
except errors.AuthorizationError as e:
msg = 'Authorization error: %s' % e
raise CheckError(msg) raise CheckError(msg)
except Exception as e: except Exception as e:
msg = ('Unknown error while retrieving setting from %s: %s' % msg = ('Unknown error while retrieving setting from %s: %s' %
(self.ldap_uri, e)) (self.ldap_uri, e))
self.log.exception(msg) self.log.exception(msg)
raise CheckError(msg) raise FatalError(msg)
def _find_entry(self, dn, attrs, filter, scope=IPAdmin.SCOPE_BASE): def _find_entry(self, dn, attrs, filter, scope=IPAdmin.SCOPE_BASE):
"""Find an LDAP entry, handles NotFound and Limit""" """Find an LDAP entry, handles NotFound and Limit"""
@@ -87,7 +107,7 @@ class KDCProxyConfig(object):
msg = ('Unknown error while retrieving setting from %s: %s' % msg = ('Unknown error while retrieving setting from %s: %s' %
(self.ldap_uri, e)) (self.ldap_uri, e))
self.log.exception(msg) self.log.exception(msg)
raise CheckError(msg) raise FatalError(msg)
return entries[0] return entries[0]
def is_host_enabled(self): def is_host_enabled(self):
@@ -105,11 +125,13 @@ class KDCProxyConfig(object):
if not os.path.exists(self.conflink): if not os.path.exists(self.conflink):
return False return False
if not os.path.islink(self.conflink): if not os.path.islink(self.conflink):
raise CheckError("'%s' already exists, but it is not a symlink" % raise ConfigFileError(
self.conflink) "'%s' already exists, but it is not a symlink"
% self.conflink)
dest = os.readlink(self.conflink) dest = os.readlink(self.conflink)
if dest != self.conf: if dest != self.conf:
raise CheckError("'%s' points to '%s', expected '%s'" raise ConfigFileError(
"'%s' points to '%s', expected '%s'"
% (self.conflink, dest, self.conf)) % (self.conflink, dest, self.conf))
return True return True
@@ -117,7 +139,7 @@ class KDCProxyConfig(object):
"""Create symlink to enable KDC proxy support""" """Create symlink to enable KDC proxy support"""
try: try:
valid = self.validate_symlink() valid = self.validate_symlink()
except CheckError as e: except ConfigFileError as e:
self.log.warn("Cannot enable KDC proxy: %s " % e) self.log.warn("Cannot enable KDC proxy: %s " % e)
return False return False
@@ -165,16 +187,29 @@ class KDCProxyConfig(object):
def main(debug=DEBUG, time_limit=TIME_LIMIT): def main(debug=DEBUG, time_limit=TIME_LIMIT):
# initialize API without file logging # initialize API without file logging
if not api.isdone('bootstrap'): if not api.isdone('bootstrap'):
api.bootstrap(context='kdcproxyshim', log=None, debug=debug) api.bootstrap(context='ipa-httpd-kdcproxy', log=None, debug=debug)
standard_logging_setup(verbose=True, debug=debug) standard_logging_setup(verbose=True, debug=debug)
with KDCProxyConfig(time_limit) as cfg: try:
cfg = KDCProxyConfig(time_limit)
with cfg:
if cfg.is_host_enabled(): if cfg.is_host_enabled():
if cfg.create_symlink(): if cfg.create_symlink():
api.log.info('KDC proxy enabled') api.log.info('KDC proxy enabled')
return 0
else: else:
if cfg.remove_symlink(): if cfg.remove_symlink():
api.log.info('KDC proxy disabled') api.log.info('KDC proxy disabled')
return 0
except CheckError as e:
api.log.warn(str(e))
api.log.warn('Disabling KDC proxy')
cfg.remove_symlink()
return 0
except Exception as e:
api.log.error(str(e))
return 1
if __name__ == '__main__': if __name__ == '__main__':
main() sys.exit(main())