Imported Upstream version 4.8.10
This commit is contained in:
7
ipaplatform/suse/__init__.py
Normal file
7
ipaplatform/suse/__init__.py
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Copyright (C) 2020 FreeIPA Contributors, see COPYING for license
|
||||
#
|
||||
|
||||
"""
|
||||
This module contains SUSE specific platform files.
|
||||
"""
|
||||
22
ipaplatform/suse/constants.py
Normal file
22
ipaplatform/suse/constants.py
Normal file
@@ -0,0 +1,22 @@
|
||||
#
|
||||
# Copyright (C) 2020 FreeIPA Contributors, see COPYING for license
|
||||
#
|
||||
|
||||
"""
|
||||
This SUSE OS family base platform module exports default platform
|
||||
related constants for the SUSE OS family-based systems.
|
||||
"""
|
||||
|
||||
# Fallback to default path definitions
|
||||
from ipaplatform.base.constants import BaseConstantsNamespace
|
||||
|
||||
|
||||
class SuseConstantsNamespace(BaseConstantsNamespace):
|
||||
HTTPD_USER = "wwwrun"
|
||||
HTTPD_GROUP = "www"
|
||||
# Don't have it yet
|
||||
SSSD_USER = "root"
|
||||
TLS_HIGH_CIPHERS = None
|
||||
|
||||
|
||||
constants = SuseConstantsNamespace()
|
||||
88
ipaplatform/suse/paths.py
Normal file
88
ipaplatform/suse/paths.py
Normal file
@@ -0,0 +1,88 @@
|
||||
#
|
||||
# Copyright (C) 2020 FreeIPA Contributors, see COPYING for license
|
||||
#
|
||||
|
||||
"""
|
||||
This SUSE OS family base platform module exports default filesystem paths as
|
||||
common in SUSE OS family-based systems.
|
||||
"""
|
||||
|
||||
from ipaplatform.base.paths import BasePathNamespace
|
||||
|
||||
|
||||
class SusePathNamespace(BasePathNamespace):
|
||||
BIN_HOSTNAMECTL = "/usr/bin/hostnamectl"
|
||||
SYSTEMCTL = "/usr/bin/systemctl"
|
||||
ETC_HTTPD_DIR = "/etc/apache2"
|
||||
HTTPD_ALIAS_DIR = "/etc/apache2/ipa"
|
||||
GSSAPI_SESSION_KEY = "/etc/apache2/ipa/ipasession.key"
|
||||
HTTPD_CONF_D_DIR = "/etc/apache2/conf.d/"
|
||||
HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/apache2/conf.d/ipa-kdc-proxy.conf"
|
||||
HTTPD_IPA_PKI_PROXY_CONF = "/etc/apache2/conf.d/ipa-pki-proxy.conf"
|
||||
HTTPD_IPA_REWRITE_CONF = "/etc/apache2/conf.d/ipa-rewrite.conf"
|
||||
HTTPD_IPA_CONF = "/etc/apache2/conf.d/ipa.conf"
|
||||
HTTPD_NSS_CONF = "/etc/apache2/conf.d/nss.conf"
|
||||
HTTPD_SSL_CONF = "/etc/apache2/conf.d/ssl.conf"
|
||||
HTTPD_SSL_SITE_CONF = "/etc/apache2/conf.d/ssl.conf"
|
||||
HTTPD_PASSWORD_CONF = "/etc/apache2/ipa/password.conf"
|
||||
NAMED_CUSTOM_CONF = "/etc/named.d/ipa-ext.conf"
|
||||
NAMED_CUSTOM_OPTIONS_CONF = "/etc/named.d/ipa-options-ext.conf"
|
||||
NAMED_VAR_DIR = "/var/lib/named"
|
||||
NAMED_MANAGED_KEYS_DIR = "/var/lib/named/dyn"
|
||||
IPA_P11_KIT = "/etc/pki/trust/ipa.p11-kit"
|
||||
# Those files are only here to be able to configure them, we copy those in
|
||||
# rpm spec to fillupdir
|
||||
SYSCONFIG_HTTPD = "/etc/sysconfig/apache2"
|
||||
SYSCONFIG_NAMED = "/etc/sysconfig/named-named"
|
||||
SYSCONFIG_NTPD = "/etc/sysconfig/ntp"
|
||||
SYSCONF_NETWORK = "/etc/sysconfig/network/config"
|
||||
SYSTEMD_SYSTEM_HTTPD_D_DIR = "/etc/systemd/system/apache2.service.d/"
|
||||
SYSTEMD_SYSTEM_HTTPD_IPA_CONF = (
|
||||
"/etc/systemd/system/apache2.service.d/ipa.conf"
|
||||
)
|
||||
CERTMONGER_COMMAND_TEMPLATE = "/usr/lib/ipa/certmonger/%s"
|
||||
CHROMIUM_BROWSER = "/usr/bin/chromium"
|
||||
BIN_NISDOMAINNAME = "/bin/nisdomainname"
|
||||
BIND_LDAP_DNS_IPA_WORKDIR = "/var/lib/named/dyndb-ldap/ipa/"
|
||||
BIND_LDAP_DNS_ZONE_WORKDIR = "/var/lib/named/dyndb-ldap/ipa/master/"
|
||||
PAM_KRB5_SO = "/lib/security/pam_krb5.so"
|
||||
PAM_KRB5_SO_64 = PAM_KRB5_SO
|
||||
# openSUSE still uses lib for libexec, this will change when we don't
|
||||
# anymore
|
||||
LIBEXEC_CERTMONGER_DIR = "/usr/lib/certmonger"
|
||||
DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT = (
|
||||
"/usr/lib/certmonger/dogtag-ipa-ca-renew-agent-submit"
|
||||
)
|
||||
DOGTAG_IPA_RENEW_AGENT_SUBMIT = (
|
||||
"/usr/lib/certmonger/dogtag-ipa-renew-agent-submit"
|
||||
)
|
||||
CERTMONGER_DOGTAG_SUBMIT = "/usr/lib/certmonger/dogtag-submit"
|
||||
IPA_SERVER_GUARD = "/usr/lib/certmonger/ipa-server-guard"
|
||||
GENERATE_RNDC_KEY = "/usr/lib/generate-rndc-key.sh"
|
||||
LIBEXEC_IPA_DIR = "/usr/lib/ipa"
|
||||
IPA_DNSKEYSYNCD_REPLICA = "/usr/lib/ipa/ipa-dnskeysync-replica"
|
||||
IPA_DNSKEYSYNCD = "/usr/lib/ipa/ipa-dnskeysyncd"
|
||||
IPA_HTTPD_KDCPROXY = "/usr/lib/ipa/ipa-httpd-kdcproxy"
|
||||
IPA_ODS_EXPORTER = "/usr/lib/ipa/ipa-ods-exporter"
|
||||
IPA_PKI_RETRIEVE_KEY = "/usr/lib/ipa/ipa-pki-retrieve-key"
|
||||
IPA_HTTPD_PASSWD_READER = "/usr/lib/ipa/ipa-httpd-pwdreader"
|
||||
IPA_PKI_WAIT_RUNNING = "/usr/lib/ipa/ipa-pki-wait-running"
|
||||
DNSSEC_KEYFROMLABEL = "/usr/sbin/dnssec-keyfromlabel-pkcs11"
|
||||
VAR_KERBEROS_KRB5KDC_DIR = "/var/lib/kerberos/krb5kdc/"
|
||||
VAR_KRB5KDC_K5_REALM = "/var/lib/kerberos/krb5kdc/.k5."
|
||||
CACERT_PEM = "/var/lib/kerberos/krb5kdc/cacert.pem"
|
||||
KRB5KDC_KADM5_ACL = "/var/lib/kerberos/krb5kdc/kadm5.acl"
|
||||
KRB5KDC_KADM5_KEYTAB = "/var/lib/kerberos/krb5kdc/kadm5.keytab"
|
||||
KRB5KDC_KDC_CONF = "/var/lib/kerberos/krb5kdc/kdc.conf"
|
||||
KDC_CERT = "/var/lib/kerberos/krb5kdc/kdc.crt"
|
||||
KDC_KEY = "/var/lib/kerberos/krb5kdc/kdc.key"
|
||||
NAMED_RUN = "/var/lib/named/data/named.run"
|
||||
IPA_CUSTODIA_HANDLER = "/usr/lib/ipa/custodia"
|
||||
WSGI_PREFIX_DIR = "/run/apache2/wsgi"
|
||||
KDESTROY = "/usr/lib/mit/bin/kdestroy"
|
||||
BIN_KVNO = "/usr/lib/mit/bin/kvno"
|
||||
UPDATE_CA_TRUST = "/usr/sbin/update-ca-certificates"
|
||||
AUTHSELECT = "/usr/bin/authselect"
|
||||
|
||||
|
||||
paths = SusePathNamespace()
|
||||
194
ipaplatform/suse/services.py
Normal file
194
ipaplatform/suse/services.py
Normal file
@@ -0,0 +1,194 @@
|
||||
#
|
||||
# Copyright (C) 2020 FreeIPA Contributors, see COPYING for license
|
||||
#
|
||||
|
||||
import os
|
||||
import logging
|
||||
import time
|
||||
import contextlib
|
||||
|
||||
from ipaplatform.base import services as base_services
|
||||
from ipapython import ipautil, dogtag
|
||||
from ipaplatform.paths import paths
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
suse_system_units = dict(
|
||||
(x, "%s.service" % x) for x in base_services.wellknownservices
|
||||
)
|
||||
suse_system_units["httpd"] = "apache2.service"
|
||||
|
||||
suse_system_units["dirsrv"] = "dirsrv@.service"
|
||||
suse_system_units["pki-tomcatd"] = "pki-tomcatd@pki-tomcat.service"
|
||||
suse_system_units["pki_tomcatd"] = suse_system_units["pki-tomcatd"]
|
||||
suse_system_units["ipa-otpd"] = "ipa-otpd.socket"
|
||||
suse_system_units["ipa-dnskeysyncd"] = "ipa-dnskeysyncd.service"
|
||||
suse_system_units["named-regular"] = "named.service"
|
||||
suse_system_units["named-pkcs11"] = "named.service"
|
||||
suse_system_units["named"] = "named.service"
|
||||
suse_system_units["ods-enforcerd"] = "ods-enforcerd.service"
|
||||
suse_system_units["ods_enforcerd"] = suse_system_units["ods-enforcerd"]
|
||||
suse_system_units["ods-signerd"] = "ods-signerd.service"
|
||||
suse_system_units["ods_signerd"] = suse_system_units["ods-signerd"]
|
||||
|
||||
|
||||
class SuseService(base_services.SystemdService):
|
||||
system_units = suse_system_units
|
||||
|
||||
def __init__(self, service_name, api=None):
|
||||
systemd_name = service_name
|
||||
if service_name in self.system_units:
|
||||
systemd_name = self.system_units[service_name]
|
||||
else:
|
||||
if "." not in service_name:
|
||||
systemd_name = "%s.service" % (service_name)
|
||||
super().__init__(service_name, systemd_name, api)
|
||||
|
||||
|
||||
class SuseDirectoryService(SuseService):
|
||||
def is_installed(self, instance_name):
|
||||
file_path = "{}/{}-{}".format(
|
||||
paths.ETC_DIRSRV, "slapd", instance_name
|
||||
)
|
||||
return os.path.exists(file_path)
|
||||
|
||||
def restart(
|
||||
self, instance_name="", capture_output=True, wait=True, ldapi=False
|
||||
):
|
||||
# We need to explicitly enable instances to install proper symlinks as
|
||||
# dirsrv.target.wants/ dependencies. Standard systemd service class
|
||||
# does it on enable() method call. Unfortunately, ipa-server-install
|
||||
# does not do explicit dirsrv.enable() because the service startup is
|
||||
# handled by ipactl.
|
||||
#
|
||||
# If we wouldn't do this, our instances will not be started as systemd
|
||||
# would not have any clue about instances (PKI-IPA and the domain we
|
||||
# serve) at all. Thus, hook into dirsrv.restart().
|
||||
|
||||
if instance_name:
|
||||
elements = self.systemd_name.split("@")
|
||||
|
||||
srv_etc = os.path.join(
|
||||
paths.ETC_SYSTEMD_SYSTEM_DIR, self.systemd_name
|
||||
)
|
||||
srv_tgt = os.path.join(
|
||||
paths.ETC_SYSTEMD_SYSTEM_DIR,
|
||||
self.SYSTEMD_SRV_TARGET % (elements[0]),
|
||||
)
|
||||
srv_lnk = os.path.join(
|
||||
srv_tgt, self.service_instance(instance_name)
|
||||
)
|
||||
|
||||
if not os.path.exists(srv_etc):
|
||||
self.enable(instance_name)
|
||||
elif not os.path.samefile(srv_etc, srv_lnk):
|
||||
os.unlink(srv_lnk)
|
||||
os.symlink(srv_etc, srv_lnk)
|
||||
|
||||
with self._wait(instance_name, wait, ldapi) as wait:
|
||||
super().restart(
|
||||
instance_name, capture_output=capture_output, wait=wait
|
||||
)
|
||||
|
||||
def start(
|
||||
self, instance_name="", capture_output=True, wait=True, ldapi=False
|
||||
):
|
||||
with self._wait(instance_name, wait, ldapi) as wait:
|
||||
super().start(
|
||||
instance_name, capture_output=capture_output, wait=wait
|
||||
)
|
||||
|
||||
@contextlib.contextmanager
|
||||
def _wait(self, instance_name, wait, ldapi):
|
||||
if ldapi:
|
||||
instance_name = self.service_instance(instance_name)
|
||||
if instance_name.endswith(".service"):
|
||||
instance_name = instance_name[:-8]
|
||||
if instance_name.startswith("dirsrv"):
|
||||
# this is intentional, return the empty string if the instance
|
||||
# name is 'dirsrv'
|
||||
instance_name = instance_name[7:]
|
||||
if not instance_name:
|
||||
ldapi = False
|
||||
if ldapi:
|
||||
yield False
|
||||
socket_name = paths.SLAPD_INSTANCE_SOCKET_TEMPLATE % instance_name
|
||||
ipautil.wait_for_open_socket(
|
||||
socket_name, self.api.env.startup_timeout
|
||||
)
|
||||
else:
|
||||
yield wait
|
||||
|
||||
|
||||
class SuseIPAService(SuseService):
|
||||
# Credits to upstream developer
|
||||
def enable(self, instance_name=""):
|
||||
super().enable(instance_name)
|
||||
self.restart(instance_name)
|
||||
|
||||
|
||||
class SuseCAService(SuseService):
|
||||
# Credits to upstream developer
|
||||
def wait_until_running(self):
|
||||
logger.debug("Waiting until the CA is running")
|
||||
timeout = float(self.api.env.startup_timeout)
|
||||
op_timeout = time.time() + timeout
|
||||
while time.time() < op_timeout:
|
||||
try:
|
||||
# check status of CA instance on this host, not remote ca_host
|
||||
status = dogtag.ca_status(self.api.env.host)
|
||||
except Exception as e:
|
||||
status = "check interrupted due to error: %s" % e
|
||||
logger.debug("The CA status is: %s", status)
|
||||
if status == "running":
|
||||
break
|
||||
logger.debug("Waiting for CA to start...")
|
||||
time.sleep(1)
|
||||
else:
|
||||
raise RuntimeError("CA did not start in %ss" % timeout)
|
||||
|
||||
def is_running(self, instance_name="", wait=True):
|
||||
if instance_name:
|
||||
return super().is_running(instance_name)
|
||||
try:
|
||||
status = dogtag.ca_status()
|
||||
if status == "running":
|
||||
return True
|
||||
elif status == "starting" and wait:
|
||||
# Exception is raised if status is 'starting' even after wait
|
||||
self.wait_until_running()
|
||||
return True
|
||||
except Exception as e:
|
||||
logger.debug("Failed to check CA status: %s", e)
|
||||
return False
|
||||
|
||||
|
||||
def suse_service_class_factory(name, api):
|
||||
if name == "dirsrv":
|
||||
return SuseDirectoryService(name, api)
|
||||
if name == "ipa":
|
||||
return SuseIPAService(name, api)
|
||||
if name in ("pki-tomcatd", "pki_tomcatd"):
|
||||
return SuseCAService(name, api)
|
||||
return SuseService(name, api)
|
||||
|
||||
|
||||
class SuseServices(base_services.KnownServices):
|
||||
def service_class_factory(self, name, api=None):
|
||||
return suse_service_class_factory(name, api)
|
||||
|
||||
# Credits to upstream developer
|
||||
def __init__(self):
|
||||
# pylint: disable=ipa-forbidden-import
|
||||
import ipalib
|
||||
|
||||
# pylint: enable=ipa-forbidden-import
|
||||
services = dict()
|
||||
for s in base_services.wellknownservices:
|
||||
services[s] = self.service_class_factory(s, ipalib.api)
|
||||
super().__init__(services)
|
||||
|
||||
|
||||
timedate_services = ["ntpd"]
|
||||
service = suse_service_class_factory
|
||||
knownservices = SuseServices()
|
||||
46
ipaplatform/suse/tasks.py
Normal file
46
ipaplatform/suse/tasks.py
Normal file
@@ -0,0 +1,46 @@
|
||||
#
|
||||
# Copyright (C) 2020 FreeIPA Contributors, see COPYING for license
|
||||
#
|
||||
|
||||
"""
|
||||
This module contains default SUSE OS family-specific implementations of
|
||||
system tasks.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from ipaplatform.paths import paths
|
||||
from ipaplatform.redhat.tasks import RedHatTaskNamespace
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SuseTaskNamespace(RedHatTaskNamespace):
|
||||
def restore_context(self, filepath, force=False):
|
||||
pass # FIXME: Implement after libexec move
|
||||
|
||||
def check_selinux_status(self, restorecon=paths.RESTORECON):
|
||||
pass # FIXME: Implement after libexec move
|
||||
|
||||
def set_nisdomain(self, nisdomain):
|
||||
nis_variable = "NETCONFIG_NIS_STATIC_DOMAIN"
|
||||
try:
|
||||
with open(paths.SYSCONF_NETWORK, "r") as f:
|
||||
content = [
|
||||
line
|
||||
for line in f
|
||||
if not line.strip().upper().startswith(nis_variable)
|
||||
]
|
||||
except IOError:
|
||||
content = []
|
||||
|
||||
content.append("{}={}\n".format(nis_variable, nisdomain))
|
||||
|
||||
with open(paths.SYSCONF_NETWORK, "w") as f:
|
||||
f.writelines(content)
|
||||
|
||||
def set_selinux_booleans(self, required_settings, backup_func=None):
|
||||
return False # FIXME: Implement after libexec move
|
||||
|
||||
|
||||
tasks = SuseTaskNamespace()
|
||||
Reference in New Issue
Block a user