Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move DS's Kerberos env vars to unit file #2982

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions install/share/Makefile.am
Expand Up @@ -39,6 +39,7 @@ dist_app_DATA = \
replica-acis.ldif \
replica-prevent-time-skew.ldif \
ds-nfiles.ldif \
ds-ipa-env.conf.template \
dns.ldif \
dnssec.ldif \
domainlevel.ldif \
Expand Down
5 changes: 5 additions & 0 deletions install/share/ds-ipa-env.conf.template
@@ -0,0 +1,5 @@
# Installed and maintained by ipa update tools, please do not modify

[Service]
Environment=KRB5_KTNAME=$KRB5_KTNAME
Environment=KRB5CCNAME=$KRB5CCNAME
2 changes: 2 additions & 0 deletions ipaplatform/base/paths.py
Expand Up @@ -382,6 +382,8 @@ class BasePathNamespace:
VAR_LOG_DIRSRV_INSTANCE_TEMPLATE = "/var/log/dirsrv/slapd-%s"
SLAPD_INSTANCE_ACCESS_LOG_TEMPLATE = "/var/log/dirsrv/slapd-%s/access"
SLAPD_INSTANCE_ERROR_LOG_TEMPLATE = "/var/log/dirsrv/slapd-%s/errors"
SLAPD_INSTANCE_SYSTEMD_IPA_ENV_TEMPLATE = \
"/etc/systemd/system/dirsrv@%s.service.d/ipa-env.conf"
# Legacy 389 commands
LDIF2DB = '/usr/sbin/ldif2db'
DB2LDIF = '/usr/sbin/db2ldif'
Expand Down
5 changes: 3 additions & 2 deletions ipaplatform/base/services.py
Expand Up @@ -35,6 +35,7 @@

from ipapython import ipautil
from ipaplatform.paths import paths
from ipaplatform.tasks import tasks

# pylint: disable=no-name-in-module, import-error
if six.PY3:
Expand Down Expand Up @@ -452,7 +453,7 @@ def enable(self, instance_name=""):
# Link exists and it is broken, make new one
os.unlink(srv_lnk)
os.symlink(self.lib_path, srv_lnk)
ipautil.run([paths.SYSTEMCTL, "--system", "daemon-reload"])
tasks.systemd_daemon_reload()
except Exception:
pass
else:
Expand All @@ -475,7 +476,7 @@ def disable(self, instance_name=""):
if os.path.isdir(srv_tgt):
if os.path.islink(srv_lnk):
os.unlink(srv_lnk)
ipautil.run([paths.SYSTEMCTL, "--system", "daemon-reload"])
tasks.systemd_daemon_reload()
except Exception:
pass
else:
Expand Down
4 changes: 4 additions & 0 deletions ipaplatform/base/tasks.py
Expand Up @@ -251,5 +251,9 @@ def add_user_to_group(self, user, group):
def setup_httpd_logging(self):
raise NotImplementedError()

def systemd_daemon_reload(self):
"""Tell systemd to reload config files"""
raise NotImplementedError


tasks = BaseTaskNamespace()
9 changes: 5 additions & 4 deletions ipaplatform/redhat/tasks.py
Expand Up @@ -498,9 +498,11 @@ def configure_httpd_service_ipa_conf(self):

os.chmod(paths.SYSTEMD_SYSTEM_HTTPD_IPA_CONF, 0o644)
self.restore_context(paths.SYSTEMD_SYSTEM_HTTPD_IPA_CONF)
self.systemd_daemon_reload()

ipautil.run([paths.SYSTEMCTL, "--system", "daemon-reload"],
raiseonerr=False)
def systemd_daemon_reload(self):
"""Tell systemd to reload config files"""
ipautil.run([paths.SYSTEMCTL, "--system", "daemon-reload"])

def configure_http_gssproxy_conf(self, ipaapi_user):
ipautil.copy_template_file(
Expand Down Expand Up @@ -564,8 +566,7 @@ def remove_httpd_service_ipa_conf(self):
)
return

ipautil.run([paths.SYSTEMCTL, "--system", "daemon-reload"],
raiseonerr=False)
self.systemd_daemon_reload()

def set_hostname(self, hostname):
ipautil.run([paths.BIN_HOSTNAMECTL, 'set-hostname', hostname])
Expand Down
13 changes: 10 additions & 3 deletions ipapython/ipautil.py
Expand Up @@ -1104,14 +1104,17 @@ def reverse_record_exists(ip_address):
return True


