Hi, I've created a new patch that implements the KDC switch as a ExecStartPre hook in httpd.service.
Testing: If you are doing an upgrade of an existing installation, then you have to run ipa-server-update first. The update creates the config file /etc/ipa/kdcproxy/ipa-kdc-proxy.conf from a template. /usr/libexec/ipa/ipa-httpd-kdcproxy creates / removes the symlink /etc/httpd/conf.d/ipa-kdc-proxy.conf. The feature is enabled by default. Disable KDC Proxy on the current host: # ipa-ldap-updater /usr/share/ipa/kdcproxy-disable.ldif # systemctl restart httpd.service Enable KDC Proxy on the current host: # ipa-ldap-updater /usr/share/ipa/kdcproxy-enable.ldif # systemctl restart httpd.service Regards, Christian
From b860590e6859fc0edcd9543b1a0dc6e58d93afa6 Mon Sep 17 00:00:00 2001 From: Christian Heimes <chei...@redhat.com> Date: Tue, 23 Jun 2015 11:09:46 +0200 Subject: [PATCH] Provide Kerberos over HTTP (MS-KKDCP) Add integration of python-kdcproxy into FreeIPA to support the MS Kerberos KDC proxy protocol (MS-KKDCP), to allow KDC and KPASSWD client requests over HTTP and HTTPS. - freeipa-server now depends on python-kdcproxy >= 0.2.1. All kdcproxy dependencies are already satisfied. - The service's state is configured in cn=KDC,cn=$FQDN,cn=masters,cn=ipa, cn=etc,$SUFFIX. It's enabled, when ipaConfigString=kdcProxyEnabled is present. - The installers and update create a new Apache config file /etc/ipa/kdcproxy/ipa-kdc-proxy.conf that mounts a WSGI app on /KdcProxy. The app is run inside its own WSGI daemon group with a different uid and gid than the webui. - A ExecStartPre script in httpd.service symlinks the config file to /etc/httpd/conf.d/ iff ipaConfigString=kdcProxyEnabled is present. - The Apache config sets KDCPROXY_CONFIG=/etc/ipa/kdcproxy.conf, so that an existing config is not used. - python-kdcproxy is configured to *not* use DNS SRV lookups. The location of KDC and KPASSWD servers are read from /etc/krb5.conf. - The state of the service can be modified with two ldif files for ipa-ldap-updater. No CLI script is offered yet. Changes since the last patch: - WSGI shim module was removed in favor of the symlink approach. - Since the ExecStartPre scripts runs as root user, EXTERNAL GSSAPI bind can be used. This eliminates the need for a keytab, service principal and additional permission. https://www.freeipa.org/page/V4/KDC_Proxy https://fedorahosted.org/freeipa/ticket/4801 --- freeipa.spec.in | 26 +++++ init/systemd/httpd.service | 1 + install/conf/Makefile.am | 1 + install/conf/ipa-kdc-proxy.conf.template | 31 +++++ install/conf/ipa.conf | 6 +- install/share/Makefile.am | 3 + install/share/kdcproxy-disable.ldif | 3 + install/share/kdcproxy-enable.ldif | 6 + install/share/kdcproxy.conf | 4 + install/tools/Makefile.am | 5 + install/tools/ipa-httpd-kdcproxy | 180 +++++++++++++++++++++++++++++ ipaplatform/base/paths.py | 4 +- ipaserver/install/ipa_backup.py | 1 + ipaserver/install/kdcproxyinstance.py | 163 ++++++++++++++++++++++++++ ipaserver/install/server/install.py | 8 +- ipaserver/install/server/replicainstall.py | 8 +- ipaserver/install/server/upgrade.py | 8 ++ 17 files changed, 452 insertions(+), 6 deletions(-) create mode 100644 install/conf/ipa-kdc-proxy.conf.template create mode 100644 install/share/kdcproxy-disable.ldif create mode 100644 install/share/kdcproxy-enable.ldif create mode 100644 install/share/kdcproxy.conf create mode 100755 install/tools/ipa-httpd-kdcproxy create mode 100644 ipaserver/install/kdcproxyinstance.py diff --git a/freeipa.spec.in b/freeipa.spec.in index 809ac1e5bb877c85e29c082ecfb9ad91aa97b4f5..6b14650600016d9fa6f5baf01379c37af9b38eef 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -22,6 +22,10 @@ %define _hardened_build 1 +%define kdcproxy_user kdcproxy +%define kdcproxy_group kdcproxy +%define kdcproxy_home %{_sharedstatedir}/kdcproxy + Name: freeipa Version: __VERSION__ Release: __RELEASE__%{?dist} @@ -95,6 +99,7 @@ BuildRequires: p11-kit-devel BuildRequires: pki-base >= 10.2.4-1 BuildRequires: python-pytest-multihost >= 0.5 BuildRequires: python-pytest-sourceorder +BuildRequires: python-kdcproxy >= 0.2.1 %description IPA is an integrated solution to provide centrally managed Identity (machine, @@ -130,6 +135,7 @@ Requires: memcached Requires: python-memcached Requires: dbus-python Requires: systemd-units >= 38 +Requires(pre): shadow-utils Requires(pre): systemd-units Requires(post): systemd-units Requires: selinux-policy >= %{selinux_policy_version} @@ -140,6 +146,7 @@ Requires: pki-kra >= 10.2.4-1 Requires(preun): python systemd-units Requires(postun): python systemd-units Requires: python-dns >= 1.11.1 +Requires: python-kdcproxy >= 0.2.1 Requires: zip Requires: policycoreutils >= 2.1.12-5 Requires: tar @@ -429,6 +436,7 @@ ln -s ../../../..%{_sysconfdir}/ipa/html/browserconfig.html \ # So we can own our Apache configuration mkdir -p %{buildroot}%{_sysconfdir}/httpd/conf.d/ /bin/touch %{buildroot}%{_sysconfdir}/httpd/conf.d/ipa.conf +/bin/touch %{buildroot}%{_sysconfdir}/httpd/conf.d/ipa-kdc-proxy.conf /bin/touch %{buildroot}%{_sysconfdir}/httpd/conf.d/ipa-pki-proxy.conf /bin/touch %{buildroot}%{_sysconfdir}/httpd/conf.d/ipa-rewrite.conf mkdir -p %{buildroot}%{_usr}/share/ipa/html/ @@ -458,6 +466,10 @@ install daemons/dnssec/ipa-ods-exporter %{buildroot}%{_libexecdir}/ipa/ipa-ods-e # Web UI plugin dir mkdir -p %{buildroot}%{_usr}/share/ipa/ui/js/plugins +# KDC proxy config (Apache config sets KDCPROXY_CONFIG to load this file) +mkdir -p %{buildroot}%{_sysconfdir}/ipa/kdcproxy/ +install -m 644 install/share/kdcproxy.conf %{buildroot}%{_sysconfdir}/ipa/kdcproxy/kdcproxy.conf + # NOTE: systemd specific section mkdir -p %{buildroot}%{_tmpfilesdir} install -m 0644 init/systemd/ipa.conf.tmpfiles %{buildroot}%{_tmpfilesdir}/%{name}.conf @@ -551,6 +563,13 @@ if [ -e /usr/sbin/ipa_kpasswd ]; then # END fi +# create kdcproxy user +getent group %{kdcproxy_group} >/dev/null || groupadd -r %{kdcproxy_group} +getent passwd %{kdcproxy_user} >/dev/null || \ + /usr/sbin/useradd -r -m -c "IPA KDC Proxy User" -s /sbin/nologin \ + -g %{kdcproxy_group} -d %{kdcproxy_home} %{kdcproxy_user} +exit 0 + %postun server-trust-ad if [ "$1" -ge "1" ]; then if [ "`readlink %{_sysconfdir}/alternatives/winbind_krb5_locator.so`" == "/dev/null" ]; then @@ -683,9 +702,11 @@ fi %{_libexecdir}/ipa/ipa-dnskeysyncd %{_libexecdir}/ipa/ipa-dnskeysync-replica %{_libexecdir}/ipa/ipa-ods-exporter +%{_libexecdir}/ipa/ipa-httpd-kdcproxy %config(noreplace) %{_sysconfdir}/sysconfig/ipa_memcached %config(noreplace) %{_sysconfdir}/sysconfig/ipa-dnskeysyncd %config(noreplace) %{_sysconfdir}/sysconfig/ipa-ods-exporter +%config(noreplace) %{_sysconfdir}/ipa/kdcproxy/kdcproxy.conf %dir %attr(0700,apache,apache) %{_localstatedir}/run/ipa_memcached/ %dir %attr(0700,root,root) %{_localstatedir}/run/ipa/ %dir %attr(0700,apache,apache) %{_localstatedir}/run/httpd/ipa/ @@ -777,10 +798,14 @@ fi %config(noreplace) %{_sysconfdir}/ipa/html/browserconfig.html %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa-rewrite.conf %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa.conf +%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa-kdc-proxy.conf %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/httpd/conf.d/ipa-pki-proxy.conf +%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/kdcproxy/ipa-kdc-proxy.conf %{_usr}/share/ipa/ipa.conf %{_usr}/share/ipa/ipa-rewrite.conf +%{_usr}/share/ipa/ipa-kdc-proxy.conf.template %{_usr}/share/ipa/ipa-pki-proxy.conf +%{_usr}/share/ipa/kdcproxy.conf %ghost %attr(0644,root,apache) %config(noreplace) %{_usr}/share/ipa/html/ca.crt %ghost %attr(0644,root,apache) %{_usr}/share/ipa/html/configure.jar %ghost %attr(0644,root,apache) %{_usr}/share/ipa/html/kerberosauth.xpi @@ -903,6 +928,7 @@ fi %ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/ca.crt %dir %attr(0755,root,root) %{_sysconfdir}/ipa/nssdb %dir %attr(0755,root,root) %{_sysconfdir}/ipa/dnssec +%dir %attr(0755,root,root) %{_sysconfdir}/ipa/kdcproxy %ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/cert8.db %ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/key3.db %ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/secmod.db diff --git a/init/systemd/httpd.service b/init/systemd/httpd.service index 231f86f44808156e0eb20d67ef15bb7d19550e19..421de7d0781b7dcd7cc2742d63669dda27957cbd 100644 --- a/init/systemd/httpd.service +++ b/init/systemd/httpd.service @@ -2,3 +2,4 @@ [Service] Environment=KRB5CCNAME=/var/run/httpd/ipa/krbcache/krb5ccache +ExecStartPre=/usr/libexec/ipa/ipa-httpd-kdcproxy diff --git a/install/conf/Makefile.am b/install/conf/Makefile.am index 65e25bc94682d85428ccfbcba87137c0d4edc3d0..5daac776f71c5d01187b46d51044a07bf5fd717a 100644 --- a/install/conf/Makefile.am +++ b/install/conf/Makefile.am @@ -3,6 +3,7 @@ NULL = appdir = $(IPA_DATA_DIR) app_DATA = \ ipa.conf \ + ipa-kdc-proxy.conf.template \ ipa-pki-proxy.conf \ ipa-rewrite.conf \ $(NULL) diff --git a/install/conf/ipa-kdc-proxy.conf.template b/install/conf/ipa-kdc-proxy.conf.template new file mode 100644 index 0000000000000000000000000000000000000000..172ba8b5ee40db36a2436ea785d1b50f63d1bcba --- /dev/null +++ b/install/conf/ipa-kdc-proxy.conf.template @@ -0,0 +1,31 @@ +# Kerberos over HTTP / MS-KKDCP support (Kerberos KDC Proxy) +# +# The symlink from /etc/ipa/kdcproxy/ to /etc/httpd/conf.d/ is maintained +# by the ExecStartPre script /usr/libexec/ipa/ipa-httpd-kdcproxy in +# httpd.service +# +# Disable KDC Proxy on the current host: +# # ipa-ldap-updater /usr/share/ipa/kdcproxy-disable.ldif +# # systemctl restart httpd.service +# +# Enable KDC Proxy on the current host: +# # ipa-ldap-updater /usr/share/ipa/kdcproxy-enable.ldif +# # systemctl restart httpd.service +# + +SetEnv KDCPROXY_CONFIG $KDCPROXY_CONFIG + +WSGIDaemonProcess kdcproxy processes=2 threads=15 maximum-requests=5000 \ + user=kdcproxy group=kdcproxy display-name=%{GROUP} +WSGIImportScript /usr/lib/python2.7/site-packages/kdcproxy/__init__.py \ + process-group=kdcproxy application-group=kdcproxy +WSGIScriptAlias /KdcProxy /usr/lib/python2.7/site-packages/kdcproxy/__init__.py +WSGIScriptReloading Off + +<Location "/KdcProxy"> + Satisfy Any + Order Deny,Allow + Allow from all + WSGIProcessGroup kdcproxy + WSGIApplicationGroup kdcproxy +</Location> diff --git a/install/conf/ipa.conf b/install/conf/ipa.conf index 57de2f1a9543e1395f3eb46b045334f86cc8e79f..e2b602c8573078f517badac00a8c8c5bd593db28 100644 --- a/install/conf/ipa.conf +++ b/install/conf/ipa.conf @@ -41,9 +41,7 @@ WSGISocketPrefix /run/httpd/wsgi # Configure mod_wsgi handler for /ipa -WSGIDaemonProcess ipa processes=2 threads=1 maximum-requests=500 -WSGIProcessGroup ipa -WSGIApplicationGroup ipa +WSGIDaemonProcess ipa processes=2 threads=1 maximum-requests=500 display-name=%{GROUP} WSGIImportScript /usr/share/ipa/wsgi.py process-group=ipa application-group=ipa WSGIScriptAlias /ipa /usr/share/ipa/wsgi.py WSGIScriptReloading Off @@ -70,6 +68,8 @@ WSGIScriptReloading Off GssapiUseS4U2Proxy on Require valid-user ErrorDocument 401 /ipa/errors/unauthorized.html + WSGIProcessGroup ipa + WSGIApplicationGroup ipa </Location> # Turn off Apache authentication for sessions diff --git a/install/share/Makefile.am b/install/share/Makefile.am index 53f0ecf01d5b401b3361ce5969b18dd713ad246f..e88cf4e03609338329b072268631901741515eb9 100644 --- a/install/share/Makefile.am +++ b/install/share/Makefile.am @@ -84,6 +84,9 @@ app_DATA = \ sasl-mapping-fallback.ldif \ schema-update.ldif \ vault.update \ + kdcproxy.conf \ + kdcproxy-enable.ldif \ + kdcproxy-disable.ldif \ $(NULL) EXTRA_DIST = \ diff --git a/install/share/kdcproxy-disable.ldif b/install/share/kdcproxy-disable.ldif new file mode 100644 index 0000000000000000000000000000000000000000..bfc0b72c18a0c1e83d3cf50e57dbb6f0e66f087d --- /dev/null +++ b/install/share/kdcproxy-disable.ldif @@ -0,0 +1,3 @@ +# Disable MS-KKDCP protocol for the current host +dn: cn=KDC,cn=$FQDN,cn=masters,cn=ipa,cn=etc,$SUFFIX +remove:ipaConfigString:kdcProxyEnabled diff --git a/install/share/kdcproxy-enable.ldif b/install/share/kdcproxy-enable.ldif new file mode 100644 index 0000000000000000000000000000000000000000..92297152fcd4c9cf77195ab4661d4eab4b98e0c0 --- /dev/null +++ b/install/share/kdcproxy-enable.ldif @@ -0,0 +1,6 @@ +# Enable MS-KKDCP protocol for the current host +dn: cn=KDC,cn=$FQDN,cn=masters,cn=ipa,cn=etc,$SUFFIX +default:objectClass: nsContainer +default:objectClass: ipaConfigObject +default:cn: KDC +add: ipaConfigString: kdcProxyEnabled diff --git a/install/share/kdcproxy.conf b/install/share/kdcproxy.conf new file mode 100644 index 0000000000000000000000000000000000000000..530703d4aa67765a6a6a9cc82c81df7448c43608 --- /dev/null +++ b/install/share/kdcproxy.conf @@ -0,0 +1,4 @@ +[global] +configs = mit +use_dns = false + diff --git a/install/tools/Makefile.am b/install/tools/Makefile.am index e5d45c47966a503da9f25aec13175793a36962e4..147ce33a9d8a6471b46a3b6f36f6ce3e8237700b 100644 --- a/install/tools/Makefile.am +++ b/install/tools/Makefile.am @@ -35,6 +35,11 @@ EXTRA_DIST = \ $(sbin_SCRIPTS) \ $(NULL) +appdir = $(libexecdir)/ipa/ +app_SCRIPTS = \ + ipa-httpd-kdcproxy \ + $(NULL) + MAINTAINERCLEANFILES = \ *~ \ Makefile.in diff --git a/install/tools/ipa-httpd-kdcproxy b/install/tools/ipa-httpd-kdcproxy new file mode 100755 index 0000000000000000000000000000000000000000..e9cf380b6b6644381430629482f19fa3d9d542ae --- /dev/null +++ b/install/tools/ipa-httpd-kdcproxy @@ -0,0 +1,180 @@ +#!/usr/bin/env python2.7 +# Authors: +# Christian Heimes <chei...@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 os +import sys + +from ipalib import api, errors +from ipapython.ipa_log_manager import standard_logging_setup +from ipapython.ipaldap import IPAdmin +from ipapython.dn import DN +from ipaplatform.paths import paths + + +DEBUG = False +TIME_LIMIT = 2 + + +class CheckError(Exception): + """An unrecoverable error has occured""" + + +class KDCProxyConfig(object): + ipaconfig_flag = 'ipaKDCProxyEnabled' + + def __init__(self, time_limit=TIME_LIMIT): + self.time_limit = time_limit + self.con = None + self.log = api.log + 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""" + self.log.debug('ldap_uri: %s', self.ldap_uri) + try: + self.con = IPAdmin(ldap_uri=self.ldap_uri) + # EXTERNAL bind as root user + self.con.ldapi = True + self.con.do_bind(timeout=self.time_limit) + except errors.NetworkError as e: + msg = 'Failed to get setting from dirsrv: %s' % e + self.log.exception(msg) + raise CheckError(msg) + except Exception as e: + msg = ('Unknown error while retrieving setting from %s: %s' % + (self.ldap_uri, e)) + self.log.exception(msg) + raise CheckError(msg) + + def _find_entry(self, dn, attrs, filter, scope=IPAdmin.SCOPE_BASE): + """Find an LDAP entry, handles NotFound and Limit""" + try: + entries, truncated = self.con.find_entries( + filter, attrs, dn, scope, time_limit=self.time_limit) + if truncated: + raise errors.LimitsExceeded() + except errors.NotFound: + self.log.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)) + self.log.exception(msg) + raise CheckError(msg) + return entries[0] + + def is_host_enabled(self): + """Check replica specific flag""" + self.log.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) + self.log.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 CheckError("'%s' already exists, but it is not a symlink" % + self.conflink) + dest = os.readlink(self.conflink) + if dest != self.conf: + raise CheckError("'%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 CheckError as e: + self.log.warn("Cannot enable KDC proxy: %s " % e) + return False + + if valid: + self.log.debug("Symlink exists and is valid") + return True + + if not os.path.isfile(self.conf): + self.log.warn("'%s' does not exist", self.conf) + return False + + # create the symbolic link + self.log.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: + self.log.warn("Cannot disable KDC proxy: %s " % e) + return False + + if valid: + self.log.debug("Removing symlink '%s'", self.conflink) + os.unlink(self.conflink) + else: + self.log.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='kdcproxyshim', log=None, debug=debug) + standard_logging_setup(verbose=True, debug=debug) + + with KDCProxyConfig(time_limit) as cfg: + if cfg.is_host_enabled(): + if cfg.create_symlink(): + api.log.info('KDC proxy enabled') + else: + if cfg.remove_symlink(): + api.log.info('KDC proxy disabled') + +if __name__ == '__main__': + main() diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index e6b19181929b54f6d83701a0fdbc3c4a54364082..e847f93b543d187f9ec72788e17f67e7afe90c07 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -49,6 +49,8 @@ class BasePathNamespace(object): ALIAS_CACERT_ASC = "/etc/httpd/alias/cacert.asc" ALIAS_PWDFILE_TXT = "/etc/httpd/alias/pwdfile.txt" HTTPD_CONF_D_DIR = "/etc/httpd/conf.d/" + HTTPD_IPA_KDCPROXY_CONF = "/etc/ipa/kdcproxy/ipa-kdc-proxy.conf" + HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/httpd/conf.d/ipa-kdc-proxy.conf" HTTPD_IPA_PKI_PROXY_CONF = "/etc/httpd/conf.d/ipa-pki-proxy.conf" HTTPD_IPA_REWRITE_CONF = "/etc/httpd/conf.d/ipa-rewrite.conf" HTTPD_IPA_CONF = "/etc/httpd/conf.d/ipa.conf" @@ -342,7 +344,7 @@ class BasePathNamespace(object): DB2LDIF = '/usr/sbin/db2ldif' BAK2DB = '/usr/sbin/bak2db' DB2BAK = '/usr/sbin/db2bak' - + KDCPROXY_CONFIG = '/etc/ipa/kdcproxy/kdcproxy.conf' path_namespace = BasePathNamespace diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py index 01871c7b57a3e491cebf8fe81f040268992f1ada..f7e032ae572f404f84ce48c1a5d72e78c31b4766 100644 --- a/ipaserver/install/ipa_backup.py +++ b/ipaserver/install/ipa_backup.py @@ -146,6 +146,7 @@ class Backup(admintool.AdminTool): paths.LIMITS_CONF, paths.HTTPD_PASSWORD_CONF, paths.IPA_KEYTAB, + paths.HTTPD_IPA_KDCPROXY_CONF, paths.HTTPD_IPA_PKI_PROXY_CONF, paths.HTTPD_IPA_REWRITE_CONF, paths.HTTPD_NSS_CONF, diff --git a/ipaserver/install/kdcproxyinstance.py b/ipaserver/install/kdcproxyinstance.py new file mode 100644 index 0000000000000000000000000000000000000000..fe951420d5cab2e1800de8ef7a6f4386b4afc241 --- /dev/null +++ b/ipaserver/install/kdcproxyinstance.py @@ -0,0 +1,163 @@ +# Authors: Christian Heimes <chei...@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/>. +# +import os + +from ipalib import errors +from ipalib.krb_utils import krb5_format_service_principal_name +from ipapython import ipautil +from ipapython import sysrestore +from ipapython.dn import DN +from ipapython.ipa_log_manager import root_logger +from ipaplatform.paths import paths +from ipaplatform import services + +import installutils +import service + + +class KDCProxyInstance(service.SimpleServiceInstance): + def __init__(self, fstore): + service.SimpleServiceInstance.__init__(self, "kdcproxy") + if fstore: + self.fstore = fstore + else: + self.fstore = sysrestore.FileStore(paths.SYSRESTORE) + # KDC proxy runs inside Apache HTTPD + self.service = None + self.httpd_service_name = 'httpd' + self.httpd_service = services.service(self.httpd_service_name) + + # HTTPD + def start_httpd(self, instance_name="", capture_output=True, wait=True): + self.httpd_service.start(instance_name, capture_output=capture_output, + wait=wait) + + def stop_httpd(self, instance_name="", capture_output=True): + self.httpd_service.stop(instance_name, capture_output=capture_output) + + def restart_httpd(self, instance_name="", capture_output=True, wait=True): + self.httpd_service.restart(instance_name, + capture_output=capture_output, + wait=wait) + + def is_httpd_running(self): + return self.httpd_service.is_running() + + def is_httpd_enabled(self): + return self.httpd_service.is_enabled() + + def is_configured(self): + return os.path.isfile(paths.HTTPD_IPA_KDCPROXY_CONF) + + def disable(self): + pass + + def create_instance(self, gensvc_name=None, fqdn=None, dm_password=None, + ldap_suffix=None, realm=None): + assert gensvc_name == 'KDCPROXY' + self.gensvc_name = gensvc_name + self.fqdn = fqdn + self.dm_password = dm_password + self.suffix = ldap_suffix + self.realm = realm + self.principal = krb5_format_service_principal_name( + gensvc_name, self.fqdn, self.realm) + if not realm: + self.ldapi = False + self.sub_dict = dict( + REALM=realm, + FQDN=fqdn, + KDCPROXY_CONFIG=paths.KDCPROXY_CONFIG, + ) + if not self.admin_conn: + self.ldap_connect() + + self.step("Enable %s in KDC" % self.service_name, + self.__enable_kdcproxy) + self.step("configuring httpd", self.__configure_http) + self.step("(re)starting %s " % self.httpd_service_name, + self.__restart_httpd) + self.start_creation("Configuring %s" % self.service_name) + + def __enable_kdcproxy(self): + entry_name = DN(('cn', 'KDC'), ('cn', self.fqdn), ('cn', 'masters'), + ('cn', 'ipa'), ('cn', 'etc'), self.suffix) + attr_name = 'kdcProxyEnabled' + + try: + entry = self.admin_conn.get_entry(entry_name, ['ipaConfigString']) + except errors.NotFound: + pass + else: + if any(attr_name.lower() == val.lower() + for val in entry.get('ipaConfigString', [])): + root_logger.debug("service KDCPROXY already enabled") + return + + entry.setdefault('ipaConfigString', []).append(attr_name) + try: + self.admin_conn.update_entry(entry) + except errors.EmptyModlist: + root_logger.debug("service KDCPROXY already enabled") + return + except: + root_logger.debug("failed to enable service KDCPROXY") + raise + + root_logger.debug("service KDCPROXY enabled") + return + + entry = self.admin_conn.make_entry( + entry_name, + objectclass=["nsContainer", "ipaConfigObject"], + cn=['KDC'], + ipaconfigstring=[attr_name] + ) + + try: + self.admin_conn.add_entry(entry) + except errors.DuplicateEntry: + root_logger.debug("failed to add service KDCPROXY entry") + raise + + def __configure_http(self): + target_fname = paths.HTTPD_IPA_KDCPROXY_CONF + http_txt = ipautil.template_file( + ipautil.SHARE_DIR + "ipa-kdc-proxy.conf.template", self.sub_dict) + self.fstore.backup_file(target_fname) + with open(target_fname, 'w') as f: + f.write(http_txt) + os.chmod(target_fname, 0644) + + def __restart_httpd(self): + self.backup_state("running", self.is_httpd_running()) + self.restart_httpd() + + def uninstall(self): + if self.is_configured(): + self.print_msg("Unconfiguring %s" % self.service_name) + + self.stop_httpd() + + running = self.restore_state("running") + installutils.remove_file(paths.HTTPD_IPA_KDCPROXY_CONF) + installutils.remove_file(paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK) + + if running: + self.start_httpd() diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index bde34851871f9b9f2bdf6dfecfd428755cc42e31..e0df9eaeda6b814f706adf85cc26af6be836492c 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -29,7 +29,7 @@ import ipaclient.ntpconf from ipaserver.install import ( bindinstance, ca, cainstance, certs, dns, dsinstance, httpinstance, installutils, kra, krbinstance, memcacheinstance, ntpinstance, - otpdinstance, replication, service, sysupgrade) + otpdinstance, kdcproxyinstance, replication, service, sysupgrade) from ipaserver.install.installutils import ( IPA_MODULES, BadHostError, get_fqdn, get_server_ip_address, is_ipa_configured, load_pkcs12, read_password, verify_fqdn) @@ -823,6 +823,11 @@ def install(installer): ca_is_configured=setup_ca) tasks.restore_context(paths.CACHE_IPA_SESSIONS) + # Create KDCProxyInstance + kdcproxy = kdcproxyinstance.KDCProxyInstance(fstore) + kdcproxy.create_instance('KDCPROXY', host_name, dm_password, + ipautil.realm_to_suffix(realm_name)) + # Export full CA chain ca_db = certs.CertDB(realm_name) os.chmod(CACERT, 0644) @@ -1065,6 +1070,7 @@ def uninstall(installer): dns.uninstall() + kdcproxyinstance.KDCProxyInstance(fstore).uninstall() httpinstance.HTTPInstance(fstore).uninstall() krbinstance.KrbInstance(fstore).uninstall() dsinstance.DsInstance(fstore=fstore).uninstall() diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 303d0bcf2907165b9cb7044945bdb3bd330e508d..dafde23fc382d36e87b3263f49a23cc419240a93 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -26,7 +26,7 @@ import ipaclient.ntpconf from ipaserver.install import ( bindinstance, ca, cainstance, certs, dns, dsinstance, httpinstance, installutils, kra, krbinstance, memcacheinstance, ntpinstance, - otpdinstance, service) + otpdinstance, kdcproxyinstance, service) from ipaserver.install.installutils import create_replica_config from ipaserver.install.replication import ( ReplicationManager, replica_conn_check) @@ -590,6 +590,12 @@ def install(installer): CA.import_ra_cert(config.dir + "/ra.p12") CA.fix_ra_perms() + kdcproxy = kdcproxyinstance.KDCProxyInstance(fstore) + kdcproxy.create_instance('KDCPROXY', + config.host_name, + config.dirman_password, + ipautil.realm_to_suffix(config.realm_name)) + # The DS instance is created before the keytab, add the SSL cert we # generated ds.add_cert_to_service() diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index a9dac59e009f5646630b7a8dd0e92f39b5a44a86..9c8c05d3dc15b6b64ae9f3e80863ec900709ee09 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -31,6 +31,7 @@ from ipaserver.install import service from ipaserver.install import cainstance from ipaserver.install import certs from ipaserver.install import otpdinstance +from ipaserver.install import kdcproxyinstance from ipaserver.install import sysupgrade from ipaserver.install import dnskeysyncinstance from ipaserver.install.upgradeinstance import IPAUpgrade @@ -1408,6 +1409,13 @@ def upgrade_configuration(): dnskeysyncd.create_instance(fqdn, api.env.realm) dnskeysyncd.start_dnskeysyncd() + # Install KDCProxy configuration file + kdcproxy = kdcproxyinstance.KDCProxyInstance(fstore) + if not kdcproxy.is_configured(): + kdcproxy.create_instance('KDCPROXY', fqdn, None, + ipautil.realm_to_suffix(api.env.realm), + realm=api.env.realm) + cleanup_kdc(fstore) cleanup_adtrust(fstore) setup_firefox_extension(fstore) -- 2.4.3
signature.asc
Description: OpenPGP digital signature
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code