This is hopefully the final patch. I've tested a fresh installation and
upgrade from 4.2 alpha 1.

Christian
From f503bb15304edea863ba1bad91657b1f880f0e4b Mon Sep 17 00:00:00 2001
From: Christian Heimes <chei...@redhat.com>
Date: Tue, 23 Jun 2015 17:01:00 +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 httpd.service also sets KDCPROXY_CONFIG=/etc/ipa/kdcproxy.conf,
  so that an existing config is not used. SetEnv from Apache config does
  not work here, because it doesn't set an OS env var.
- 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.
- Require python-kdcproxy 0.3
- Set env var in httpd.service instead of SetEnv

https://www.freeipa.org/page/V4/KDC_Proxy

https://fedorahosted.org/freeipa/ticket/4801
---
 freeipa.spec.in                          |  26 +++++
 init/systemd/httpd.service               |   2 +
 install/conf/Makefile.am                 |   1 +
 install/conf/ipa-kdc-proxy.conf.template |  30 ++++++
 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/httpinstance.py        |  65 ++++++++++-
 ipaserver/install/ipa_backup.py          |   1 +
 14 files changed, 331 insertions(+), 5 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

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 809ac1e5bb877c85e29c082ecfb9ad91aa97b4f5..80331e60006829c77c7994d600318fc331a6b711 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.3
 
 %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.3
 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..e68f39eca759db50ad18d8db1faa3b704cb15ede 100644
--- a/init/systemd/httpd.service
+++ b/init/systemd/httpd.service
@@ -2,3 +2,5 @@
 
 [Service]
 Environment=KRB5CCNAME=/var/run/httpd/ipa/krbcache/krb5ccache
+Environment=KDCPROXY_CONFIG=/etc/ipa/kdcproxy/kdcproxy.conf
+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..7b884800820ce3a826be73fc96629500ffcb156e
--- /dev/null
+++ b/install/conf/ipa-kdc-proxy.conf.template
@@ -0,0 +1,30 @@
+# 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. The service also sets the environment variable
+# KDCPROXY_CONFIG to $KDCPROXY_CONFIG.
+#
+# 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
+#
+
+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..c71f9cccfe0c05e1484aac7cfcd6801050ed51ab
--- /dev/null
+++ b/install/tools/ipa-httpd-kdcproxy
@@ -0,0 +1,180 @@
+#!/usr/bin/python2
+# 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/httpinstance.py b/ipaserver/install/httpinstance.py
index 31eab022d97a3105e2086b5cf4479c0d1e2b525b..f168d7a6ea999934b483fa7be39aec59e641b42f 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -33,15 +33,16 @@ import installutils
 from ipapython import sysrestore
 from ipapython import ipautil
 from ipapython import dogtag
+from ipapython.dn import DN
 from ipapython.ipa_log_manager import root_logger
 import ipapython.errors
 from ipaserver.install import sysupgrade
 from ipalib import api
+from ipalib import errors
 from ipaplatform.tasks import tasks
 from ipaplatform.paths import paths
 from ipaplatform import services
 
-
 SELINUX_BOOLEAN_SETTINGS = dict(
     httpd_can_network_connect='on',
     httpd_manage_ipa='on',
@@ -109,6 +110,7 @@ class HTTPInstance(service.Service):
             DOMAIN=self.domain,
             AUTOREDIR='' if auto_redirect else '#',
             CRL_PUBLISH_PATH=dogtag.install_constants.CRL_PUBLISH_PATH,
+            KDCPROXY_CONFIG=paths.KDCPROXY_CONFIG,
         )
         self.ca_file = ca_file
         if ca_is_configured is not None:
@@ -136,6 +138,9 @@ class HTTPInstance(service.Service):
         self.step("creating a keytab for httpd", self.__create_http_keytab)
         self.step("clean up any existing httpd ccache", self.remove_httpd_ccache)
         self.step("configuring SELinux for httpd", self.configure_selinux_for_httpd)
+        if not self.is_kdcprox_configured():
+            self.step("create KDC proxy config", self.create_kdcproxy_conf)
+            self.step("enable KDC proxy", self.enable_kdcproxy)
         self.step("restarting httpd", self.__start)
         self.step("configuring httpd to start on boot", self.__enable)
 
@@ -381,6 +386,62 @@ class HTTPInstance(service.Service):
         ca_db = certs.CertDB(self.realm)
         ca_db.publish_ca_cert(paths.CA_CRT)
 
+    def is_kdcprox_configured(self):
+        """Check if KDC proxy has already been configured in the past"""
+        return os.path.isfile(paths.HTTPD_IPA_KDCPROXY_CONF)
+
+    def enable_kdcproxy(self):
+        """Add ipaConfigString=kdcProxyEnabled to cn=KDC"""
+        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 create_kdcproxy_conf(self):
+        """Create ipa-kdc-proxy.conf in /etc/ipa/kdcproxy"""
+        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 uninstall(self):
         if self.is_configured():
             self.print_msg("Unconfiguring web server")
@@ -420,6 +481,8 @@ class HTTPInstance(service.Service):
         installutils.remove_file(paths.HTTPD_IPA_REWRITE_CONF)
         installutils.remove_file(paths.HTTPD_IPA_CONF)
         installutils.remove_file(paths.HTTPD_IPA_PKI_PROXY_CONF)
+        installutils.remove_file(paths.HTTPD_IPA_KDCPROXY_CONF)
+        installutils.remove_file(paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK)
 
         # Restore SELinux boolean states
         boolean_states = {name: self.restore_state(name)
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,
-- 
2.4.3

Attachment: 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

Reply via email to