Imported Debian patch 4.7.2-3
This commit is contained in:
committed by
Mario Fetka
parent
27edeba051
commit
8bc559c5a1
@@ -27,7 +27,6 @@ from ipaplatform.paths import paths
|
||||
from ipapython import ipautil
|
||||
from ipapython.admintool import ScriptError
|
||||
import os
|
||||
import time
|
||||
|
||||
FILES_TO_NOT_BACKUP = ['passwd', 'group', 'shadow', 'gshadow']
|
||||
|
||||
@@ -39,7 +38,7 @@ def get_auth_tool():
|
||||
|
||||
|
||||
@six.add_metaclass(abc.ABCMeta)
|
||||
class RedHatAuthToolBase:
|
||||
class RedHatAuthToolBase(object):
|
||||
|
||||
@abc.abstractmethod
|
||||
def configure(self, sssd, mkhomedir, statestore, sudo=True):
|
||||
@@ -104,16 +103,28 @@ class RedHatAuthSelect(RedHatAuthToolBase):
|
||||
def configure(self, sssd, mkhomedir, statestore, sudo=True):
|
||||
# In the statestore, the following keys are used for the
|
||||
# 'authselect' module:
|
||||
# Old method:
|
||||
# profile: name of the profile configured pre-installation
|
||||
# features_list: list of features configured pre-installation
|
||||
# mkhomedir: True if installation was called with --mkhomedir
|
||||
# profile and features_list are used when reverting to the
|
||||
# pre-install state
|
||||
# New method:
|
||||
# backup: name of the authselect backup
|
||||
backup_name = "pre_ipaclient_{}".format(time.strftime("%Y%m%d%H%M%S"))
|
||||
statestore.backup_state('authselect', 'backup', backup_name)
|
||||
cfg = self._parse_authselect_output()
|
||||
if cfg:
|
||||
statestore.backup_state('authselect', 'profile', cfg[0])
|
||||
statestore.backup_state(
|
||||
'authselect', 'features_list', " ".join(cfg[1]))
|
||||
else:
|
||||
# cfg = None means that the current conf is not managed by
|
||||
# authselect but by authconfig.
|
||||
# As we are using authselect to configure the host,
|
||||
# it will not be possible to revert to a custom authconfig
|
||||
# configuration later (during uninstall)
|
||||
# Best thing to do will be to use sssd profile at this time
|
||||
logger.warning(
|
||||
"WARNING: The configuration pre-client installation is not "
|
||||
"managed by authselect and cannot be backed up. "
|
||||
"Uninstallation may not be able to revert to the original "
|
||||
"state.")
|
||||
|
||||
cmd = [paths.AUTHSELECT, "select", "sssd"]
|
||||
if mkhomedir:
|
||||
@@ -122,7 +133,6 @@ class RedHatAuthSelect(RedHatAuthToolBase):
|
||||
if sudo:
|
||||
cmd.append("with-sudo")
|
||||
cmd.append("--force")
|
||||
cmd.append("--backup={}".format(backup_name))
|
||||
|
||||
ipautil.run(cmd)
|
||||
|
||||
@@ -157,10 +167,6 @@ class RedHatAuthSelect(RedHatAuthToolBase):
|
||||
'authselect', 'features_list'
|
||||
)
|
||||
statestore.delete_state('authselect', 'mkhomedir')
|
||||
# https://pagure.io/freeipa/issue/8054
|
||||
if fstore.has_file(paths.NSSWITCH_CONF):
|
||||
logger.info("Restoring user-nsswitch.conf")
|
||||
fstore.restore_file(paths.NSSWITCH_CONF)
|
||||
# only non-empty features, https://pagure.io/freeipa/issue/7776
|
||||
if features_state is not None:
|
||||
features = [
|
||||
@@ -169,15 +175,10 @@ class RedHatAuthSelect(RedHatAuthToolBase):
|
||||
else:
|
||||
features = []
|
||||
|
||||
backup = statestore.restore_state('authselect', 'backup')
|
||||
if backup:
|
||||
cmd = [paths.AUTHSELECT, "backup-restore", backup]
|
||||
ipautil.run(cmd)
|
||||
else:
|
||||
cmd = [paths.AUTHSELECT, "select", profile]
|
||||
cmd.extend(features)
|
||||
cmd.append("--force")
|
||||
ipautil.run(cmd)
|
||||
cmd = [paths.AUTHSELECT, "select", profile]
|
||||
cmd.extend(features)
|
||||
cmd.append("--force")
|
||||
ipautil.run(cmd)
|
||||
|
||||
def backup(self, path):
|
||||
current = self._get_authselect_current_output()
|
||||
|
||||
@@ -14,9 +14,6 @@ from ipaplatform.base.constants import BaseConstantsNamespace
|
||||
|
||||
|
||||
class RedHatConstantsNamespace(BaseConstantsNamespace):
|
||||
# Use system-wide crypto policy
|
||||
# see https://fedoraproject.org/wiki/Changes/CryptoPolicy
|
||||
TLS_HIGH_CIPHERS = None
|
||||
|
||||
pass
|
||||
|
||||
constants = RedHatConstantsNamespace()
|
||||
|
||||
@@ -39,7 +39,6 @@ class RedHatPathNamespace(BasePathNamespace):
|
||||
AUTHCONFIG = '/usr/sbin/authconfig'
|
||||
AUTHSELECT = '/usr/bin/authselect'
|
||||
SYSCONF_NETWORK = '/etc/sysconfig/network'
|
||||
NSSWITCH_CONF = '/etc/authselect/user-nsswitch.conf'
|
||||
|
||||
|
||||
paths = RedHatPathNamespace()
|
||||
|
||||
@@ -45,8 +45,8 @@ logger = logging.getLogger(__name__)
|
||||
redhat_system_units = dict((x, "%s.service" % x)
|
||||
for x in base_services.wellknownservices)
|
||||
|
||||
redhat_system_units['rpcgssd'] = 'rpc-gssd.service'
|
||||
redhat_system_units['rpcidmapd'] = 'nfs-idmapd.service'
|
||||
redhat_system_units['rpcgssd'] = 'nfs-secure.service'
|
||||
redhat_system_units['rpcidmapd'] = 'nfs-idmap.service'
|
||||
redhat_system_units['domainname'] = 'nis-domainname.service'
|
||||
|
||||
# Rewrite dirsrv and pki-tomcatd services as they support instances via separate
|
||||
@@ -186,6 +186,18 @@ class RedHatCAService(RedHatService):
|
||||
else:
|
||||
raise RuntimeError('CA did not start in %ss' % timeout)
|
||||
|
||||
def start(self, instance_name="", capture_output=True, wait=True):
|
||||
super(RedHatCAService, self).start(
|
||||
instance_name, capture_output=capture_output, wait=wait)
|
||||
if wait:
|
||||
self.wait_until_running()
|
||||
|
||||
def restart(self, instance_name="", capture_output=True, wait=True):
|
||||
super(RedHatCAService, self).restart(
|
||||
instance_name, capture_output=capture_output, wait=wait)
|
||||
if wait:
|
||||
self.wait_until_running()
|
||||
|
||||
def is_running(self, instance_name="", wait=True):
|
||||
if instance_name:
|
||||
return super(RedHatCAService, self).is_running(instance_name)
|
||||
|
||||
@@ -28,20 +28,17 @@ from __future__ import print_function, absolute_import
|
||||
import ctypes
|
||||
import logging
|
||||
import os
|
||||
from pathlib import Path
|
||||
import socket
|
||||
import traceback
|
||||
import errno
|
||||
import urllib
|
||||
import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
from ctypes.util import find_library
|
||||
from functools import total_ordering
|
||||
from subprocess import CalledProcessError
|
||||
|
||||
from pyasn1.error import PyAsn1Error
|
||||
from six.moves import urllib
|
||||
|
||||
from ipapython import directivesetter
|
||||
from ipapython import ipautil
|
||||
@@ -55,29 +52,24 @@ from ipaplatform.base.tasks import BaseTaskNamespace
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# /etc/pkcs11/modules override
|
||||
# base filen ame, module, list of disabled-in
|
||||
# 'p11-kit-proxy' disables proxying of module, see man(5) pkcs11.conf
|
||||
PKCS11_MODULES = [
|
||||
('softhsm2', paths.LIBSOFTHSM2_SO, ['p11-kit-proxy']),
|
||||
]
|
||||
|
||||
|
||||
NM_IPA_CONF = textwrap.dedent("""
|
||||
# auto-generated by IPA installer
|
||||
[main]
|
||||
dns={dnsprocessing}
|
||||
|
||||
[global-dns]
|
||||
searches={searches}
|
||||
|
||||
[global-dns-domain-*]
|
||||
servers={servers}
|
||||
""")
|
||||
def selinux_enabled():
|
||||
"""
|
||||
Check if SELinux is enabled.
|
||||
"""
|
||||
if os.path.exists(paths.SELINUXENABLED):
|
||||
try:
|
||||
ipautil.run([paths.SELINUXENABLED])
|
||||
return True
|
||||
except ipautil.CalledProcessError:
|
||||
# selinuxenabled returns 1 if not enabled
|
||||
return False
|
||||
else:
|
||||
# No selinuxenabled, no SELinux
|
||||
return False
|
||||
|
||||
|
||||
@total_ordering
|
||||
class IPAVersion:
|
||||
class IPAVersion(object):
|
||||
_rpmvercmp_func = None
|
||||
|
||||
@classmethod
|
||||
@@ -128,7 +120,7 @@ class RedHatTaskNamespace(BaseTaskNamespace):
|
||||
ipautil.run() will do the logging.
|
||||
"""
|
||||
restorecon = paths.SBIN_RESTORECON
|
||||
if not self.is_selinux_enabled() or not os.path.exists(restorecon):
|
||||
if not selinux_enabled() or not os.path.exists(restorecon):
|
||||
return
|
||||
|
||||
# Force reset of context to match file_context for customizable
|
||||
@@ -140,20 +132,6 @@ class RedHatTaskNamespace(BaseTaskNamespace):
|
||||
args.append(filepath)
|
||||
ipautil.run(args, raiseonerr=False)
|
||||
|
||||
def is_selinux_enabled(self):
|
||||
"""Check if SELinux is available and enabled
|
||||
"""
|
||||
try:
|
||||
ipautil.run([paths.SELINUXENABLED])
|
||||
except ipautil.CalledProcessError:
|
||||
# selinuxenabled returns 1 if not enabled
|
||||
return False
|
||||
except OSError:
|
||||
# selinuxenabled binary not available
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def check_selinux_status(self, restorecon=paths.RESTORECON):
|
||||
"""
|
||||
We don't have a specific package requirement for policycoreutils
|
||||
@@ -164,14 +142,13 @@ class RedHatTaskNamespace(BaseTaskNamespace):
|
||||
This function returns nothing but may raise a Runtime exception
|
||||
if SELinux is enabled but restorecon is not available.
|
||||
"""
|
||||
if not self.is_selinux_enabled():
|
||||
return False
|
||||
if not selinux_enabled():
|
||||
return
|
||||
|
||||
if not os.path.exists(restorecon):
|
||||
raise RuntimeError('SELinux is enabled but %s does not exist.\n'
|
||||
'Install the policycoreutils package and start '
|
||||
'the installation again.' % restorecon)
|
||||
return True
|
||||
|
||||
def check_ipv6_stack_enabled(self):
|
||||
"""Checks whether IPv6 kernel module is loaded.
|
||||
@@ -189,6 +166,12 @@ class RedHatTaskNamespace(BaseTaskNamespace):
|
||||
"globally, disable it on the specific interfaces in "
|
||||
"sysctl.conf except 'lo' interface.")
|
||||
|
||||
# XXX This is a hack to work around an issue with Travis CI by
|
||||
# skipping IPv6 address test. The Dec 2017 update removed ::1 from
|
||||
# loopback, see https://github.com/travis-ci/travis-ci/issues/8891.
|
||||
if os.environ.get('TRAVIS') == 'true':
|
||||
return
|
||||
|
||||
try:
|
||||
localhost6 = ipautil.CheckedIPAddress('::1', allow_loopback=True)
|
||||
if localhost6.get_matching_interface() is None:
|
||||
@@ -200,26 +183,6 @@ class RedHatTaskNamespace(BaseTaskNamespace):
|
||||
"resolution to 'lo' interface. You might need to enable IPv6 "
|
||||
"on the interface 'lo' in sysctl.conf.")
|
||||
|
||||
def detect_container(self):
|
||||
"""Check if running inside a container
|
||||
|
||||
:returns: container runtime or None
|
||||
:rtype: str, None
|
||||
"""
|
||||
try:
|
||||
output = subprocess.check_output(
|
||||
[paths.SYSTEMD_DETECT_VIRT, '--container'],
|
||||
stderr=subprocess.STDOUT
|
||||
)
|
||||
except subprocess.CalledProcessError as e:
|
||||
if e.returncode == 1:
|
||||
# No container runtime detected
|
||||
return None
|
||||
else:
|
||||
raise
|
||||
else:
|
||||
return output.decode('utf-8').strip()
|
||||
|
||||
def restore_pre_ipa_client_configuration(self, fstore, statestore,
|
||||
was_sssd_installed,
|
||||
was_sssd_configured):
|
||||
@@ -297,121 +260,128 @@ class RedHatTaskNamespace(BaseTaskNamespace):
|
||||
logger.info("Systemwide CA database updated.")
|
||||
return True
|
||||
|
||||
def platform_insert_ca_certs(self, ca_certs):
|
||||
return any([
|
||||
self.write_p11kit_certs(paths.IPA_P11_KIT, ca_certs),
|
||||
self.remove_ca_certificates_bundle(
|
||||
paths.SYSTEMWIDE_IPA_CA_CRT
|
||||
),
|
||||
])
|
||||
|
||||
def write_p11kit_certs(self, filename, ca_certs):
|
||||
def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
|
||||
# pylint: disable=ipa-forbidden-import
|
||||
from ipalib import x509 # FixMe: break import cycle
|
||||
from ipalib.errors import CertificateError
|
||||
# pylint: enable=ipa-forbidden-import
|
||||
|
||||
path = Path(filename)
|
||||
try:
|
||||
f = open(path, 'w')
|
||||
except IOError:
|
||||
logger.error("Failed to open %s", path)
|
||||
raise
|
||||
|
||||
with f:
|
||||
f.write("# This file was created by IPA. Do not edit.\n"
|
||||
"\n")
|
||||
new_cacert_path = paths.SYSTEMWIDE_IPA_CA_CRT
|
||||
|
||||
if os.path.exists(new_cacert_path):
|
||||
try:
|
||||
os.fchmod(f.fileno(), 0o644)
|
||||
except IOError:
|
||||
logger.error("Failed to set mode of %s", path)
|
||||
raise
|
||||
os.remove(new_cacert_path)
|
||||
except OSError as e:
|
||||
logger.error(
|
||||
"Could not remove %s: %s", new_cacert_path, e)
|
||||
return False
|
||||
|
||||
has_eku = set()
|
||||
for cert, nickname, trusted, _ext_key_usage in ca_certs:
|
||||
try:
|
||||
subject = cert.subject_bytes
|
||||
issuer = cert.issuer_bytes
|
||||
serial_number = cert.serial_number_bytes
|
||||
public_key_info = cert.public_key_info_bytes
|
||||
except (PyAsn1Error, ValueError, CertificateError):
|
||||
logger.error(
|
||||
"Failed to decode certificate \"%s\"", nickname)
|
||||
raise
|
||||
new_cacert_path = paths.IPA_P11_KIT
|
||||
|
||||
label = urllib.parse.quote(nickname)
|
||||
subject = urllib.parse.quote(subject)
|
||||
issuer = urllib.parse.quote(issuer)
|
||||
serial_number = urllib.parse.quote(serial_number)
|
||||
public_key_info = urllib.parse.quote(public_key_info)
|
||||
|
||||
obj = ("[p11-kit-object-v1]\n"
|
||||
"class: certificate\n"
|
||||
"certificate-type: x-509\n"
|
||||
"certificate-category: authority\n"
|
||||
"label: \"%(label)s\"\n"
|
||||
"subject: \"%(subject)s\"\n"
|
||||
"issuer: \"%(issuer)s\"\n"
|
||||
"serial-number: \"%(serial_number)s\"\n"
|
||||
"x-public-key-info: \"%(public_key_info)s\"\n" %
|
||||
dict(label=label,
|
||||
subject=subject,
|
||||
issuer=issuer,
|
||||
serial_number=serial_number,
|
||||
public_key_info=public_key_info))
|
||||
if trusted is True:
|
||||
obj += "trusted: true\n"
|
||||
elif trusted is False:
|
||||
obj += "x-distrusted: true\n"
|
||||
obj += "{pem}\n\n".format(
|
||||
pem=cert.public_bytes(x509.Encoding.PEM).decode('ascii'))
|
||||
|
||||
f.write(obj)
|
||||
|
||||
if (cert.extended_key_usage is not None and
|
||||
public_key_info not in has_eku):
|
||||
try:
|
||||
ext_key_usage = cert.extended_key_usage_bytes
|
||||
except PyAsn1Error:
|
||||
logger.error(
|
||||
"Failed to encode extended key usage for \"%s\"",
|
||||
nickname)
|
||||
raise
|
||||
value = urllib.parse.quote(ext_key_usage)
|
||||
obj = ("[p11-kit-object-v1]\n"
|
||||
"class: x-certificate-extension\n"
|
||||
"label: \"ExtendedKeyUsage for %(label)s\"\n"
|
||||
"x-public-key-info: \"%(public_key_info)s\"\n"
|
||||
"object-id: 2.5.29.37\n"
|
||||
"value: \"%(value)s\"\n\n" %
|
||||
dict(label=label,
|
||||
public_key_info=public_key_info,
|
||||
value=value))
|
||||
f.write(obj)
|
||||
has_eku.add(public_key_info)
|
||||
|
||||
return True
|
||||
|
||||
def platform_remove_ca_certs(self):
|
||||
return any([
|
||||
self.remove_ca_certificates_bundle(paths.IPA_P11_KIT),
|
||||
self.remove_ca_certificates_bundle(paths.SYSTEMWIDE_IPA_CA_CRT),
|
||||
])
|
||||
|
||||
def remove_ca_certificates_bundle(self, filename):
|
||||
path = Path(filename)
|
||||
if not path.is_file():
|
||||
try:
|
||||
f = open(new_cacert_path, 'w')
|
||||
os.fchmod(f.fileno(), 0o644)
|
||||
except IOError as e:
|
||||
logger.info("Failed to open %s: %s", new_cacert_path, e)
|
||||
return False
|
||||
|
||||
try:
|
||||
path.unlink()
|
||||
except Exception:
|
||||
logger.error("Could not remove %s", path)
|
||||
raise
|
||||
f.write("# This file was created by IPA. Do not edit.\n"
|
||||
"\n")
|
||||
|
||||
has_eku = set()
|
||||
for cert, nickname, trusted, _ext_key_usage in ca_certs:
|
||||
try:
|
||||
subject = cert.subject_bytes
|
||||
issuer = cert.issuer_bytes
|
||||
serial_number = cert.serial_number_bytes
|
||||
public_key_info = cert.public_key_info_bytes
|
||||
except (PyAsn1Error, ValueError, CertificateError) as e:
|
||||
logger.warning(
|
||||
"Failed to decode certificate \"%s\": %s", nickname, e)
|
||||
continue
|
||||
|
||||
label = urllib.parse.quote(nickname)
|
||||
subject = urllib.parse.quote(subject)
|
||||
issuer = urllib.parse.quote(issuer)
|
||||
serial_number = urllib.parse.quote(serial_number)
|
||||
public_key_info = urllib.parse.quote(public_key_info)
|
||||
|
||||
obj = ("[p11-kit-object-v1]\n"
|
||||
"class: certificate\n"
|
||||
"certificate-type: x-509\n"
|
||||
"certificate-category: authority\n"
|
||||
"label: \"%(label)s\"\n"
|
||||
"subject: \"%(subject)s\"\n"
|
||||
"issuer: \"%(issuer)s\"\n"
|
||||
"serial-number: \"%(serial_number)s\"\n"
|
||||
"x-public-key-info: \"%(public_key_info)s\"\n" %
|
||||
dict(label=label,
|
||||
subject=subject,
|
||||
issuer=issuer,
|
||||
serial_number=serial_number,
|
||||
public_key_info=public_key_info))
|
||||
if trusted is True:
|
||||
obj += "trusted: true\n"
|
||||
elif trusted is False:
|
||||
obj += "x-distrusted: true\n"
|
||||
obj += "{pem}\n\n".format(
|
||||
pem=cert.public_bytes(x509.Encoding.PEM).decode('ascii'))
|
||||
f.write(obj)
|
||||
|
||||
if (cert.extended_key_usage is not None and
|
||||
public_key_info not in has_eku):
|
||||
try:
|
||||
ext_key_usage = cert.extended_key_usage_bytes
|
||||
except PyAsn1Error as e:
|
||||
logger.warning(
|
||||
"Failed to encode extended key usage for \"%s\": %s",
|
||||
nickname, e)
|
||||
continue
|
||||
value = urllib.parse.quote(ext_key_usage)
|
||||
obj = ("[p11-kit-object-v1]\n"
|
||||
"class: x-certificate-extension\n"
|
||||
"label: \"ExtendedKeyUsage for %(label)s\"\n"
|
||||
"x-public-key-info: \"%(public_key_info)s\"\n"
|
||||
"object-id: 2.5.29.37\n"
|
||||
"value: \"%(value)s\"\n\n" %
|
||||
dict(label=label,
|
||||
public_key_info=public_key_info,
|
||||
value=value))
|
||||
f.write(obj)
|
||||
has_eku.add(public_key_info)
|
||||
|
||||
f.close()
|
||||
|
||||
# Add the CA to the systemwide CA trust database
|
||||
if not self.reload_systemwide_ca_store():
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def remove_ca_certs_from_systemwide_ca_store(self):
|
||||
result = True
|
||||
update = False
|
||||
|
||||
# Remove CA cert from systemwide store
|
||||
for new_cacert_path in (paths.IPA_P11_KIT,
|
||||
paths.SYSTEMWIDE_IPA_CA_CRT):
|
||||
if not os.path.exists(new_cacert_path):
|
||||
continue
|
||||
try:
|
||||
os.remove(new_cacert_path)
|
||||
except OSError as e:
|
||||
logger.error(
|
||||
"Could not remove %s: %s", new_cacert_path, e)
|
||||
result = False
|
||||
else:
|
||||
update = True
|
||||
|
||||
if update:
|
||||
if not self.reload_systemwide_ca_store():
|
||||
return False
|
||||
|
||||
return result
|
||||
|
||||
def backup_hostname(self, fstore, statestore):
|
||||
filepath = paths.ETC_HOSTNAME
|
||||
if os.path.exists(filepath):
|
||||
@@ -445,7 +415,7 @@ class RedHatTaskNamespace(BaseTaskNamespace):
|
||||
|
||||
return args
|
||||
|
||||
if not self.is_selinux_enabled():
|
||||
if not selinux_enabled():
|
||||
return False
|
||||
|
||||
updated_vars = {}
|
||||
@@ -507,11 +477,9 @@ 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()
|
||||
|
||||
def systemd_daemon_reload(self):
|
||||
"""Tell systemd to reload config files"""
|
||||
ipautil.run([paths.SYSTEMCTL, "--system", "daemon-reload"])
|
||||
ipautil.run([paths.SYSTEMCTL, "--system", "daemon-reload"],
|
||||
raiseonerr=False)
|
||||
|
||||
def configure_http_gssproxy_conf(self, ipaapi_user):
|
||||
ipautil.copy_template_file(
|
||||
@@ -575,13 +543,8 @@ class RedHatTaskNamespace(BaseTaskNamespace):
|
||||
)
|
||||
return
|
||||
|
||||
self.systemd_daemon_reload()
|
||||
|
||||
def configure_httpd_protocol(self):
|
||||
# use default crypto policy for SSLProtocol
|
||||
directivesetter.set_directive(
|
||||
paths.HTTPD_SSL_CONF, 'SSLProtocol', None, False
|
||||
)
|
||||
ipautil.run([paths.SYSTEMCTL, "--system", "daemon-reload"],
|
||||
raiseonerr=False)
|
||||
|
||||
def set_hostname(self, hostname):
|
||||
ipautil.run([paths.BIN_HOSTNAMECTL, 'set-hostname', hostname])
|
||||
@@ -613,166 +576,5 @@ class RedHatTaskNamespace(BaseTaskNamespace):
|
||||
'TransferLog',
|
||||
'logs/access_log', False)
|
||||
|
||||
def configure_dns_resolver(self, nameservers, searchdomains, *,
|
||||
resolve1_enabled=False, fstore=None):
|
||||
"""Configure global DNS resolver (e.g. /etc/resolv.conf)
|
||||
|
||||
:param nameservers: list of IP addresses
|
||||
:param searchdomains: list of search domaons
|
||||
:param fstore: optional file store for backup
|
||||
"""
|
||||
assert nameservers and isinstance(nameservers, list)
|
||||
assert searchdomains and isinstance(searchdomains, list)
|
||||
|
||||
super().configure_dns_resolver(
|
||||
nameservers=nameservers,
|
||||
searchdomains=searchdomains,
|
||||
resolve1_enabled=resolve1_enabled,
|
||||
fstore=fstore
|
||||
)
|
||||
|
||||
# break circular import
|
||||
from ipaplatform.services import knownservices
|
||||
|
||||
if fstore is not None and not fstore.has_file(paths.RESOLV_CONF):
|
||||
fstore.backup_file(paths.RESOLV_CONF)
|
||||
|
||||
nm = knownservices['NetworkManager']
|
||||
nm_enabled = nm.is_enabled()
|
||||
if nm_enabled:
|
||||
logger.debug(
|
||||
"Network Manager is enabled, write %s",
|
||||
paths.NETWORK_MANAGER_IPA_CONF
|
||||
)
|
||||
# write DNS override and reload network manager to have it create
|
||||
# a new resolv.conf. The file is prefixed with ``zzz`` to
|
||||
# make it the last file. Global dns options do not stack and last
|
||||
# man standing wins.
|
||||
if resolve1_enabled:
|
||||
# push DNS configuration to systemd-resolved
|
||||
dnsprocessing = "systemd-resolved"
|
||||
else:
|
||||
# update /etc/resolv.conf
|
||||
dnsprocessing = "default"
|
||||
|
||||
cfg = NM_IPA_CONF.format(
|
||||
dnsprocessing=dnsprocessing,
|
||||
servers=','.join(nameservers),
|
||||
searches=','.join(searchdomains)
|
||||
)
|
||||
with open(paths.NETWORK_MANAGER_IPA_CONF, 'w') as f:
|
||||
os.fchmod(f.fileno(), 0o644)
|
||||
f.write(cfg)
|
||||
# reload NetworkManager
|
||||
nm.reload_or_restart()
|
||||
|
||||
if not resolve1_enabled and not nm_enabled:
|
||||
# no NM running, no systemd-resolved detected
|
||||
# fall back to /etc/resolv.conf
|
||||
logger.debug(
|
||||
"Neither Network Manager nor systemd-resolved are enabled, "
|
||||
"write %s directly.", paths.RESOLV_CONF
|
||||
)
|
||||
cfg = [
|
||||
"# auto-generated by IPA installer",
|
||||
"search {}".format(' '.join(searchdomains)),
|
||||
]
|
||||
for nameserver in nameservers:
|
||||
cfg.append("nameserver {}".format(nameserver))
|
||||
with open(paths.RESOLV_CONF, 'w') as f:
|
||||
f.write('\n'.join(cfg))
|
||||
|
||||
def unconfigure_dns_resolver(self, fstore=None):
|
||||
"""Unconfigure global DNS resolver (e.g. /etc/resolv.conf)
|
||||
|
||||
:param fstore: optional file store for restore
|
||||
"""
|
||||
super().unconfigure_dns_resolver(fstore=fstore)
|
||||
# break circular import
|
||||
from ipaplatform.services import knownservices
|
||||
|
||||
nm = knownservices['NetworkManager']
|
||||
if os.path.isfile(paths.NETWORK_MANAGER_IPA_CONF):
|
||||
os.unlink(paths.NETWORK_MANAGER_IPA_CONF)
|
||||
if nm.is_enabled():
|
||||
nm.reload_or_restart()
|
||||
|
||||
def configure_pkcs11_modules(self, fstore):
|
||||
"""Disable global p11-kit configuration for NSS
|
||||
"""
|
||||
filenames = []
|
||||
for name, module, disabled_in in PKCS11_MODULES:
|
||||
filename = os.path.join(
|
||||
paths.ETC_PKCS11_MODULES_DIR,
|
||||
"{}.module".format(name)
|
||||
)
|
||||
if os.path.isfile(filename):
|
||||
# Only back up if file is not yet backed up and it does not
|
||||
# look like a file that is generated by IPA.
|
||||
with open(filename) as f:
|
||||
content = f.read()
|
||||
is_ipa_file = "IPA" in content
|
||||
if not is_ipa_file and not fstore.has_file(filename):
|
||||
logger.debug("Backing up existing '%s'.", filename)
|
||||
fstore.backup_file(filename)
|
||||
|
||||
with open(filename, "w") as f:
|
||||
f.write("# created by IPA installer\n")
|
||||
f.write("module: {}\n".format(module))
|
||||
# see man(5) pkcs11.conf
|
||||
f.write("disable-in: {}\n".format(", ".join(disabled_in)))
|
||||
os.fchmod(f.fileno(), 0o644)
|
||||
self.restore_context(filename)
|
||||
logger.debug("Created PKCS#11 module config '%s'.", filename)
|
||||
filenames.append(filename)
|
||||
|
||||
return filenames
|
||||
|
||||
def restore_pkcs11_modules(self, fstore):
|
||||
"""Restore global p11-kit configuration for NSS
|
||||
"""
|
||||
filenames = []
|
||||
for name, _module, _disabled_in in PKCS11_MODULES:
|
||||
filename = os.path.join(
|
||||
paths.ETC_PKCS11_MODULES_DIR,
|
||||
"{}.module".format(name)
|
||||
)
|
||||
try:
|
||||
os.unlink(filename)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
filenames.append(filename)
|
||||
|
||||
if fstore.has_file(filename):
|
||||
fstore.restore_file(filename)
|
||||
|
||||
return filenames
|
||||
|
||||
def get_pkcs11_modules(self):
|
||||
"""Return the list of module config files setup by IPA
|
||||
"""
|
||||
return tuple(os.path.join(paths.ETC_PKCS11_MODULES_DIR,
|
||||
"{}.module".format(name))
|
||||
for name, _module, _disabled in PKCS11_MODULES)
|
||||
|
||||
def enable_ldap_automount(self, statestore):
|
||||
"""
|
||||
Point automount to ldap in nsswitch.conf.
|
||||
This function is for non-SSSD setups only.
|
||||
"""
|
||||
super(RedHatTaskNamespace, self).enable_ldap_automount(statestore)
|
||||
|
||||
authselect_cmd = [paths.AUTHSELECT, "enable-feature",
|
||||
"with-custom-automount"]
|
||||
ipautil.run(authselect_cmd)
|
||||
|
||||
def disable_ldap_automount(self, statestore):
|
||||
"""Disable ldap-based automount"""
|
||||
super(RedHatTaskNamespace, self).disable_ldap_automount(statestore)
|
||||
|
||||
authselect_cmd = [paths.AUTHSELECT, "disable-feature",
|
||||
"with-custom-automount"]
|
||||
ipautil.run(authselect_cmd)
|
||||
|
||||
tasks = RedHatTaskNamespace()
|
||||
|
||||
Reference in New Issue
Block a user