From 38c66896de1769077cd5b057133606ec5eeaf62b Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Thu, 1 Dec 2016 11:37:20 -0500 Subject: [PATCH] Generate tmpfiles config at install time We do not want to generate runtime directories just because the packages are installed, but only if the server is actually setup and run. Also this will be needed later because we will create a user at install time and some tmpfiles will need to be owned by this user. As we are changing this code also rationalize the directory structure and move it from the http rundir to the ipa specific rundir. https://fedorahosted.org/freeipa/ticket/5959 Signed-off-by: Simo Sorce Reviewed-By: Jan Cholasta --- configure.ac | 1 - freeipa.spec.in | 7 +----- init/Makefile.am | 2 +- init/tmpfilesd/Makefile.am | 20 ----------------- init/tmpfilesd/ipa.conf.in | 4 ---- install/conf/ipa.conf | 2 +- install/share/Makefile.am | 1 + install/share/ipa.conf.tmpfiles | 2 ++ ipaplatform/base/paths.py | 5 +++-- ipaplatform/base/tasks.py | 8 +++++++ ipaplatform/redhat/tasks.py | 22 +++++++++++++++++++ ipaserver/dcerpc.py | 17 +++++++-------- ipaserver/install/server/install.py | 6 ++++++ ipaserver/install/server/replicainstall.py | 3 +++ ipaserver/install/server/upgrade.py | 4 ++++ ipaserver/rpcserver.py | 25 ++++++++++++++++------ ipaserver/session.py | 16 -------------- 17 files changed, 78 insertions(+), 67 deletions(-) delete mode 100644 init/tmpfilesd/Makefile.am delete mode 100644 init/tmpfilesd/ipa.conf.in create mode 100644 install/share/ipa.conf.tmpfiles diff --git a/configure.ac b/configure.ac index 8fdc73138..a79504372 100644 --- a/configure.ac +++ b/configure.ac @@ -523,7 +523,6 @@ AC_CONFIG_FILES([ daemons/ipa-slapi-plugins/ipa-range-check/Makefile daemons/ipa-slapi-plugins/topology/Makefile init/systemd/Makefile - init/tmpfilesd/Makefile init/Makefile install/Makefile install/certmonger/Makefile diff --git a/freeipa.spec.in b/freeipa.spec.in index b65588a57..8a050cc5f 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -1189,12 +1189,6 @@ fi %config(noreplace) %{_sysconfdir}/sysconfig/ipa-dnskeysyncd %config(noreplace) %{_sysconfdir}/sysconfig/ipa-ods-exporter %config(noreplace) %{_sysconfdir}/ipa/kdcproxy/kdcproxy.conf -%dir %attr(0700,root,root) %{_localstatedir}/run/ipa/ -%dir %attr(0700,apache,apache) %{_localstatedir}/run/httpd/ipa/ -%dir %attr(0700,apache,apache) %{_localstatedir}/run/httpd/ipa/clientcaches/ -%dir %attr(0700,apache,apache) %{_localstatedir}/run/httpd/ipa/krbcache/ -# NOTE: systemd specific section -%{_tmpfilesdir}/ipa.conf %attr(644,root,root) %{_unitdir}/ipa-custodia.service %ghost %attr(644,root,root) %{etc_systemd_dir}/httpd.d/ipa.conf # END @@ -1204,6 +1198,7 @@ fi %{_usr}/share/ipa/*.ldif %{_usr}/share/ipa/*.uldif %{_usr}/share/ipa/*.template +%{_usr}/share/ipa/ipa.conf.tmpfiles %dir %{_usr}/share/ipa/advise %dir %{_usr}/share/ipa/advise/legacy %{_usr}/share/ipa/advise/legacy/*.template diff --git a/init/Makefile.am b/init/Makefile.am index 8f4d1d0a8..bee424391 100644 --- a/init/Makefile.am +++ b/init/Makefile.am @@ -2,7 +2,7 @@ # AUTOMAKE_OPTIONS = 1.7 -SUBDIRS = systemd tmpfilesd +SUBDIRS = systemd dist_sysconfenv_DATA = \ ipa-dnskeysyncd \ diff --git a/init/tmpfilesd/Makefile.am b/init/tmpfilesd/Makefile.am deleted file mode 100644 index 82afa6ad5..000000000 --- a/init/tmpfilesd/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -dist_noinst_DATA = \ - ipa.conf.in - -systemdtmpfiles_DATA = \ - ipa.conf - -CLEANFILES = $(systemdtmpfiles_DATA) - -%: %.in Makefile - sed -e 's|@localstatedir[@]|$(localstatedir)|g' '$(srcdir)/$@.in' >$@ - -# create empty directories as needed -# DESTDIR might not be set, in that case default to system root -DESTDIR ?= / -install-data-hook: - for conf in $(systemdtmpfiles_DATA); do \ - systemd-tmpfiles --remove --create --boot \ - --root $(DESTDIR) \ - $(DESTDIR)$(systemdtmpfilesdir)/$${conf} || :; \ - done diff --git a/init/tmpfilesd/ipa.conf.in b/init/tmpfilesd/ipa.conf.in deleted file mode 100644 index 5ac96f20f..000000000 --- a/init/tmpfilesd/ipa.conf.in +++ /dev/null @@ -1,4 +0,0 @@ -d @localstatedir@/run/ipa 0700 root root -d @localstatedir@/run/httpd/ipa 0700 apache apache -d @localstatedir@/run/httpd/ipa/clientcaches 0700 apache apache -d @localstatedir@/run/httpd/ipa/krbcache 0700 apache apache diff --git a/install/conf/ipa.conf b/install/conf/ipa.conf index 6ae416353..ce2ea74a1 100644 --- a/install/conf/ipa.conf +++ b/install/conf/ipa.conf @@ -71,7 +71,7 @@ WSGIScriptReloading Off GssapiCredStore keytab:/etc/httpd/conf/ipa.keytab GssapiCredStore client_keytab:/etc/httpd/conf/ipa.keytab - GssapiDelegCcacheDir /var/run/httpd/ipa/clientcaches + GssapiDelegCcacheDir /var/run/ipa/ccaches GssapiUseS4U2Proxy on GssapiAllowedMech krb5 Require valid-user diff --git a/install/share/Makefile.am b/install/share/Makefile.am index 6f35a329e..72f474a47 100644 --- a/install/share/Makefile.am +++ b/install/share/Makefile.am @@ -88,6 +88,7 @@ dist_app_DATA = \ kdcproxy-disable.uldif \ ipa-httpd.conf.template \ gssapi.login \ + ipa.conf.tmpfiles \ $(NULL) kdcproxyconfdir = $(IPA_SYSCONF_DIR)/kdcproxy diff --git a/install/share/ipa.conf.tmpfiles b/install/share/ipa.conf.tmpfiles new file mode 100644 index 000000000..3037787da --- /dev/null +++ b/install/share/ipa.conf.tmpfiles @@ -0,0 +1,2 @@ +d /var/run/ipa 0700 root root +d /var/run/ipa/ccaches 0700 apache apache diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index 44108e52a..d62ffa224 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -130,6 +130,7 @@ class BasePathNamespace(object): SYSTEMD_SSSD_SERVICE = "/etc/systemd/system/multi-user.target.wants/sssd.service" SYSTEMD_PKI_TOMCAT_SERVICE = "/etc/systemd/system/pki-tomcatd.target.wants/pki-tomcatd@pki-tomcat.service" ETC_TMPFILESD_DIRSRV = "/etc/tmpfiles.d/dirsrv-%s.conf" + ETC_TMPFILESD_IPA = "/etc/tmpfiles.d/ipa.conf" DNSSEC_TRUSTED_KEY = "/etc/trusted-key.key" HOME_DIR = "/home" PROC_FIPS_ENABLED = "/proc/sys/crypto/fips_enabled" @@ -325,10 +326,10 @@ class BasePathNamespace(object): OPENDNSSEC_KASP_DB = "/var/opendnssec/kasp.db" IPA_ODS_EXPORTER_CCACHE = "/var/opendnssec/tmp/ipa-ods-exporter.ccache" VAR_RUN_DIRSRV_DIR = "/var/run/dirsrv" - KRB5CC_HTTPD = "/var/run/httpd/ipa/krbcache/krb5ccache" + IPA_CCACHES = "/var/run/ipa/ccaches" + KRB5CC_HTTPD = "/var/run/ipa/ccaches/http.ccache" IPA_RENEWAL_LOCK = "/var/run/ipa/renewal.lock" SVC_LIST_FILE = "/var/run/ipa/services.list" - IPA_HTTPD_DIR = "/var/run/httpd" KRB5CC_SAMBA = "/var/run/samba/krb5cc_samba" SLAPD_INSTANCE_SOCKET_TEMPLATE = "/var/run/slapd-%s.socket" ALL_SLAPD_INSTANCE_SOCKETS = "/var/run/slapd-*.socket" diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py index 8cf6fded1..49b87613f 100644 --- a/ipaplatform/base/tasks.py +++ b/ipaplatform/base/tasks.py @@ -243,6 +243,14 @@ class BaseTaskNamespace(object): """ raise NotImplementedError() + def configure_tmpfiles(self): + """Configure tmpfiles to be created at boot""" + raise NotImplementedError() + + def create_tmpfiles_dirs(self): + """Create run dirs for the install phase""" + raise NotImplementedError() + def configure_httpd_service_ipa_conf(self): """Configure httpd service to work with IPA""" raise NotImplementedError() diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py index 9dd71b453..1191acd07 100644 --- a/ipaplatform/redhat/tasks.py +++ b/ipaplatform/redhat/tasks.py @@ -26,6 +26,8 @@ system tasks. from __future__ import print_function import os +import pwd +import shutil import socket import base64 import traceback @@ -497,4 +499,24 @@ class RedHatTaskNamespace(BaseTaskNamespace): pass return False + def _create_tmpfiles_dir(self, name, mode, uid, gid): + if not os.path.exists(name): + os.mkdir(name) + os.chmod(name, mode) + os.chown(name, uid, gid) + + def create_tmpfiles_dirs(self): + parent = os.path.dirname(paths.IPA_CCACHES) + pent = pwd.getpwnam(constants.HTTPD_USER) + self._create_tmpfiles_dir(parent, 0o711, 0, 0) + self._create_tmpfiles_dir(paths.IPA_CCACHES, 0o770, + pent.pw_uid, pent.pw_gid) + + def configure_tmpfiles(self): + shutil.copy( + os.path.join(paths.USR_SHARE_IPA_DIR, 'ipa.conf.tmpfiles'), + paths.ETC_TMPFILESD_IPA + ) + + tasks = RedHatTaskNamespace() diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py index e37d0ebdd..aa790b75f 100644 --- a/ipaserver/dcerpc.py +++ b/ipaserver/dcerpc.py @@ -51,7 +51,6 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms from cryptography.hazmat.backends import default_backend import ldap as _ldap from ipapython import ipaldap -from ipaserver.session import krbccache_dir, krbccache_prefix from dns import resolver, rdatatype from dns.exception import DNSException import pysss_nss_idmap @@ -639,8 +638,8 @@ class DomainValidator(object): Initializes ccache with http service credentials. Applies session code defaults for ccache directory and naming prefix. - Session code uses krbccache_prefix+, we use - krbccache_prefix++ so there is no clash. + Session code uses kinit_+, we use + kinit_++ so there is no clash. Returns tuple (ccache path, principal) where (None, None) signifes an error on ccache initialization @@ -648,8 +647,8 @@ class DomainValidator(object): domain_suffix = domain.replace('.', '-') - ccache_name = "%sTD%s" % (krbccache_prefix, domain_suffix) - ccache_path = os.path.join(krbccache_dir, ccache_name) + ccache_name = "kinit_TD%s" % (domain_suffix) + ccache_path = os.path.join(paths.IPA_CCACHES, ccache_name) realm = api.env.realm hostname = api.env.host @@ -683,8 +682,8 @@ class DomainValidator(object): Initializes ccache with http service credentials. Applies session code defaults for ccache directory and naming prefix. - Session code uses krbccache_prefix+, we use - krbccache_prefix++ so there is no clash. + Session code uses kinit_+, we use + kinit_++ so there is no clash. Returns tuple (ccache path, principal) where (None, None) signifes an error on ccache initialization @@ -695,8 +694,8 @@ class DomainValidator(object): domain_suffix = domain.replace('.', '-') - ccache_name = "%sTDA%s" % (krbccache_prefix, domain_suffix) - ccache_path = os.path.join(krbccache_dir, ccache_name) + ccache_name = "kinit_TDA%s" % (domain_suffix) + ccache_path = os.path.join(paths.IPA_CCACHES, ccache_name) (principal, password) = self._admin_creds.split('%', 1) diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index 8628572a7..c2bcc1c32 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -709,6 +709,9 @@ def install(installer): if installer._update_hosts_file: update_hosts_file(ip_addresses, host_name, fstore) + # Make sure tmpfiles dir exist before installing components + tasks.create_tmpfiles_dirs() + http_instance = httpinstance.HTTPInstance() http_instance.create_cert_db() @@ -878,6 +881,9 @@ def install(installer): except Exception: raise ScriptError("Configuration of client side components failed!") + # Make sure the files we crated in /var/run are recreated at startup + tasks.configure_tmpfiles() + # Everything installed properly, activate ipa service. services.knownservices.ipa.enable() diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 649184cbe..ed7203d6f 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -1301,6 +1301,9 @@ def install(installer): conn = remote_api.Backend.ldap2 ccache = os.environ['KRB5CCNAME'] + # Make sure tmpfiles dir exist before installing components + tasks.create_tmpfiles_dirs() + if promote: if installer._add_to_ipaservers: try: diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index 2bdf6eede..c7f0f9f44 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -1795,6 +1795,10 @@ def upgrade_check(options): def upgrade(): + # Do this early so that any code depending on these dirs will not fail + tasks.create_tmpfiles_dirs() + tasks.configure_tmpfiles() + realm = api.env.realm schema_files = [os.path.join(paths.USR_SHARE_IPA_DIR, f) for f in dsinstance.ALL_SCHEMA_FILES] diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py index 2b1e42bf6..34106ee86 100644 --- a/ipaserver/rpcserver.py +++ b/ipaserver/rpcserver.py @@ -53,9 +53,6 @@ from ipalib.rpc import (xml_dumps, xml_loads, from ipalib.util import normalize_name from ipapython.dn import DN from ipaserver.plugins.ldap2 import ldap2 -from ipaserver.session import ( - get_ipa_ccache_name, - krbccache_dir, krbccache_prefix) from ipalib.backend import Backend from ipalib.krb_utils import ( krb5_format_principal_name, @@ -913,7 +910,13 @@ class login_password(Backend, KerberosSession): return self.bad_request(environ, start_response, "no password specified") # Get the ccache we'll use and attempt to get credentials in it with user,password - ipa_ccache_name = get_ipa_ccache_name() + ipa_ccache_name = os.path.join(paths.IPA_CCACHES, + 'kinit_{}'.format(os.getpid())) + try: + # try to remove in case an old file was there + os.unlink(ipa_ccache_name) + except OSError: + pass try: self.kinit(user, self.api.env.realm, password, ipa_ccache_name) except PasswordExpired as e: @@ -931,15 +934,23 @@ class login_password(Backend, KerberosSession): str(e), 'user-locked') - return self.finalize_kerberos_acquisition('login_password', ipa_ccache_name, environ, start_response) + result = self.finalize_kerberos_acquisition('login_password', + ipa_ccache_name, environ, + start_response) + try: + # Try not to litter the filesystem with unused TGTs + os.unlink(ipa_ccache_name) + except OSError: + pass + return result def kinit(self, user, realm, password, ccache_name): # get http service ccache as an armor for FAST to enable OTP authentication armor_principal = str(krb5_format_service_principal_name( 'HTTP', self.api.env.host, realm)) keytab = paths.IPA_KEYTAB - armor_name = "%sA_%s" % (krbccache_prefix, user) - armor_path = os.path.join(krbccache_dir, armor_name) + armor_path = os.path.join(paths.IPA_CCACHES, + "armor_{}".format(os.getpid())) self.debug('Obtaining armor ccache: principal=%s keytab=%s ccache=%s', armor_principal, keytab, armor_path) diff --git a/ipaserver/session.py b/ipaserver/session.py index cdf8995bc..6957feb74 100644 --- a/ipaserver/session.py +++ b/ipaserver/session.py @@ -21,23 +21,7 @@ import os from ipalib.request import context from ipalib.krb_utils import ( krb5_parse_ccache, - krb5_unparse_ccache ) -from ipaplatform.paths import paths - - -krbccache_dir = paths.IPA_HTTPD_DIR -krbccache_prefix = 'krbcc_' - - -def get_ipa_ccache_name(scheme='FILE'): - if scheme == 'FILE': - name = os.path.join(krbccache_dir, '%s%s' % (krbccache_prefix, os.getpid())) - else: - raise ValueError('ccache scheme "%s" unsupported', scheme) - - ccache_name = krb5_unparse_ccache(scheme, name) - return ccache_name def logout(ccache_name=None):