def config_replace_variables(filepath, replacevars=dict(), appendvars=dict()):
def config_replace_variables(filepath, replacevars=dict(), appendvars=dict(),
removevars=None):
"""
Take a key=value based configuration file, and write new version
with certain values replaced or appended
with certain values replaced, appended, or removed.

All (key,value) pairs from replacevars and appendvars that were not found
in the configuration file, will be added there.

All entries in set removevars are removed.

It is responsibility of a caller to ensure that replacevars and
appendvars do not overlap.

Expand Down Expand Up @@ -1153,7 +1156,11 @@ def config_replace_variables(filepath, replacevars=dict(), appendvars=dict()):
elif value.find(appendvars[option]) == -1:
new_line = u"%s=%s %s\n" % (option, value, appendvars[option])
old_values[option] = value
new_config.write(new_line)
if removevars and option in removevars:
old_values[option] = value
new_line = None
if new_line is not None:
new_config.write(new_line)
# Now add all options from replacevars and appendvars that were not found in the file
new_vars = replacevars.copy()
new_vars.update(appendvars)
Expand Down
65 changes: 47 additions & 18 deletions ipaserver/install/dsinstance.py
Expand Up @@ -26,7 +26,6 @@
import os
import time
import tempfile
import stat
import fnmatch

from lib389 import DirSrv
Expand Down Expand Up @@ -200,7 +199,6 @@ def __init__(self, realm_name=None, domain_name=None, fstore=None,
self.nickname = 'Server-Cert'
self.sub_dict = None
self.domain = domain_name
self.serverid = None
self.master_fqdn = None
self.pkcs12_info = None
self.cacert_name = None
Expand All @@ -216,9 +214,11 @@ def __init__(self, realm_name=None, domain_name=None, fstore=None,
self.domainlevel = domainlevel
if realm_name:
self.suffix = ipautil.realm_to_suffix(self.realm)
self.serverid = ipaldap.realm_to_serverid(self.realm)
self.__setup_sub_dict()
else:
self.suffix = DN()
self.serverid = None

subject_base = ipautil.dn_attribute_property('_subject_base')

Expand All @@ -245,7 +245,8 @@ def __common_setup(self):
self.step("enabling referential integrity plugin", self.__add_referint_module)
self.step("configuring certmap.conf", self.__certmap_conf)
self.step("configure new location for managed entries", self.__repoint_managed_entries)
self.step("configure dirsrv ccache", self.configure_dirsrv_ccache)
self.step("configure dirsrv ccache and keytab",
self.configure_systemd_ipa_env)
self.step("enabling SASL mapping fallback",
self.__enable_sasl_mapping_fallback)

Expand Down Expand Up @@ -521,7 +522,6 @@ def __setup_sub_dict(self):

def __create_instance(self):
self.backup_state("serverid", self.serverid)
self.fstore.backup_file(paths.SYSCONFIG_DIRSRV)

# The new installer is api driven. We can pass it a log function
# and it will use it. Because of this, we can pass verbose true,
Expand Down Expand Up @@ -756,21 +756,39 @@ def __config_topology_module(self):
def __repoint_managed_entries(self):
self._ldap_mod("repoint-managed-entries.ldif", self.sub_dict)

def configure_dirsrv_ccache(self):
def configure_systemd_ipa_env(self):
pent = pwd.getpwnam(platformconstants.DS_USER)
ccache = paths.TMP_KRB5CC % pent.pw_uid
filepath = paths.SYSCONFIG_DIRSRV
if not os.path.exists(filepath):
# file doesn't exist; create it with correct ownership & mode
open(filepath, 'a').close()
os.chmod(filepath,
stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
os.chown(filepath, 0, 0)

replacevars = {'KRB5CCNAME': ccache}
ipautil.backup_config_and_replace_variables(
self.fstore, filepath, replacevars=replacevars)
tasks.restore_context(filepath)
template = os.path.join(
paths.USR_SHARE_IPA_DIR, "ds-ipa-env.conf.template"
)
sub_dict = dict(
KRB5_KTNAME=paths.DS_KEYTAB,
KRB5CCNAME=paths.TMP_KRB5CC % pent.pw_uid
)
conf = ipautil.template_file(template, sub_dict)

destfile = paths.SLAPD_INSTANCE_SYSTEMD_IPA_ENV_TEMPLATE % (
self.serverid
)
destdir = os.path.dirname(destfile)

if not os.path.isdir(destdir):
# create dirsrv-$SERVERID.service.d
os.mkdir(destdir, 0o755)
with open(destfile, 'w') as f:
os.fchmod(f.fileno(), 0o644)
f.write(conf)
tasks.restore_context(destfile)

# remove variables from old /etc/sysconfig/dirsrv file
if os.path.isfile(paths.SYSCONFIG_DIRSRV):
self.fstore.backup_file(paths.SYSCONFIG_DIRSRV)
ipautil.config_replace_variables(
paths.SYSCONFIG_DIRSRV,
removevars={'KRB5_KTNAME', 'KRB5CCNAME'}
)
# reload systemd to materialize new config file
tasks.systemd_daemon_reload()

def __managed_entries(self):
self._ldap_mod("managed-entries.ldif", self.sub_dict)
Expand Down Expand Up @@ -1083,6 +1101,17 @@ def uninstall(self):
serverid)
installutils.rmtree(scripts)

# remove systemd unit file
unitfile = paths.SLAPD_INSTANCE_SYSTEMD_IPA_ENV_TEMPLATE % (
serverid
)
installutils.remove_file(unitfile)
try:
os.rmdir(os.path.dirname(unitfile))
except OSError:
# not empty
pass

# Just eat this state
self.restore_state("user_exists")

Expand Down
1 change: 1 addition & 0 deletions ipaserver/install/ipa_backup.py
Expand Up @@ -375,6 +375,7 @@ def add_instance_specific_data(self):
for file in (
paths.SYSCONFIG_DIRSRV_INSTANCE % serverid,
paths.ETC_TMPFILESD_DIRSRV % serverid,
paths.SLAPD_INSTANCE_SYSTEMD_IPA_ENV_TEMPLATE % serverid,
):
if os.path.exists(file):
self.files.append(file)
Expand Down
2 changes: 1 addition & 1 deletion ipaserver/install/ipa_restore.py
Expand Up @@ -451,7 +451,7 @@ def run(self):
oddjobd.start()
http.remove_httpd_ccaches()
# have the daemons pick up their restored configs
run([paths.SYSTEMCTL, "--system", "daemon-reload"])
tasks.systemd_daemon_reload()
finally:
try:
os.chdir(cwd)
Expand Down
4 changes: 0 additions & 4 deletions ipaserver/install/krbinstance.py
Expand Up @@ -386,10 +386,6 @@ def __create_ds_keytab(self):

self.fstore.backup_file(paths.DS_KEYTAB)
installutils.create_keytab(paths.DS_KEYTAB, ldap_principal)

vardict = {"KRB5_KTNAME": paths.DS_KEYTAB}
ipautil.config_replace_variables(paths.SYSCONFIG_DIRSRV,
replacevars=vardict)
pent = pwd.getpwnam(constants.DS_USER)
os.chown(paths.DS_KEYTAB, pent.pw_uid, pent.pw_gid)

Expand Down
15 changes: 7 additions & 8 deletions ipaserver/install/server/upgrade.py
Expand Up @@ -1812,13 +1812,12 @@ def upgrade_configuration():
fqdn = api.env.host

# Ok, we are an IPA server, do the additional tests
ds_serverid = ipaldap.realm_to_serverid(api.env.realm)
ds = dsinstance.DsInstance()
ds = dsinstance.DsInstance(realm_name=api.env.realm)

# start DS, CA will not start without running DS, and cause error
ds_running = ds.is_running()
if not ds_running:
ds.start(ds_serverid)
ds.start(ds.serverid)

if not sysupgrade.get_upgrade_state('ntpd', 'ntpd_cleaned'):
ntpd_cleanup(fqdn, fstore)
Expand Down Expand Up @@ -1872,7 +1871,7 @@ def upgrade_configuration():
paths.CA_CS_CFG_PATH, 'ca.crl.MasterCRL.enableCRLUpdates', '=')
sub_dict['CLONE']='#' if crl.lower() == 'true' else ''

ds_dirname = dsinstance.config_dirname(ds_serverid)
ds_dirname = dsinstance.config_dirname(ds.serverid)

upgrade_file(sub_dict, paths.HTTPD_IPA_CONF,
os.path.join(paths.USR_SHARE_IPA_DIR,
Expand Down Expand Up @@ -1948,16 +1947,16 @@ def upgrade_configuration():

http.enable_and_start_oddjobd()

ds.configure_dirsrv_ccache()
ds.configure_systemd_ipa_env()

update_replica_config(ipautil.realm_to_suffix(api.env.realm))
if ca.is_configured():
update_replica_config(DN(('o', 'ipaca')))

ds.stop(ds_serverid)
ds.stop(ds.serverid)
fix_schema_file_syntax()
remove_ds_ra_cert(subject_base)
ds.start(ds_serverid)
ds.start(ds.serverid)

ds.fqdn = fqdn
ds.realm = api.env.realm
Expand Down Expand Up @@ -2116,7 +2115,7 @@ def upgrade_configuration():
enable_certauth(krb)

if not ds_running:
ds.stop(ds_serverid)
ds.stop(ds.serverid)

if ca.is_configured():
if ca_running and not ca.is_running():
Expand Down
13 changes: 13 additions & 0 deletions ipatests/conftest.py
Expand Up @@ -5,7 +5,9 @@

import os
import pprint
import shutil
import sys
import tempfile

import pytest

Expand Down Expand Up @@ -145,3 +147,14 @@ def pytest_runtest_setup(item):
# pylint: disable=no-member
if pytest.config.option.skip_ipaapi:
pytest.skip("Skip tests that needs an IPA API")


@pytest.fixture
def tempdir(request):
tempdir = tempfile.mkdtemp()

def fin():
shutil.rmtree(tempdir)

request.addfinalizer(fin)
return tempdir
14 changes: 0 additions & 14 deletions ipatests/test_ipapython/test_directivesetter.py
Expand Up @@ -4,11 +4,8 @@
from __future__ import absolute_import

import os
import shutil
import tempfile

import pytest

from ipapython import directivesetter

EXAMPLE_CONFIG = [
Expand All @@ -22,17 +19,6 @@
]


@pytest.fixture
def tempdir(request):
tempdir = tempfile.mkdtemp()

def fin():
shutil.rmtree(tempdir)

request.addfinalizer(fin)
return tempdir


class test_set_directive_lines:
def test_remove_directive(self):
lines = directivesetter.set_directive_lines(
Expand Down