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