freeipa/ipaplatform/debian/tasks.py

214 lines
6.7 KiB
Python
Raw Normal View History

#
# Copyright (C) 2017 FreeIPA Contributors see COPYING for license
#
"""
This module contains default Debian-specific implementations of system tasks.
"""
from __future__ import absolute_import
Debian: write out only one CA certificate per file ca-certificates populates /etc/ssl/certs with symlinks to its input files and then runs 'openssl rehash' to create the symlinks that libssl uses to look up a CA certificate to see if it is trused. 'openssl rehash' ignores any files that contain more than one certificate: <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=945274>. With this change, we write out trusted CA certificates to /usr/local/share/ca-certificates/ipa-ca, one certificate per file. The logic that decides whether to reload the store is moved up into the original `insert_ca_certs_into_systemwide_ca_store` and `remove_ca_certs_from_systemwide_ca_store` methods. These methods now also handle any exceptions that may be thrown while updating the store. The functions that actually manipulate the store are factored out into new `platform_{insert,remove}_ca_certs` methods, which implementations must override. These new methods also orchestrate the cleanup of deprecated files (such as `/etc/pki/ca-trust/source/anchors/ipa-ca.crt`), rather than having the cleanup code be included in the same method that creates `/etc/pki/ca-trust/source/ipa.p11-kit`. As well as creating `/usr/local/share/ca-certificates/ipa-ca`, Debian systems will now also have `/usr/local/share/ca-certificates/ipa.p11-kit` be created. Note that `p11-kit` in Debian does not use this file. Fixes: https://pagure.io/freeipa/issue/8106 Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Timo Aaltonen <tjaalton@debian.org> Reviewed-By: Rob Crittenden <rcritten@redhat.com>
2019-12-17 12:41:35 -06:00
import logging
import os
import shutil
from pathlib import Path
from ipaplatform.base.tasks import BaseTaskNamespace
from ipaplatform.redhat.tasks import RedHatTaskNamespace
from ipaplatform.paths import paths
from ipapython import directivesetter
from ipapython import ipautil
Debian: write out only one CA certificate per file ca-certificates populates /etc/ssl/certs with symlinks to its input files and then runs 'openssl rehash' to create the symlinks that libssl uses to look up a CA certificate to see if it is trused. 'openssl rehash' ignores any files that contain more than one certificate: <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=945274>. With this change, we write out trusted CA certificates to /usr/local/share/ca-certificates/ipa-ca, one certificate per file. The logic that decides whether to reload the store is moved up into the original `insert_ca_certs_into_systemwide_ca_store` and `remove_ca_certs_from_systemwide_ca_store` methods. These methods now also handle any exceptions that may be thrown while updating the store. The functions that actually manipulate the store are factored out into new `platform_{insert,remove}_ca_certs` methods, which implementations must override. These new methods also orchestrate the cleanup of deprecated files (such as `/etc/pki/ca-trust/source/anchors/ipa-ca.crt`), rather than having the cleanup code be included in the same method that creates `/etc/pki/ca-trust/source/ipa.p11-kit`. As well as creating `/usr/local/share/ca-certificates/ipa-ca`, Debian systems will now also have `/usr/local/share/ca-certificates/ipa.p11-kit` be created. Note that `p11-kit` in Debian does not use this file. Fixes: https://pagure.io/freeipa/issue/8106 Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Timo Aaltonen <tjaalton@debian.org> Reviewed-By: Rob Crittenden <rcritten@redhat.com>
2019-12-17 12:41:35 -06:00
from ipapython.dn import DN
logger = logging.getLogger(__name__)
class DebianTaskNamespace(RedHatTaskNamespace):
@staticmethod
def restore_pre_ipa_client_configuration(fstore, statestore,
was_sssd_installed,
was_sssd_configured):
try:
ipautil.run(["pam-auth-update",
"--package", "--remove", "mkhomedir"])
except ipautil.CalledProcessError:
return False
return True
@staticmethod
def set_nisdomain(nisdomain):
# Debian doesn't use authconfig, nothing to set
return True
@staticmethod
def modify_nsswitch_pam_stack(sssd, mkhomedir, statestore, sudo=True):
if mkhomedir:
try:
ipautil.run(["pam-auth-update",
"--package", "--enable", "mkhomedir"])
except ipautil.CalledProcessError:
return False
return True
else:
return True
@staticmethod
def modify_pam_to_use_krb5(statestore):
# Debian doesn't use authconfig, this is handled by pam-auth-update
return True
@staticmethod
def backup_auth_configuration(path):
# Debian doesn't use authconfig, nothing to backup
return True
@staticmethod
def restore_auth_configuration(path):
# Debian doesn't use authconfig, nothing to restore
return True
def migrate_auth_configuration(self, statestore):
# Debian doesn't have authselect
return True
def configure_httpd_wsgi_conf(self):
# Debian doesn't require special mod_wsgi configuration
pass
def configure_httpd_protocol(self):
# TLS 1.3 is not yet supported
directivesetter.set_directive(paths.HTTPD_SSL_CONF,
'SSLProtocol',
'TLSv1.2', False)
def setup_httpd_logging(self):
# Debian handles httpd logging differently
pass
def configure_pkcs11_modules(self, fstore):
# Debian doesn't use p11-kit
pass
def restore_pkcs11_modules(self, fstore):
pass
Debian: write out only one CA certificate per file ca-certificates populates /etc/ssl/certs with symlinks to its input files and then runs 'openssl rehash' to create the symlinks that libssl uses to look up a CA certificate to see if it is trused. 'openssl rehash' ignores any files that contain more than one certificate: <https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=945274>. With this change, we write out trusted CA certificates to /usr/local/share/ca-certificates/ipa-ca, one certificate per file. The logic that decides whether to reload the store is moved up into the original `insert_ca_certs_into_systemwide_ca_store` and `remove_ca_certs_from_systemwide_ca_store` methods. These methods now also handle any exceptions that may be thrown while updating the store. The functions that actually manipulate the store are factored out into new `platform_{insert,remove}_ca_certs` methods, which implementations must override. These new methods also orchestrate the cleanup of deprecated files (such as `/etc/pki/ca-trust/source/anchors/ipa-ca.crt`), rather than having the cleanup code be included in the same method that creates `/etc/pki/ca-trust/source/ipa.p11-kit`. As well as creating `/usr/local/share/ca-certificates/ipa-ca`, Debian systems will now also have `/usr/local/share/ca-certificates/ipa.p11-kit` be created. Note that `p11-kit` in Debian does not use this file. Fixes: https://pagure.io/freeipa/issue/8106 Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com> Reviewed-By: Timo Aaltonen <tjaalton@debian.org> Reviewed-By: Rob Crittenden <rcritten@redhat.com>
2019-12-17 12:41:35 -06:00
def platform_insert_ca_certs(self, ca_certs):
# ca-certificates does not use this file, so it doesn't matter if we
# fail to create it.
try:
self.write_p11kit_certs(paths.IPA_P11_KIT, ca_certs),
except Exception:
logger.exception("""\
Could not create p11-kit anchor trust file. On Debian this file is not
used by ca-certificates and is provided for information only.\
""")
return any([
self.write_ca_certificates_dir(
paths.CA_CERTIFICATES_DIR, ca_certs
),
self.remove_ca_certificates_bundle(
paths.CA_CERTIFICATES_BUNDLE_PEM
),
])
def write_ca_certificates_dir(self, directory, ca_certs):
# pylint: disable=ipa-forbidden-import
from ipalib import x509 # FixMe: break import cycle
# pylint: enable=ipa-forbidden-import
path = Path(directory)
try:
path.mkdir(mode=0o755, exist_ok=True)
except Exception:
logger.error("Could not create %s", path)
raise
for cert, nickname, trusted, _ext_key_usage in ca_certs:
if not trusted:
continue
# I'm not handling errors here because they have already
# been checked by the time we get here
subject = DN(cert.subject)
issuer = DN(cert.issuer)
# Construct the certificate filename using the Subject DN so that
# the user can see which CA a particular file is for, and include
# the serial number to disambiguate clashes where a subordinate CA
# had a new certificate issued.
#
# Strictly speaking, certificates are uniquely idenified by (Issuer
# DN, Serial Number). Do we care about the possibility of a clash
# where a subordinate CA had two certificates issued by different
# CAs who used the same serial number?)
filename = f'{subject.ldap_text()} {cert.serial_number}.crt'
# pylint: disable=old-division
cert_path = path / filename
# pylint: enable=old-division
try:
f = open(cert_path, 'w')
except Exception:
logger.error("Could not create %s", cert_path)
raise
with f:
try:
os.fchmod(f.fileno(), 0o644)
except Exception:
logger.error("Could not set mode of %s", cert_path)
raise
try:
f.write(f"""\
This file was created by IPA. Do not edit.
Description: {nickname}
Subject: {subject.ldap_text()}
Issuer: {issuer.ldap_text()}
Serial Number (dec): {cert.serial_number}
Serial Number (hex): {cert.serial_number:#x}
""")
pem = cert.public_bytes(x509.Encoding.PEM).decode('ascii')
f.write(pem)
except Exception:
logger.error("Could not write to %s", cert_path)
raise
return True
def platform_remove_ca_certs(self):
return any([
self.remove_ca_certificates_dir(paths.CA_CERTIFICATES_DIR),
self.remove_ca_certificates_bundle(paths.IPA_P11_KIT),
self.remove_ca_certificates_bundle(
paths.CA_CERTIFICATES_BUNDLE_PEM
),
])
def remove_ca_certificates_dir(self, directory):
path = Path(paths.CA_CERTIFICATES_DIR)
if not path.exists():
return False
try:
shutil.rmtree(path)
except Exception:
logger.error("Could not remove %s", path)
raise
return True
# Debian doesn't use authselect, so call enable/disable_ldap_automount
# from BaseTaskNamespace.
def enable_ldap_automount(self, statestore):
return BaseTaskNamespace.enable_ldap_automount(self, statestore)
def disable_ldap_automount(self, statestore):
return BaseTaskNamespace.disable_ldap_automount(self, statestore)
tasks = DebianTaskNamespace()