mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-27 00:26:33 -06:00
6d02eddd3e
Replace the @PYTHONSHEBANG@ substitution with a valid #!/usr/bin/python3 shebang. This turns Python .in files into valid Python files. The files can now be checked with pylint and IDEs recognize the files as Python files. The shebang is still replaced with "#!$(PYTHON) -E" to support platform-python. Related: https://pagure.io/freeipa/issue/7984 Signed-off-by: Christian Heimes <cheimes@redhat.com> Reviewed-By: Francois Cami <fcami@redhat.com>
218 lines
6.8 KiB
Python
218 lines
6.8 KiB
Python
#!/usr/bin/python3
|
|
# Authors:
|
|
# Christian Heimes <cheimes@redhat.com>
|
|
#
|
|
# Copyright (C) 2015 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/>.
|
|
#
|
|
"""ipa-httpd-kdproxy
|
|
|
|
This script creates or removes the symlink from /etc/ipa/ipa-kdc-proxy.conf
|
|
to /etc/httpd/conf.d/. It's called from ExecStartPre hook in httpd.service.
|
|
"""
|
|
import logging
|
|
import os
|
|
import socket
|
|
import sys
|
|
|
|
from ipalib import api, errors
|
|
from ipapython.ipa_log_manager import standard_logging_setup
|
|
from ipapython.ipaldap import LDAPClient
|
|
from ipapython.dn import DN
|
|
from ipaplatform.paths import paths
|
|
|
|
logger = logging.getLogger(os.path.basename(__file__))
|
|
|
|
|
|
DEBUG = False
|
|
TIME_LIMIT = 2
|
|
|
|
|
|
class Error(Exception):
|
|
"""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:
|
|
ipaconfig_flag = 'ipaKDCProxyEnabled'
|
|
|
|
def __init__(self, time_limit=TIME_LIMIT):
|
|
self.time_limit = time_limit
|
|
self.con = None
|
|
self.ldap_uri = api.env.ldap_uri
|
|
self.kdc_dn = DN(('cn', 'KDC'), ('cn', api.env.host),
|
|
('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
|
|
api.env.basedn)
|
|
self.conf = paths.HTTPD_IPA_KDCPROXY_CONF
|
|
self.conflink = paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK
|
|
|
|
def _ldap_con(self):
|
|
"""Establish LDAP connection"""
|
|
logger.debug('ldap_uri: %s', self.ldap_uri)
|
|
try:
|
|
self.con = LDAPClient(self.ldap_uri)
|
|
self.con.external_bind()
|
|
except (errors.NetworkError, socket.timeout) as e:
|
|
msg = 'Unable to connect to dirsrv: %s' % e
|
|
raise CheckError(msg)
|
|
except errors.AuthorizationError as e:
|
|
msg = 'Authorization error: %s' % e
|
|
raise CheckError(msg)
|
|
except Exception as e:
|
|
msg = ('Unknown error while retrieving setting from %s: %s' %
|
|
(self.ldap_uri, e))
|
|
logger.exception('%s', msg)
|
|
raise FatalError(msg)
|
|
|
|
def _find_entry(self, dn, attrs, filter, scope=LDAPClient.SCOPE_BASE):
|
|
"""Find an LDAP entry, handles NotFound and Limit"""
|
|
try:
|
|
entries = self.con.get_entries(
|
|
dn, scope, filter, attrs, time_limit=self.time_limit)
|
|
except errors.NotFound:
|
|
logger.debug('Entry not found: %s', dn)
|
|
return None
|
|
except Exception as e:
|
|
msg = ('Unknown error while retrieving setting from %s: %s' %
|
|
(self.ldap_uri, e))
|
|
logger.exception('%s', msg)
|
|
raise FatalError(msg)
|
|
return entries[0]
|
|
|
|
def is_host_enabled(self):
|
|
"""Check replica specific flag"""
|
|
logger.debug('Read settings from dn: %s', self.kdc_dn)
|
|
srcfilter = self.con.make_filter(
|
|
{'ipaConfigString': u'kdcProxyEnabled'}
|
|
)
|
|
entry = self._find_entry(self.kdc_dn, ['cn'], srcfilter)
|
|
logger.debug('%s ipaConfigString: %s', self.kdc_dn, entry)
|
|
return entry is not None
|
|
|
|
def validate_symlink(self):
|
|
"""Validate symlink in Apache conf.d"""
|
|
if not os.path.exists(self.conflink):
|
|
return False
|
|
if not os.path.islink(self.conflink):
|
|
raise ConfigFileError(
|
|
"'%s' already exists, but it is not a symlink"
|
|
% self.conflink)
|
|
dest = os.readlink(self.conflink)
|
|
if dest != self.conf:
|
|
raise ConfigFileError(
|
|
"'%s' points to '%s', expected '%s'"
|
|
% (self.conflink, dest, self.conf))
|
|
return True
|
|
|
|
def create_symlink(self):
|
|
"""Create symlink to enable KDC proxy support"""
|
|
try:
|
|
valid = self.validate_symlink()
|
|
except ConfigFileError as e:
|
|
logger.warning("Cannot enable KDC proxy: %s ", e)
|
|
return False
|
|
|
|
if valid:
|
|
logger.debug("Symlink exists and is valid")
|
|
return True
|
|
|
|
if not os.path.isfile(self.conf):
|
|
logger.warning("'%s' does not exist", self.conf)
|
|
return False
|
|
|
|
# create the symbolic link
|
|
logger.debug("Creating symlink from '%s' to '%s'",
|
|
self.conf, self.conflink)
|
|
os.symlink(self.conf, self.conflink)
|
|
return True
|
|
|
|
def remove_symlink(self):
|
|
"""Delete symlink to disable KDC proxy support"""
|
|
try:
|
|
valid = self.validate_symlink()
|
|
except CheckError as e:
|
|
logger.warning("Cannot disable KDC proxy: %s ", e)
|
|
return False
|
|
|
|
if valid:
|
|
logger.debug("Removing symlink '%s'", self.conflink)
|
|
os.unlink(self.conflink)
|
|
else:
|
|
logger.debug("Symlink '%s' has already been removed.",
|
|
self.conflink)
|
|
|
|
return True
|
|
|
|
def __enter__(self):
|
|
self._ldap_con()
|
|
return self
|
|
|
|
def __exit__(self, exc_type, exc_value, traceback):
|
|
if self.con is not None:
|
|
self.con.unbind()
|
|
self.con = None
|
|
|
|
|
|
def main(debug=DEBUG, time_limit=TIME_LIMIT):
|
|
# initialize API without file logging
|
|
if not api.isdone('bootstrap'):
|
|
api.bootstrap(context='server', confdir=paths.ETC_IPA,
|
|
log=None, debug=debug)
|
|
standard_logging_setup(verbose=True, debug=debug)
|
|
|
|
try:
|
|
cfg = KDCProxyConfig(time_limit)
|
|
with cfg:
|
|
if cfg.is_host_enabled():
|
|
if cfg.create_symlink():
|
|
logger.info('KDC proxy enabled')
|
|
return 0
|
|
else:
|
|
if cfg.remove_symlink():
|
|
logger.info('KDC proxy disabled')
|
|
return 0
|
|
except CheckError as e:
|
|
logger.warning('%s', str(e))
|
|
logger.warning('Disabling KDC proxy')
|
|
cfg.remove_symlink()
|
|
return 0
|
|
except Exception as e:
|
|
logger.error('%s', str(e))
|
|
return 1
|
|
else:
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|