diff --git a/.gitignore b/.gitignore index e69de29..c48d8bb 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,9 @@ +/acme-tiny-5a7b4e7.tar.gz +/acme-tiny-af025f5.tar.gz +/acme-tiny-4.0.4.tar.gz +/*.src.rpm +/.build-* +/acme-tiny-4.1.0.tar.gz +/results_acme-tiny +/acme-tiny-4.1.1.tar.gz +/acme-tiny-5.0.1.tar.gz diff --git a/README-fedora.md b/README-fedora.md new file mode 100644 index 0000000..7a010fc --- /dev/null +++ b/README-fedora.md @@ -0,0 +1,152 @@ +# acme-tiny-core Fedora package + +This package contains only the upstream python script - for those +who prefer their own framework for cert maintenance. + +# acme-tiny Fedora package + +The Fedora package for acme-tiny adds a tiny framework to make issuing +and renewing [Let's Encrypt](https://letsencrypt.org/) certificates +convenient. It does *not* alter your configuration in any way, other +than to drop an acme.conf apache config snippet into `/etc/httpd/conf.d` +and provide a systemd service. + +If you want a package that tries to do everything for you as root, +consider the `certbot` package. + +The ACME protocol will work with other certificate authorities, but +acme-tiny is currently hardwired to use letencrypt.org - which is +also currently the only ACME certificate authority recognized in +most browsers. + +These instructions assume you are using letsencrypt for the first time +with this acme-tiny package. For example, you should not already have +an account key for the domains it will manage. If you do, see README.md +for instructions on converting it. Put any existing account key in +PEM format in `/var/lib/acme/private`, readable by the acme user (only!). + +## The web server must already serve your domains on HTTP + +If you cannot access your web domains locally with commands like +`curl` and `wget`, then this framework won't work. Acme-tiny will work with +any web server package, but if you are not using apache (httpd package), you +must provide the equivalent of `/etc/httpd/conf.d/acme.conf` to map +`/var/www/challenges` to the ACME URL location. The web server can even +be on a remote machine - provided you have somehow arranged for it to +serve files from `/var/www/challenges` (perhaps via NFS). + +If you are using Apache, and restrict access to ``, then this +will override the acme.conf global config snippet, and you must explicitly +make the ACME URL (http://your.domain.here/.well-known/acme-challenge/) +publicly accessible. + +## Put your CSRs in `/var/lib/acme/csr` + +You can use existing CSRs, or generate a new one using openssl. Put +all CSRs to be issued and renewed by acme-tiny in `/var/lib/acme/csr`. +I like to symlink the CSRs into /var/lib/acme/csr, just make sure the acme +user can read them (and follow the symlink). The details for openssl are +beyond the scope of this documentation, but this should work for creating a +certificate for a single domain: +``` +cd /etc/pki/tls +ln -s /var/lib/acme/csr . +openssl req -new -nodes -keyout private/your.domain.key \ + -out csr/your.domain.csr +chmod 0400 private/your.domain.key +``` +If you have an existing key, replace `-nodes -keyout` with `-key`. +The default openssl config will ask you for data, be sure to give the +domain you will be serving when it asks for "Common Name". It is possible +to cover multiple domains with a single certificate using openssl. First, add +a section to the end of `/etc/pki/tls/openssl.cnf` defining your extension: +``` +[MYSERV] +subjectAltName=DNS:your.domain,DNS:www.your.domain +``` +Then add `-reqexts MYSERV` to the openssl command line. One of the domains +must match the common name. + +Make sure the CSR can be read by the acme user. + +## Issue the certificate + +The timer service in acme-tiny will check the certificate for all CSRs in csr +every 24 hours, and issue or renew the certificate if it is missing or about to +expire (in 7 days by default). You don't have to wait for the timer, however. +Use +``` +systemctl start acme-tiny +``` +to run the service now. The certificate should appear in `/var/lib/acme/certs`, +and errors will be in journalctl. Alternatively, run +`/usr/libexec/acme-tiny/sign` as the acme user, and errors will go +to your terminal. + +## Use the certificate + +The default httpd config uses a self-signed localhost certificate for https. +Edit `/etc/httpd/conf.d/ssl.conf` and change `SSLCertificateFile` and +`SSLCertificateChainFile` to `/var/lib/acme/certs/your.domain.crt` (or use a +symlink to /etc/pki/tls/certs). Change `SSLCertificateKeyFile` to +`/etc/pki/tls/private/your.domain.key`. + +Obviously, you can change the locations to suit your sysadmin tastes. + +Some SSL apps, like dovecot, require SSL certificates to be tagged in selinux. +``` +semanage fcontext -a -f 'all files' -t cert_t '/var/lib/acme/certs(/.*)?' +restorecon -rv /var/lib/acme/certs +``` +The above will permanently change the selinux tag to work with dovecot +and other apps. + +Sendmail is a special problem - it insists that any certificates it loads be +only writable by root. This is at odds with the privilege separation of the +acme user. (Obviously, the private key must be accessible only by root.) You +can, of course, copy the crt file to `/etc/pki/tls/certs` as root and change +the mode. But this has to be done every time the cert is renewed. +The systemd `acme-tiny.service` runs `acme-tiny-notify.service` +afterward which executes as root. It calls +`/usr/libexec/acme-tiny/notify` for each nenewed cert. (This used +to be `/etc/acme-tiny/notify.sh` - which is now a symlink.) + +Suppose `/var/lib/acme/certs/mail.crt` is renewed, where `mail.crt` is the +certificate sendmail will use. The notify script +sees the reference to `/etc/pki/tls/certs/mail.crt` in `/etc/mail/*.cf`, and +copies the renewed cert to `/etc/pki/tls/certs`. Sendmail can then load it +from there and be happy. This also solves the file context problem. + +The notify script has built in support for the httpd, sendmail, and dovecot +packages for Fedora. To avoid restarting services multiple times, +the notify script records in `/var/lib/acme/.notify` +when it last restarted each service. + +By dropping scripts with names ending in `.sh` in `/etc/acme-tiny/notify.d`, +additional packages (e.g. nginx) can be supported. + +This new system should be compatible with older incrond configs, +but the additional `/etc/acme-tiny/notify.sh` calls from incrond are redundant. +Making them redundant, incidentally fixes +[BZ#1839904](https://bugzilla.redhat.com/show_bug.cgi?id=1839904). There +could still be a race condition missed in testing, so I would disable your old +acme incrontab. + +## Logging and Error Reporting + +Under systemd, errors and certs signed are logged with the acme-tiny +syslog identifier. + +## Virtual Hosts + +Most web servers can handle multiple logical web hosts - configuring that is +beyond the scope of this document. Each virtual host may need to have its own +certificate for SSL. They can all share the same key file (see above for +how to use an existing key for certificate requests), or use different keys. +Note that apache can load certs directly from `/var/lib/acme/certs`, and +so notify.sh simply does `apachectl graceful`. + +Put all the CSRs in `/var/lib/acme/csr` and the acme-tiny service will keep +them all renewed. This also works for certificates used by other SSL +applications, such as dovecot, sendmail, jabberd, or znc. + diff --git a/acme-tiny-notify.service b/acme-tiny-notify.service new file mode 100644 index 0000000..bcd93b7 --- /dev/null +++ b/acme-tiny-notify.service @@ -0,0 +1,8 @@ +[Unit] +Description=Notify services of updates to acme certs + +[Service] +Type=oneshot +Nice=19 +SyslogIdentifier=acme-tiny +ExecStart=/usr/libexec/acme-tiny/notify --scan diff --git a/acme-tiny-sign.sh b/acme-tiny-sign.sh new file mode 100755 index 0000000..9999005 --- /dev/null +++ b/acme-tiny-sign.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +if test "$(id -u)" -eq 0; then + echo "Do not run as root!" + exit 2 +fi + +. /etc/sysconfig/acme-tiny +DAYS="${1:-$DAYS}" +test -n "$DAYS" || DAYS="7" +if [[ "$DAYS" =~ ^[0-9]+$ ]]; then + echo "Days before expiration: $DAYS" + secs=$(( $DAYS * 24 * 60 * 60 )) +else + echo "Invalid number of days: $DAYS" + exit 1 +fi + +cd /var/lib/acme + +if ! test -s private/account.key; then + touch private/account.key + chmod 0600 private/account.key + openssl genrsa 4096 >private/account.key +fi + +rc="0" +for csr in csr/*.csr; do + test -s "$csr" || continue + test -r "$csr" || continue + crt="${csr%%.csr}" + tmp="certs/${crt##csr/}.tmp" + crt="certs/${crt##csr/}.crt" + if test -s "$crt" && openssl x509 -in "$crt" -noout -checkend "$secs"; then + continue + fi + if test -w "$crt" || test ! -e "$crt"; then + echo acme_tiny --account-key private/account.key --csr "$csr" \ + --acme-dir /var/www/challenges/ --out "$crt" + else + echo "Can't write to $crt" + rc="1" + continue + fi + + if /usr/sbin/acme_tiny --account-key private/account.key --csr "$csr" \ + --acme-dir /var/www/challenges/ > "$tmp"; then + mv "$tmp" "$crt" || exit 1 + else + test -e "$tmp" && test ! -s "$tmp" && rm "$tmp" + fi + # append intermediate certs + #cat *.pem >>"$crt" +done +exit "$rc" diff --git a/acme-tiny.conf b/acme-tiny.conf new file mode 100644 index 0000000..28e81fe --- /dev/null +++ b/acme-tiny.conf @@ -0,0 +1,4 @@ +# Default settings for acme-tiny wrapper script + +# Number of days before expiration to renew a certificate +DAYS=7 diff --git a/acme-tiny.service b/acme-tiny.service new file mode 100644 index 0000000..c00fc5d --- /dev/null +++ b/acme-tiny.service @@ -0,0 +1,17 @@ +[Unit] +Description=Check for acme certs about to expire +Wants=acme-tiny-notify.service +Before=acme-tiny-notify.service + +[Service] +Type=oneshot +Nice=19 +ProtectHome=true +ProtectSystem=true +User=acme +Group=acme +SyslogIdentifier=acme-tiny +ExecStart=/usr/libexec/acme-tiny/sign + +[Install] +Also=acme-tiny.timer diff --git a/acme-tiny.spec b/acme-tiny.spec new file mode 100644 index 0000000..c4e4387 --- /dev/null +++ b/acme-tiny.spec @@ -0,0 +1,296 @@ + +%if 0%{?fedora} || 0%{?rhel} > 7 +# Explicity require python3 on Fedora to help track which packages +# no longer need python2. +%global use_python3 1 +%else +%global use_python3 0 +%endif + +Name: acme-tiny +Version: 5.0.1 +Release: 13%{?dist} +Summary: Tiny auditable script to issue, renew Let's Encrypt certificates + +License: MIT +URL: https://github.com/diafygi/%{name} +Source0: https://github.com/diafygi/%{name}/archive/%{version}.tar.gz#/%{name}-%{version}.tar.gz +Source1: acme-tiny-sign.sh +Source2: cert-check.py +Source3: acme.conf +Source6: acme-tiny.timer +Source7: acme-tiny.service +Source8: README-fedora.md +# simple script hook to kick services when cert is updated +Source9: notify.sh +Source10: acme-tiny-notify.service +Source11: acme-tiny.conf + +Requires(pre): shadow-utils +BuildRequires: systemd-rpm-macros +%{?systemd_requires} +Requires: %{name}-core = %{version}-%{release} +BuildArch: noarch +%if 0%{?fedora} +Suggests: httpd, mod_ssl, nginx +Enhances: httpd, mod_ssl, nginx +%endif + +%description +This is a tiny, auditable script that you can throw on your server to issue and +renew Let's Encrypt certificates. Since it has to be run on your server and +have access to your private Let's Encrypt account key, I tried to make it as +tiny as possible (currently less than 200 lines). The only prerequisites are +python and openssl. + +Well, that and a web server - but then you only need this with a web server. +This package adds a simple directory layout and timer service that runs +acme_tiny on installed CSRs as the acme user for privilege separation. + +%package core +Summary: Core python module of acme-tiny +Requires: openssl +%if 0%{?rhel} >= 5 && 0%{?rhel} < 7 +# EL6 uses python2.6, which does not include argparse +Requires: python-argparse +%endif +BuildArch: noarch + +%description core +Includes only the core acme_tiny.py script and its dependencies. +Alternate frameworks that use acme_tiny.py can install this to avoid pulling in +unneeded packages. + +%prep +%setup -q -n %{name}-%{version} +cp -p %{SOURCE1} %{SOURCE2} %{SOURCE8} . +sed -i.orig -e '1,1 s,^.*python$,#!/usr/bin/python,' acme_tiny.py +%if %{use_python3} +sed -i.old -e '1,1 s/python$/python3/' *.py +%endif + +echo 'u acme - "Tiny Auditable ACME Client" %{_sharedstatedir}/acme' >acme.sysusers.conf + +%build + +%install +mkdir -p %{buildroot}/var/www/challenges +mkdir -p %{buildroot}%{_sysconfdir}/httpd/conf.d +mkdir -p %{buildroot}%{_sbindir} +mkdir -p %{buildroot}%{_libexecdir}/%{name} +mkdir -p %{buildroot}%{_sharedstatedir}/acme/{private,csr,certs,.notify} +mkdir -p %{buildroot}%{_sysconfdir}/%{name}/notify.d +mkdir -p %{buildroot}%{_sysconfdir}/sysconfig +chmod 0700 %{buildroot}%{_sharedstatedir}/acme/private + +install -m 0755 acme-tiny-sign.sh %{buildroot}%{_libexecdir}/%{name}/sign +install -m 0755 %{SOURCE9} %{buildroot}%{_libexecdir}/%{name}/notify +install -m 0755 acme_tiny.py %{buildroot}%{_sbindir}/acme_tiny +ln -sf acme_tiny %{buildroot}%{_sbindir}/%{name} +ln -sf %{_libexecdir}/%{name}/sign %{buildroot}%{_sbindir}/acme-tiny-sign +ln -sf %{_libexecdir}/%{name}/notify %{buildroot}%{_sysconfdir}/%{name}/notify.sh +install -m 0755 cert-check.py %{buildroot}%{_sbindir}/cert-check +install -m 0644 %{SOURCE3} %{buildroot}%{_sysconfdir}/httpd/conf.d +mkdir -p %{buildroot}%{_unitdir} +install -pm 644 %{SOURCE6} %{buildroot}%{_unitdir} +install -pm 644 %{SOURCE7} %{buildroot}%{_unitdir} +install -pm 644 %{SOURCE10} %{buildroot}%{_unitdir} +install -m 0644 %{SOURCE11} %{buildroot}%{_sysconfdir}/sysconfig/%{name} +install -m 0644 -D acme.sysusers.conf %{buildroot}%{_sysusersdir}/acme.conf + +%pre +getent group acme > /dev/null || groupadd -r acme +getent passwd acme > /dev/null || /usr/sbin/useradd -g acme \ + -c "Tiny Auditable ACME Client" \ + -r -d %{_sharedstatedir}/acme -s /sbin/nologin acme +exit 0 + +%post +%systemd_post acme-tiny.service acme-tiny-notice.service acme-tiny.timer + +%postun +%systemd_postun_with_restart acme-tiny.service acme-tiny-notice.service acme-tiny.timer + +%preun +%systemd_preun acme-tiny.service acme-tiny-notice.service acme-tiny.timer + +%files +%{!?_licensedir:%global license %%doc} +%license LICENSE +%doc README-fedora.md +%attr(0755,acme,acme) /var/www/challenges +%attr(-,acme,acme) %{_sharedstatedir}/acme +%{_libexecdir}/%{name} +%config(noreplace) %{_sysconfdir}/httpd/conf.d/acme.conf +%config(noreplace) %{_sysconfdir}/sysconfig/%{name} +%{_unitdir}/* +%{_sbindir}/acme-tiny-sign +%{_sbindir}/cert-check +%{_sbindir}/%{name} +%{_sysconfdir}/%{name} +%{_sysusersdir}/acme.conf + +%files core +%license LICENSE +%doc README.md +%{_sbindir}/acme_tiny + +%changelog +* Fri Jan 16 2026 Fedora Release Engineering - 5.0.1-13 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_44_Mass_Rebuild + +* Wed Jul 23 2025 Fedora Release Engineering - 5.0.1-12 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + +* Thu Jan 16 2025 Zbigniew Jędrzejewski-Szmek - 5.0.1-11 +- Add sysusers.d config file + +* Thu Jan 16 2025 Fedora Release Engineering - 5.0.1-10 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + +* Wed Jul 17 2024 Fedora Release Engineering - 5.0.1-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + +* Mon Jan 22 2024 Fedora Release Engineering - 5.0.1-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Fri Jan 19 2024 Fedora Release Engineering - 5.0.1-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Wed Jul 19 2023 Fedora Release Engineering - 5.0.1-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild + +* Tue Mar 28 2023 Stuart D. Gathman - 5.0.1-5 +- Verified SPDX license + +* Wed Jan 18 2023 Fedora Release Engineering - 5.0.1-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Wed Jul 20 2022 Fedora Release Engineering - 5.0.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Wed Jan 19 2022 Fedora Release Engineering - 5.0.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Thu Oct 28 2021 Stuart D. Gathman 5.0.1-1 +- New upstream release + +* Wed Sep 8 2021 Stuart D. Gathman 4.1.1-2 +- Remove CLI override in acme-tiny.service (uses /etc/sysconfig/acme-tiny now) + +* Tue Sep 7 2021 Stuart D. Gathman 4.1.1-1 +- New upstream release +- Set days before expiration in /etc/sysconfig + +* Wed Jul 21 2021 Fedora Release Engineering - 4.1.0-8 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Thu May 27 2021 Stuart D. Gathman 4.1.0-7 +- Fix BZ#1839904 +- enhance notify after cert update, incrond no longer needed + +* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 4.1.0-6 +- Rebuilt for updated systemd-rpm-macros + See https://pagure.io/fesco/issue/2583. + +* Mon Jan 25 2021 Fedora Release Engineering - 4.1.0-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Mon Jul 27 2020 Fedora Release Engineering - 4.1.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Thu Apr 9 2020 Stuart D. Gathman 4.1.0-3 +- Update README-fedora.md to describe notify.sh +- Apply selected changes from Marcel Metz : +- Use openssl x509 -checkend parameter to determine certificate expiration +- Remove Let's Encrypt intermediate certificate +- Remove cron job used on non systemd systems + +* Tue Jan 28 2020 Fedora Release Engineering - 4.1.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Fri Oct 11 2019 Tim Jackson - 4.1.0-1 +- Update to 4.1.0 + +* Fri Oct 11 2019 Stuart D. Gathman 4.0.4-5 +- Add generic notify script for incron + +* Wed Jul 24 2019 Fedora Release Engineering - 4.0.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Thu Jan 31 2019 Fedora Release Engineering - 4.0.4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Thu Jul 12 2018 Fedora Release Engineering - 4.0.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Tue May 22 2018 Stuart D. Gathman 4.0.4-1 +- Official upstream release! BZ#1560531 +- Move acme_tiny.py to acme-tiny-core subpackage BZ#1438181 + +* Wed Feb 07 2018 Fedora Release Engineering - 0.2-4.20170516gitaf025f5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Wed Nov 22 2017 Stuart D. Gathman 0.2-3.20170616gitaf025f5 +- BZ#1507333 EL6 missing python-argparse dependency +- BZ#1515781 Agreement updated. +- BZ#1409345 Unwritable certs silently skipped + +* Wed Jul 26 2017 Fedora Release Engineering - 0.2-2.20170516gitaf025f5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Thu Jul 6 2017 Stuart D. Gathman 0.2-1.20170616gitaf025f5 +- BZ#1468045 Update to new upstream version +- BZ#1409686 Message.getallmatchingheaders() is broken in python3. + +* Fri Feb 10 2017 Fedora Release Engineering - 0.1-12.20160810git5a7b4e7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Mon Dec 19 2016 Miro Hrončok - 0.1-11.20160810git5a7b4e7 +- Rebuild for Python 3.6 + +* Mon Aug 22 2016 Stuart D. Gathman 0.1-10.20160810git5a7b4e7 +- Fix cert writable check in sign script +- More tips in README-fedora.md + +* Mon Aug 22 2016 Stuart D. Gathman 0.1-9.20160810git5a7b4e7 +- Use %%{systemd_requires} +- Remove unneeded cronie, python dependencies +- Add acme-tiny.timer to systemd scriptlets +- Add README-fedora.md +- acme_tiny: Fix --chain patch for python2.6 (el6) +- acme_tiny: Suppress traceback on error + +* Sun Aug 21 2016 Stuart D. Gathman 0.1-8 +- Add use_systemd flag to use systemd timer and enable on Fedora and epel7 +- Enable use_python3 flag for Fedora (but not epel7). + +* Sat Aug 20 2016 Stuart D. Gathman 0.1-7 +- sign: Actually use the new --chain flag +- cron: Make days to expiration explicit +- spec: Set file modes with install +- acme.conf: mark as config + +* Fri Aug 19 2016 Stuart D. Gathman 0.1-6 +- Python3 fixes for cert-check +- acme-tiny: Update patch to leave default behavior unchanged +- make /var/lib/acme readable by all except private + +* Thu Aug 11 2016 Stuart D. Gathman 0.1-5 +- sign: Use tmp output to avoid wiping existing cert on error +- acme_tiny: get intermediate cert from acme protocol + +* Thu Aug 11 2016 Stuart D. Gathman 0.1-4 +- Fix path of acme_tiny and make days explicit in sign script +- Add crontab + +* Wed Aug 10 2016 Stuart D. Gathman 0.1-3 +- Add global acme httpd conf +- Append intermediate certs, add current lets-encrypt intermediate cert + +* Tue Aug 9 2016 Stuart D. Gathman 0.1-2 +- add private, csr, certs directories +- add sign script suitable for cron + +* Mon Aug 8 2016 Stuart D. Gathman 0.1-1 +- Initial RPM diff --git a/acme-tiny.timer b/acme-tiny.timer new file mode 100644 index 0000000..687c820 --- /dev/null +++ b/acme-tiny.timer @@ -0,0 +1,13 @@ +[Unit] +Description=check for acme certs about to expire and renew them +ConditionKernelCommandLine=!rd.live.image +After=network-online.target +After=httpd.service nginx.service + +[Timer] +OnBootSec=20min +OnUnitInactiveSec=24h +Unit=acme-tiny.service + +[Install] +WantedBy=timers.target diff --git a/acme.conf b/acme.conf new file mode 100644 index 0000000..3768c5c --- /dev/null +++ b/acme.conf @@ -0,0 +1,17 @@ +Alias /.well-known/acme-challenge/ "/var/www/challenges/" + +# Note, blocking access to in a will override +# these global permissions. You will need to modify those domains +# to allow access to /.well-known/, or just copy the from below. +# See: http://httpd.apache.org/docs/2.2/sections.html + + + Options -Indexes + Order allow,deny + Allow from all + + + Options -Indexes + Order allow,deny + Allow from all + diff --git a/cert-check.py b/cert-check.py new file mode 100644 index 0000000..89f545c --- /dev/null +++ b/cert-check.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +from __future__ import print_function +from sys import stderr + +import subprocess, time, calendar, os, getopt + +def usage(): + print("""Usage: cert-check [options] files ... + -h,--help this message + -q,--quiet do not print cert files needing (re)newing + -d n,--days=n days before expiration to renew (default 7) +Succeeds only if all certs exist and are more than from expiration.""", + file=stderr) + return 2 + +def main(argv): + days = 7 # days ahead to + quiet = False + + try: + opts,args = getopt.getopt(argv,'hqd:',['days=','quiet','help']) + except getopt.GetoptError as err: + # print help information and exit: + print(err,file=stderr) # prints something like "option -a not recognized" + return usage() + + for opt,val in opts: + if opt in ('-h','--help'): + return usage() + if opt in ('-q','--quiet'): + quiet = True + if opt in ('-d','--days'): + try: + days = int(val) + except: + return usage() + + now = time.time() + soon = now + days * 24 * 60 * 60 + rc = 0 + + for fn in args: + try: + size = os.path.getsize(fn) + except: + size = 0 + if size == 0: + if not quiet: print(fn) + rc += 1 + continue + proc = subprocess.Popen( + ["openssl", "x509", "-in", fn, "-noout", "-enddate"], + stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = proc.communicate() + if proc.returncode != 0: + raise IOError("{1}: OpenSSL Error: {0}".format(err,fn)) + t = time.strptime(out.decode(),'notAfter=%b %d %H:%M:%S %Y GMT\n') + t = calendar.timegm(t) + if soon > t: + if not quiet: print(fn) + rc += 1 + return rc > 0 + +if __name__ == '__main__': + import sys + sys.exit(main(sys.argv[1:])) diff --git a/notify.sh b/notify.sh new file mode 100755 index 0000000..f3ca76b --- /dev/null +++ b/notify.sh @@ -0,0 +1,58 @@ +#!/usr/bin/sh + +acmedir="/var/lib/acme" +#acmedir="test" +notify="${acmedir}/.notify" +verbose="n" +mkdir -p "$notify" + +scancerts() { + if test -e "${notify}/notify"; then + find "${acmedir}/certs" -name '*.crt' -newer "${notify}/notify" -print0 + else + find "${acmedir}/certs" -name '*.crt' -print0 + fi | xargs -0 /usr/libexec/acme-tiny/notify -v + touch "${notify}/notify" +} + +for cert in "$@"; do + case "$cert" in + -v|--verbose) verbose="y"; continue;; + -s|--scan) scancerts; continue;; + -*) echo "Invalid option $cert"; exit 2;; + esac + name="${cert##*/}" + script="/etc/acme-tiny/notify.d/${name%.crt}.sh" + + # kick apache if cert is mentioned + if test "$cert" -nt "${notify}/httpd"; then + if grep "$cert" /etc/httpd/conf.d/*.conf >/dev/null 2>&1; then + apachectl graceful && touch "${notify}/httpd" && \ + [ "$verbose" = "y" ] && echo "Httpd reloaded" + fi + fi + + # kick sendmail if cert is mentioned + if test "$cert" -nt "${notify}/sendmail"; then + if grep "/etc/pki/tls/certs/$name" /etc/mail/*.cf >/dev/null 2>&1; then + cp "$cert" /etc/pki/tls/certs && systemctl restart sendmail \ + && touch "${notify}/sendmail" && \ + [ "$verbose" = "y" ] && echo "Sendmail reloaded" + fi + fi + + # kick dovecot if cert is mentioned + if test "$cert" -nt "${notify}/dovecot"; then + if grep "/etc/pki/dovecot/certs/$name" /etc/dovecot/conf.d/10-ssl.conf >/dev/null 2>&1; then + cp "$cert" /etc/pki/dovecot/certs && systemctl restart dovecot \ + && touch "${notify}/dovecot" && \ + [ "$verbose" = "y" ] && echo "Dovecot reloaded" + fi + fi + + # run any dropin extension + if test -x "$script"; then + [ "$verbose" = "y" ] && echo "Running $script $cert" + ACMEDIR="$acmedir" NOTIFY="$notify" VERBOSE="$verbose" "$script" "$cert" + fi +done diff --git a/sources b/sources index e69de29..f4629f8 100644 --- a/sources +++ b/sources @@ -0,0 +1,2 @@ +SHA512 (acme-tiny-4.1.1.tar.gz) = 9e1aac03f3aa744061b8b03bb7bb6ede52ccf1a72d729775f106eb0fef786ee495dedd4f44c672e4ee2a8fc385477366bf164ab5e78d85e0a031558cde68f4b1 +SHA512 (acme-tiny-5.0.1.tar.gz) = 6e0619917b31a5795c2c7d8aa811b46231b81fc6b57227f611f7f4b9f73eb3de669676482563c33d935a4a0812498677bcbe974663a561af61abb441a880947e