[Pkg-freeipa-devel] [Git][freeipa-team/freeipa][master] 2 commits: ci: allow blhc and piuparts to fail
Timo Aaltonen
gitlab at salsa.debian.org
Thu Feb 27 13:44:11 GMT 2020
Timo Aaltonen pushed to branch master at FreeIPA packaging / freeipa
Commits:
01148081 by Timo Aaltonen at 2020-02-27T15:41:20+02:00
ci: allow blhc and piuparts to fail
- - - - -
1b61634d by Timo Aaltonen at 2020-02-27T15:42:26+02:00
write-out-only-one-cert-per-file.diff: Fix writing CA cert to file.
- - - - -
4 changed files:
- debian/changelog
- debian/gitlab-ci.yml
- debian/patches/series
- + debian/patches/write-out-only-one-cert-per-file.diff
Changes:
=====================================
debian/changelog
=====================================
@@ -5,6 +5,8 @@ freeipa (4.8.4-1) UNRELEASED; urgency=medium
* Fix-font-awesome-path.patch: Dropped, upstream.
* Use debhelper-compat.
* Add debian/gitlab-ci.yml.
+ - allow blhc and piuparts to fail
+ * write-out-only-one-cert-per-file.diff: Fix writing CA cert to file.
-- Timo Aaltonen <tjaalton at debian.org> Thu, 28 Nov 2019 15:07:31 +0200
=====================================
debian/gitlab-ci.yml
=====================================
@@ -1,3 +1,9 @@
include:
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
+
+blhc:
+ allow_failure: true
+
+piuparts:
+ allow_failure: true
=====================================
debian/patches/series
=====================================
@@ -4,3 +4,4 @@
fix-ods-conf-template.diff
# send upstream
+write-out-only-one-cert-per-file.diff
=====================================
debian/patches/write-out-only-one-cert-per-file.diff
=====================================
@@ -0,0 +1,506 @@
+From 84db94dfa458d44ed2546382d13acd42ceb0b7d7 Mon Sep 17 00:00:00 2001
+From: Sam Morris <sam at robots.org.uk>
+Date: Tue, 17 Dec 2019 18:41:35 +0000
+Subject: [PATCH] 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
+---
+ ipaplatform/base/paths.py | 4 +
+ ipaplatform/base/tasks.py | 36 +++++++
+ ipaplatform/debian/paths.py | 8 +-
+ ipaplatform/debian/tasks.py | 118 ++++++++++++++++++++++
+ ipaplatform/redhat/tasks.py | 194 +++++++++++++++++-------------------
+ 5 files changed, 259 insertions(+), 101 deletions(-)
+
+diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
+index 2dc22ef084..caca55701b 100644
+--- a/ipaplatform/base/paths.py
++++ b/ipaplatform/base/paths.py
+@@ -101,8 +101,12 @@ class BasePathNamespace:
+ OPENLDAP_LDAP_CONF = "/etc/openldap/ldap.conf"
+ PAM_LDAP_CONF = "/etc/pam_ldap.conf"
+ PASSWD = "/etc/passwd"
++ # Trusted CA certificates used to be written out to this file. In newer
++ # versions of FreeIPA, it has been replaced by IPA_P11_KIT.
+ SYSTEMWIDE_IPA_CA_CRT = "/etc/pki/ca-trust/source/anchors/ipa-ca.crt"
+ IPA_P11_KIT = "/etc/pki/ca-trust/source/ipa.p11-kit"
++ CA_CERTIFICATES_BUNDLE_PEM = None
++ CA_CERTIFICATES_DIR = None
+ NSS_DB_DIR = "/etc/pki/nssdb"
+ PKI_TOMCAT = "/etc/pki/pki-tomcat"
+ PKI_TOMCAT_ALIAS_DIR = "/etc/pki/pki-tomcat/alias"
+diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py
+index 86617a07f5..33ae5ed568 100644
+--- a/ipaplatform/base/tasks.py
++++ b/ipaplatform/base/tasks.py
+@@ -73,6 +73,23 @@ def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
+ Returns True if the operation succeeded, False otherwise.
+ """
+
++ try:
++ if self.platform_insert_ca_certs(ca_certs):
++ return self.reload_systemwide_ca_store()
++ except Exception:
++ logger.exception('Could not populate systemwide CA store')
++
++ return False
++
++ def platform_insert_ca_certs(self, ca_certs):
++ """
++ Platform implementations override this method to implement
++ population of the systemwide CA store.
++
++ Returns True if changes were made to the CA store, False otherwise.
++
++ Raises Exception if something went wrong.
++ """
+ raise NotImplementedError()
+
+ def remove_ca_certs_from_systemwide_ca_store(self):
+@@ -83,6 +100,25 @@ def remove_ca_certs_from_systemwide_ca_store(self):
+ Returns True if the operation succeeded, False otherwise.
+ """
+
++ try:
++ if self.platform_remove_ca_certs():
++ return self.reload_systemwide_ca_store()
++ except Exception:
++ logger.exception(
++ 'Could not remove certificates from systemwide CA store'
++ )
++
++ return False
++
++ def platform_remove_ca_certs(self):
++ """
++ Platform implementations override this method to implement
++ removal of certificates from the systemwide CA store.
++
++ Returns True if changes were made to the CA store, False otherwise.
++
++ Raises Exception if something went wrong.
++ """
+ raise NotImplementedError()
+
+ def get_svc_list_file(self):
+diff --git a/ipaplatform/debian/paths.py b/ipaplatform/debian/paths.py
+index 764b5a2815..2de7819e82 100644
+--- a/ipaplatform/debian/paths.py
++++ b/ipaplatform/debian/paths.py
+@@ -43,7 +43,13 @@ class DebianPathNamespace(BasePathNamespace):
+ CHRONY_CONF = "/etc/chrony/chrony.conf"
+ OPENLDAP_LDAP_CONF = "/etc/ldap/ldap.conf"
+ ETC_DEBIAN_VERSION = "/etc/debian_version"
+- IPA_P11_KIT = "/usr/local/share/ca-certificates/ipa-ca.crt"
++ # Old versions of freeipa wrote all trusted certificates to a single
++ # file, which is not supported by ca-certificates.
++ CA_CERTIFICATES_BUNDLE_PEM = "/usr/local/share/ca-certificates/ipa-ca.crt"
++ CA_CERTIFICATES_DIR = "/usr/local/share/ca-certificates/ipa-ca"
++ # Debian's p11-kit does not use ipa.p11-kit, so the file is provided
++ # for information only.
++ IPA_P11_KIT = "/usr/local/share/ca-certificates/ipa.p11-kit"
+ ETC_SYSCONFIG_DIR = "/etc/default"
+ SYSCONFIG_AUTOFS = "/etc/default/autofs"
+ SYSCONFIG_DIRSRV = "/etc/default/dirsrv"
+diff --git a/ipaplatform/debian/tasks.py b/ipaplatform/debian/tasks.py
+index 31982a0ee9..025c5d12d9 100644
+--- a/ipaplatform/debian/tasks.py
++++ b/ipaplatform/debian/tasks.py
+@@ -8,12 +8,21 @@
+
+ from __future__ import absolute_import
+
++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
++from ipapython.dn import DN
++
++logger = logging.getLogger(__name__)
++
+
+ class DebianTaskNamespace(RedHatTaskNamespace):
+ @staticmethod
+@@ -88,4 +97,113 @@ def configure_pkcs11_modules(self, fstore):
+ def restore_pkcs11_modules(self, fstore):
+ pass
+
++ 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
++
+ tasks = DebianTaskNamespace()
+diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py
+index 0a4f4370df..3e1d427705 100644
+--- a/ipaplatform/redhat/tasks.py
++++ b/ipaplatform/redhat/tasks.py
+@@ -28,6 +28,7 @@
+ import ctypes
+ import logging
+ import os
++from pathlib import Path
+ import socket
+ import traceback
+ import errno
+@@ -296,127 +297,120 @@ def reload_systemwide_ca_store(self):
+ logger.info("Systemwide CA database updated.")
+ return True
+
+- def insert_ca_certs_into_systemwide_ca_store(self, ca_certs):
++ 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):
+ # pylint: disable=ipa-forbidden-import
+ from ipalib import x509 # FixMe: break import cycle
+ from ipalib.errors import CertificateError
+ # pylint: enable=ipa-forbidden-import
+
+- new_cacert_path = paths.SYSTEMWIDE_IPA_CA_CRT
+-
+- if os.path.exists(new_cacert_path):
+- try:
+- os.remove(new_cacert_path)
+- except OSError as e:
+- logger.error(
+- "Could not remove %s: %s", new_cacert_path, e)
+- return False
+-
+- new_cacert_path = paths.IPA_P11_KIT
+-
++ path = Path(filename)
+ 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
++ f = open(path, 'w')
++ except IOError:
++ logger.error("Failed to open %s", path)
++ raise
+
+- f.write("# This file was created by IPA. Do not edit.\n"
+- "\n")
++ with f:
++ 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
++ os.fchmod(f.fileno(), 0o644)
++ except IOError:
++ logger.error("Failed to set mode of %s", path)
++ raise
+
+- 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):
++ has_eku = set()
++ for cert, nickname, trusted, _ext_key_usage in ca_certs:
+ 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)
++ 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
++
++ 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: 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" %
++ "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,
+- public_key_info=public_key_info,
+- value=value))
+- f.write(obj)
+- has_eku.add(public_key_info)
++ 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.close()
++ f.write(obj)
+
+- # Add the CA to the systemwide CA trust database
+- if not self.reload_systemwide_ca_store():
+- return False
++ 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 remove_ca_certs_from_systemwide_ca_store(self):
+- result = True
+- update = False
++ 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),
++ ])
+
+- # 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
++ def remove_ca_certificates_bundle(self, filename):
++ path = Path(filename)
++ if not path.is_file():
++ return False
+
+- if update:
+- if not self.reload_systemwide_ca_store():
+- return False
++ try:
++ path.unlink()
++ except Exception:
++ logger.error("Could not remove %s", path)
++ raise
+
+- return result
++ return True
+
+ def backup_hostname(self, fstore, statestore):
+ filepath = paths.ETC_HOSTNAME
View it on GitLab: https://salsa.debian.org/freeipa-team/freeipa/-/compare/341a561eafc71adcf8f2916f32d61d8e06f222b4...1b61634da74b4b862883e553b43bb8015819ef7f
--
View it on GitLab: https://salsa.debian.org/freeipa-team/freeipa/-/compare/341a561eafc71adcf8f2916f32d61d8e06f222b4...1b61634da74b4b862883e553b43bb8015819ef7f
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-freeipa-devel/attachments/20200227/01c0b763/attachment-0001.html>
More information about the Pkg-freeipa-devel
mailing list