ipa/fedora-30-move-ds-systemd-snippet.patch
2019-04-06 11:31:42 +03:00

578 lines
20 KiB
Diff

From f9f01f524311d334c32fb7e404526723decd22a7 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Tue, 2 Apr 2019 15:17:52 +0200
Subject: [PATCH 1/3] Add option to remove lines from a file
config_replace_variables() can now also remove lines from a file.
Related: https://pagure.io/freeipa/issue/7860
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
install/share/ds-ipa-env.conf.template | 0
ipapython/ipautil.py | 13 ++++++--
ipatests/conftest.py | 13 ++++++++
.../test_ipapython/test_directivesetter.py | 14 ---------
ipatests/test_ipapython/test_ipautil.py | 30 +++++++++++++++++++
.../test_install/test_installutils.py | 13 --------
6 files changed, 53 insertions(+), 30 deletions(-)
create mode 100644 install/share/ds-ipa-env.conf.template
diff --git a/install/share/ds-ipa-env.conf.template b/install/share/ds-ipa-env.conf.template
new file mode 100644
index 000000000..e69de29bb
diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py
index bfe54b2cb..4001bcec7 100644
--- a/ipapython/ipautil.py
+++ b/ipapython/ipautil.py
@@ -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.
@@ -1153,7 +1156,11 @@ $)''', re.VERBOSE)
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)
diff --git a/ipatests/conftest.py b/ipatests/conftest.py
index dc1aec064..ebcbcd694 100644
--- a/ipatests/conftest.py
+++ b/ipatests/conftest.py
@@ -5,7 +5,9 @@ from __future__ import print_function
import os
import pprint
+import shutil
import sys
+import tempfile
import pytest
@@ -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
diff --git a/ipatests/test_ipapython/test_directivesetter.py b/ipatests/test_ipapython/test_directivesetter.py
index c61c891dd..846db9414 100644
--- a/ipatests/test_ipapython/test_directivesetter.py
+++ b/ipatests/test_ipapython/test_directivesetter.py
@@ -4,11 +4,8 @@
from __future__ import absolute_import
import os
-import shutil
import tempfile
-import pytest
-
from ipapython import directivesetter
EXAMPLE_CONFIG = [
@@ -22,17 +19,6 @@ WHITESPACE_CONFIG = [
]
-@pytest.fixture
-def tempdir(request):
- tempdir = tempfile.mkdtemp()
-
- def fin():
- shutil.rmtree(tempdir)
-
- request.addfinalizer(fin)
- return tempdir
-
-
class test_set_directive_lines(object):
def test_remove_directive(self):
lines = directivesetter.set_directive_lines(
diff --git a/ipatests/test_ipapython/test_ipautil.py b/ipatests/test_ipapython/test_ipautil.py
index 3a4e406c5..c3aa2a7b5 100644
--- a/ipatests/test_ipapython/test_ipautil.py
+++ b/ipatests/test_ipapython/test_ipautil.py
@@ -28,6 +28,7 @@ import pwd
import socket
import sys
import tempfile
+import textwrap
import pytest
import six
@@ -577,3 +578,32 @@ def test_check_port_bindable_udp(udp_listen):
assert not ipautil.check_port_bindable(port, socket.SOCK_DGRAM)
sock.close()
assert ipautil.check_port_bindable(port, socket.SOCK_DGRAM)
+
+
+def test_config_replace_variables(tempdir):
+ conffile = os.path.join(tempdir, 'test.conf')
+
+ conf = textwrap.dedent("""
+ replaced=foo
+ removed=gone
+ """)
+ expected = textwrap.dedent("""
+ replaced=bar
+ addreplaced=baz
+ """)
+
+ with open(conffile, 'w') as f:
+ f.write(conf)
+
+ result = ipautil.config_replace_variables(
+ conffile,
+ replacevars=dict(replaced="bar", addreplaced="baz"),
+ removevars={'removed'}
+ )
+ assert result == {
+ 'removed': 'gone', 'replaced': 'foo'
+ }
+
+ with open(conffile, 'r') as f:
+ newconf = f.read()
+ assert newconf == expected
diff --git a/ipatests/test_ipaserver/test_install/test_installutils.py b/ipatests/test_ipaserver/test_install/test_installutils.py
index 577a993f8..3d878a454 100644
--- a/ipatests/test_ipaserver/test_install/test_installutils.py
+++ b/ipatests/test_ipaserver/test_install/test_installutils.py
@@ -6,9 +6,7 @@ from __future__ import absolute_import
import binascii
import os
import re
-import shutil
import subprocess
-import tempfile
import textwrap
import pytest
@@ -20,17 +18,6 @@ from ipaserver.install import ipa_backup
from ipaserver.install import ipa_restore
-@pytest.fixture
-def tempdir(request):
- tempdir = tempfile.mkdtemp()
-
- def fin():
- shutil.rmtree(tempdir)
-
- request.addfinalizer(fin)
- return tempdir
-
-
GPG_GENKEY = textwrap.dedent("""
%echo Generating a standard key
Key-Type: RSA
--
2.20.1
From f9b3fc1fc21ee7ec7333e147f5861e63feb87e35 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Tue, 2 Apr 2019 16:13:05 +0200
Subject: [PATCH 2/3] Add tasks.systemd_daemon_reload()
systemd daemon must be reloaded after a config file is added, changed,
or removed. Provide a common API endpoint in ipaplatform.tasks.
Related: https://pagure.io/freeipa/issue/7860
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
ipaplatform/base/services.py | 5 +++--
ipaplatform/base/tasks.py | 4 ++++
ipaplatform/redhat/tasks.py | 9 +++++----
ipaserver/install/ipa_restore.py | 2 +-
4 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/ipaplatform/base/services.py b/ipaplatform/base/services.py
index 09987100b..3fe9dee1e 100644
--- a/ipaplatform/base/services.py
+++ b/ipaplatform/base/services.py
@@ -35,6 +35,7 @@ import six
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:
@@ -452,7 +453,7 @@ class SystemdService(PlatformService):
# 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:
@@ -475,7 +476,7 @@ class SystemdService(PlatformService):
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:
diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py
index e97ac0887..dc77b2e08 100644
--- a/ipaplatform/base/tasks.py
+++ b/ipaplatform/base/tasks.py
@@ -251,5 +251,9 @@ class BaseTaskNamespace(object):
def setup_httpd_logging(self):
raise NotImplementedError()
+ def systemd_daemon_reload(self):
+ """Tell systemd to reload config files"""
+ raise NotImplementedError
+
tasks = BaseTaskNamespace()
diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py
index 372d847a0..13889cf25 100644
--- a/ipaplatform/redhat/tasks.py
+++ b/ipaplatform/redhat/tasks.py
@@ -499,9 +499,11 @@ class RedHatTaskNamespace(BaseTaskNamespace):
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(
@@ -565,8 +567,7 @@ class RedHatTaskNamespace(BaseTaskNamespace):
)
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])
diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
index ac9f38485..ba9aad3f1 100644
--- a/ipaserver/install/ipa_restore.py
+++ b/ipaserver/install/ipa_restore.py
@@ -451,7 +451,7 @@ class Restore(admintool.AdminTool):
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)
--
2.20.1
From b6c810e921a42003083aa251eab01c055c1e6f78 Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Tue, 2 Apr 2019 15:37:27 +0200
Subject: [PATCH 3/3] Move DS's Kerberos env vars to unit file
The IPA specific env vars KRB5_KTNAME and KRB5CCNAME are now defined in
a instance specific ipa-env.conf unit file.
Fixes: https://pagure.io/freeipa/issue/7860
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
---
install/share/Makefile.am | 1 +
install/share/ds-ipa-env.conf.template | 5 ++
ipaplatform/base/paths.py | 2 +
ipaserver/install/dsinstance.py | 65 +++++++++++++++++++-------
ipaserver/install/ipa_backup.py | 1 +
ipaserver/install/krbinstance.py | 4 --
ipaserver/install/server/upgrade.py | 15 +++---
7 files changed, 63 insertions(+), 30 deletions(-)
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 536f68194..e1e91a2fc 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -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 \
diff --git a/install/share/ds-ipa-env.conf.template b/install/share/ds-ipa-env.conf.template
index e69de29bb..8ab667df6 100644
--- a/install/share/ds-ipa-env.conf.template
+++ b/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
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index b5fae694e..9a34d7c7e 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -384,6 +384,8 @@ class BasePathNamespace(object):
AUTHCONFIG = None
AUTHSELECT = None
SYSCONF_NETWORK = None
+ SLAPD_INSTANCE_SYSTEMD_IPA_ENV_TEMPLATE = \
+ "/etc/systemd/system/dirsrv@%s.service.d/ipa-env.conf"
IPA_SERVER_UPGRADE = '/usr/sbin/ipa-server-upgrade'
KEYCTL = '/usr/bin/keyctl'
GETENT = '/usr/bin/getent'
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 5977cc749..318559b8d 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -27,7 +27,6 @@ import os
import re
import time
import tempfile
-import stat
import fnmatch
import ldap
@@ -229,7 +228,6 @@ class DsInstance(service.Service):
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
@@ -245,9 +243,11 @@ class DsInstance(service.Service):
self.domainlevel = domainlevel
if realm_name:
self.suffix = ipautil.realm_to_suffix(self.realm)
+ self.serverid = installutils.realm_to_serverid(self.realm)
self.__setup_sub_dict()
else:
self.suffix = DN()
+ self.serverid = None
subject_base = ipautil.dn_attribute_property('_subject_base')
@@ -275,7 +275,8 @@ class DsInstance(service.Service):
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)
@@ -553,7 +554,6 @@ class DsInstance(service.Service):
pent = pwd.getpwnam(DS_USER)
self.backup_state("serverid", self.serverid)
- self.fstore.backup_file(paths.SYSCONFIG_DIRSRV)
self.sub_dict['BASEDC'] = self.realm.split('.')[0].lower()
base_txt = ipautil.template_str(BASE_TEMPLATE, self.sub_dict)
@@ -767,21 +767,39 @@ class DsInstance(service.Service):
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)
@@ -1080,6 +1098,17 @@ class DsInstance(service.Service):
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")
diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py
index c4aa04a6b..65864f980 100644
--- a/ipaserver/install/ipa_backup.py
+++ b/ipaserver/install/ipa_backup.py
@@ -375,6 +375,7 @@ class Backup(admintool.AdminTool):
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)
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index 71015788f..587a3c691 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -386,10 +386,6 @@ class KrbInstance(service.Service):
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)
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 71211b9d6..7e54ad482 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1810,13 +1810,12 @@ def upgrade_configuration():
fqdn = api.env.host
# Ok, we are an IPA server, do the additional tests
- ds_serverid = installutils.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)
@@ -1870,7 +1869,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,
@@ -1946,16 +1945,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
@@ -2114,7 +2113,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():
--
2.20.1