From 12d093e8b1a675517e05f5503f3b187e2eb2c002 Mon Sep 17 00:00:00 2001 From: Michael Marineau Date: Wed, 11 Jun 2014 22:48:49 -0700 Subject: [PATCH] fix(app-misc/ca-certificates): Never rehash certs during boot. This kills the massive time-waster we currently have during boot to cleanup/refresh OpenSSL's certificate directory in /etc/ssl/certs. System provided certs are now hashed at build time and tempfiles is used to install the proper links. The certificate bundle is also created at build time and provided as a symlink. Since tempfiles does not help us clean up broken links to certs that have been removed that task has been moved to clean-ca-certificates.service which is still run on every boot. The update-ca-certificates.service is now only responsible for recreating the certificate bundle if required. On systems where the user has never run update-ca-certificates the certificate bundle is just a symlink to the copy in /usr and update-ca-certificates.service never runs on boot. If the user does run update-ca-certificates then update-ca-certificates.service will rewrite the bundle only if the directory has not been modified since the last time it ran. There are a few edge cases where if stale hash links may be left if a system provided cert was replaced a subject that is different enough to change the hash but not change the file name. I don't expect that to ever happen though. Also hash collisions between the system certs and each other or user provided certs are not handled gracefully but should be rare. tempfiles will report wrong symlink errors in that case. --- ....ebuild => ca-certificates-3.16-r1.ebuild} | 21 +++++++++-- .../files/clean-ca-certificates.service | 12 +++++++ .../files/update-ca-certificates | 35 +++++++++++++------ .../files/update-ca-certificates.service | 10 +++--- 4 files changed, 61 insertions(+), 17 deletions(-) rename sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/{ca-certificates-3.16.ebuild => ca-certificates-3.16-r1.ebuild} (70%) create mode 100644 sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/clean-ca-certificates.service diff --git a/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/ca-certificates-3.16.ebuild b/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/ca-certificates-3.16-r1.ebuild similarity index 70% rename from sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/ca-certificates-3.16.ebuild rename to sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/ca-certificates-3.16-r1.ebuild index 3b78ac4b7a..4fd3b9fbab 100644 --- a/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/ca-certificates-3.16.ebuild +++ b/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/ca-certificates-3.16-r1.ebuild @@ -25,13 +25,25 @@ RDEPEND="dev-libs/openssl DEPEND="${RDEPEND} ${PYTHON_DEPS}" +sym_to_usr() { + local l="/etc/ssl/certs/${1##*/}" + local p="../../../usr/share/${PN}/${1}" + echo "L ${l} - - - - ${p}" +} + gen_tmpfiles() { local certfile echo "d /etc/ssl - - - - -" echo "d /etc/ssl/certs - - - - -" + sym_to_usr ca-certificates.crt for certfile in "$@"; do - local l="/etc/ssl/certs/${certfile##*/}" - local p="../../../usr/share/${PN}/${certfile}" + sym_to_usr "${certfile}" + done + for certfile in "$@"; do + local certhash=$(openssl x509 -hash -noout -in "${certfile}") + # This assumes the hashes have no collisions + local l="/etc/ssl/certs/${certhash}.0" + local p="${certfile##*/}" echo "L ${l} - - - - ${p}" done } @@ -39,20 +51,23 @@ gen_tmpfiles() { src_compile() { local certdata="${MY_P}/nss/lib/ckfw/builtins/certdata.txt" ${PYTHON} "${FILESDIR}/certdata2pem.py" "${certdata}" mozilla || die + cat mozilla/*.pem > ca-certificates.crt || die gen_tmpfiles mozilla/*.pem > ${PN}.conf || die } src_install() { insinto /usr/share/${PN} + doins ca-certificates.crt doins -r mozilla dosbin "${FILESDIR}/update-ca-certificates" + systemd_dounit "${FILESDIR}/clean-ca-certificates.service" systemd_dounit "${FILESDIR}/update-ca-certificates.service" + systemd_enable_service sysinit.target clean-ca-certificates.service systemd_enable_service sysinit.target update-ca-certificates.service systemd_dotmpfilesd ${PN}.conf # Setup initial links in /etc dodir /etc/ssl/certs tmpfiles_create - bash "${FILESDIR}/update-ca-certificates" "${D}/etc/ssl/certs" || die } diff --git a/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/clean-ca-certificates.service b/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/clean-ca-certificates.service new file mode 100644 index 0000000000..50a4fd38e9 --- /dev/null +++ b/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/clean-ca-certificates.service @@ -0,0 +1,12 @@ +[Unit] +Description=Clean up broken links in /etc/ssl/certs +# Since other services depend on the certificate store run this early +DefaultDependencies=no +Wants=systemd-tmpfiles-setup.service +After=systemd-tmpfiles-setup.service +Before=sysinit.target +ConditionPathIsReadWrite=/etc/ssl/certs + +[Service] +Type=oneshot +ExecStart=/usr/bin/find -L /etc/ssl/certs -type l -delete diff --git a/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/update-ca-certificates b/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/update-ca-certificates index 60840d89ff..ea7cb27cff 100644 --- a/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/update-ca-certificates +++ b/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/update-ca-certificates @@ -1,27 +1,42 @@ #!/bin/bash -CERTSDIR="${1:-${ROOT}/etc/ssl/certs}" +set -e + +CERTSDIR="${ROOT}/etc/ssl/certs" +CERTBUNDLE="${CERTSDIR}/ca-certificates.crt" +SKIP_REHASH=0 + +while [[ $# -gt 0 ]]; do + case "$1" in + --skip-rehash) + SKIP_REHASH=1 ;; + --help|-h|*) + echo "$0 [--skip-rehash]" + exit ;; + esac + shift +done if [[ ! -w "${CERTSDIR}" ]]; then echo "Error: SSL certificate directory ${CERTSDIR} isn't writable" >&2 exit 1 fi -set -e +if [[ ${SKIP_REHASH} -ne 1 ]]; then + c_rehash "${CERTSDIR}" +fi -echo "Pruning broken links in ${CERTSDIR}" -find -L "${CERTSDIR}" -type l -delete - -echo "Rehashing certificate files in ${CERTSDIR}" -c_rehash "${CERTSDIR}" - -CERTBUNDLE="${CERTSDIR}/ca-certificates.crt" if [[ ! -e "${CERTBUNDLE}" || "${CERTSDIR}" -nt "${CERTBUNDLE}" ]]; then echo "Recreating certificate bundle ${CERTBUNDLE}" TEMPBUNDLE=$(mktemp "${CERTBUNDLE}.XXXXXXXXXX") trap "rm -f '${CERTSDIR}/${TEMPBUNDLE}'" EXIT + # Use .0 instead of .pem to pull in only what c_rehash validated - cat "${CERTSDIR}"/*.0 > "${TEMPBUNDLE}" + cat "${CERTSDIR}"/*.[0-9] > "${TEMPBUNDLE}" + chmod 644 "${TEMPBUNDLE}" mv -f "${TEMPBUNDLE}" "${CERTBUNDLE}" trap - EXIT + + # Update the bundle's mtime so future runs know not to regenerate it + touch --reference="${CERTSDIR}" "${CERTBUNDLE}" fi diff --git a/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/update-ca-certificates.service b/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/update-ca-certificates.service index 63b05895d1..3de77d8864 100644 --- a/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/update-ca-certificates.service +++ b/sdk_container/src/third_party/coreos-overlay/app-misc/ca-certificates/files/update-ca-certificates.service @@ -1,12 +1,14 @@ [Unit] -Description=Update CA Certificates in /etc/ssl/certs +Description=Update CA bundle at /etc/ssl/certs/ca-certificates.crt # Since other services depend on the certificate store run this early DefaultDependencies=no -Wants=systemd-tmpfiles-setup.service -After=systemd-tmpfiles-setup.service +Wants=systemd-tmpfiles-setup.service clean-ca-certificates.service +After=systemd-tmpfiles-setup.service clean-ca-certificates.service Before=sysinit.target ConditionPathIsReadWrite=/etc/ssl/certs +# Do nothing if update-ca-certificates has never been run before +ConditionPathIsSymbolicLink=!/etc/ssl/certs/ca-certificates.crt [Service] Type=oneshot -ExecStart=/usr/sbin/update-ca-certificates +ExecStart=/usr/sbin/update-ca-certificates --skip-rehash