From 19ef4a12d8de048f3e42e38d9bcdd8aa35fe448a2fcb624745f599ff41c74030 Mon Sep 17 00:00:00 2001 From: Marcus Rueckert Date: Tue, 19 Sep 2017 15:42:45 +0000 Subject: [PATCH 1/4] Accepting request 527349 from home:dmolkentin:branches:security:dehydrated - Swap statements in post: installing services requires tmp.d - (Weak) dependency on dehydrated-acmeresponder. - systemd update service: ConditionPathExists goes into [Unit] section - Use timer instead of cron for systemd-enabled distros OBS-URL: https://build.opensuse.org/request/show/527349 OBS-URL: https://build.opensuse.org/package/show/security:dehydrated/dehydrated?expand=0&rev=10 --- dehydrated-update.service.in | 12 +++++++++ dehydrated-update.timer | 10 ++++++++ dehydrated.changes | 20 +++++++++++++++ dehydrated.spec | 47 +++++++++++++++++++++++++++++------- 4 files changed, 80 insertions(+), 9 deletions(-) create mode 100644 dehydrated-update.service.in create mode 100644 dehydrated-update.timer diff --git a/dehydrated-update.service.in b/dehydrated-update.service.in new file mode 100644 index 0000000..783e256 --- /dev/null +++ b/dehydrated-update.service.in @@ -0,0 +1,12 @@ +[Unit] +Description=Certificate Update Runner for Dehydrated +ConditionPathExists=/etc/dehydrated/config +After=network-online.target +Wants=acmeresponder.socket + +[Service] +Type=oneshot +ExecStart=/usr/bin/dehydrated --cron + +User=@USER@ +Group=@USER@ diff --git a/dehydrated-update.timer b/dehydrated-update.timer new file mode 100644 index 0000000..7b03f4a --- /dev/null +++ b/dehydrated-update.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Run Certificate Update Runner for Dehydrated + +[Timer] +OnCalendar=daily +# Two hour window +RandomizedDelaySec=7200 + +[Install] +WantedBy=timers.target diff --git a/dehydrated.changes b/dehydrated.changes index ee3ee9a..e11bbd9 100644 --- a/dehydrated.changes +++ b/dehydrated.changes @@ -1,3 +1,23 @@ +------------------------------------------------------------------- +Tue Sep 19 15:40:46 UTC 2017 - daniel.molkentin@suse.com + +- Swap statements in post: installing services requires tmp.d + +------------------------------------------------------------------- +Tue Sep 19 14:52:25 UTC 2017 - daniel.molkentin@suse.com + +- (Weak) dependency on dehydrated-acmeresponder. + +------------------------------------------------------------------- +Thu Sep 14 13:47:06 UTC 2017 - daniel.molkentin@suse.com + +- systemd update service: ConditionPathExists goes into [Unit] section + +------------------------------------------------------------------- +Wed Sep 13 15:27:08 UTC 2017 - daniel.molkentin@suse.com + +- Use timer instead of cron for systemd-enabled distros + ------------------------------------------------------------------- Tue Feb 21 13:12:19 UTC 2017 - daniel.molkentin@suse.com diff --git a/dehydrated.spec b/dehydrated.spec index a1ea27c..930fa32 100644 --- a/dehydrated.spec +++ b/dehydrated.spec @@ -58,6 +58,8 @@ Source2: acme-challenge.conf.nginx.in Source3: acme-challenge.conf.lighttpd.in Source4: dehydrated.cron.in Source5: dehydrated.tmpfiles.d +Source6: dehydrated-update.service.in +Source7: dehydrated-update.timer BuildRequires: %{_apache} %if %{with lighttpd} BuildRequires: lighttpd @@ -72,9 +74,6 @@ BuildRequires: generic-logos-httpd Requires: coreutils Requires: curl Requires: openssl -%if 0%{?suse_version} -Requires: cron -%endif Requires(pre): /usr/sbin/useradd Requires(pre): /usr/sbin/groupadd Requires(pre): /usr/bin/getent @@ -85,6 +84,15 @@ BuildRequires: shadow %if %{with systemd} BuildRequires: pkgconfig(systemd) %{?systemd_requires} +%else #with_systemd +%if 0%{?suse_version} +Requires: cron +%endif +%endif #with_systemd +%if 0%{?suse_version} +Recommends: dehydrated-acmeresponder +%else +Requires: dehydrated-acmeresponder %endif BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch @@ -156,8 +164,17 @@ if [ -d /etc/letsencrypt.sh ]; then mv /etc/letsencrypt.sh /etc/dehydrated; chow if [ -e /etc/dehydrated/config.sh ]; then mv /etc/dehydrated/config.sh /etc/dehydrated/config; fi %if %{with systemd} +%service_add_pre dehydrated-update.service dehydrated-update.timer + %post systemd-tmpfiles --create %{_tmpfilesdir}/%{name}.conf ||: +%service_add_post dehydrated-update.service dehydrated-update.timer + +%preun +%service_del_preun dehydrated-update.service dehydrated-update.timer + +%postun +%service_del_postun dehydrated-update.service dehydrated-update.timer %endif %prep @@ -168,6 +185,7 @@ systemd-tmpfiles --create %{_tmpfilesdir}/%{name}.conf ||: %install # sensitive keys mkdir -p %{buildroot}%{_home}/{accounts,certs} +mkdir -p %{buildroot}%{_sbindir} sed -i "s,#WELLKNOWN=.*,WELLKNOWN=%{_challengedir},g" docs/examples/config install -m 0644 docs/examples/* %{buildroot}%{_home} @@ -191,14 +209,22 @@ sed "s,@CHALLENGEDIR@,%{_challengedir},g" %{SOURCE3} > acme-challenge install -m 0644 acme-challenge %{buildroot}/etc/lighttpd/conf.d %endif #with lighttpd +%if %{with systemd} +install -D -m 0644 %{S:5} %{buildroot}%{_tmpfilesdir}/%{name}.conf +sed "s,@USER@,%{_user},g" %{S:6} > dehydrated-update.service +# Use timer +install -D -m 644 dehydrated-update.service %{buildroot}%{_unitdir}/dehydrated-update.service +install -D -m 644 %{S:7} %{buildroot}%{_unitdir}/dehydrated-update.timer +%if 0%{?suse_version} +ln -s /usr/sbin/service %{buildroot}%{_sbindir}/rcdehydrated-update +%endif +%else #with systemd +install -D -d -m 0750 %{buildroot}%{_lock_dir} +# Use cron install -m 0755 -d %{buildroot}/etc/cron.d sed "s,@USER@,%{_user},g" %{SOURCE4} > dehydrated.cron install -m 0644 dehydrated.cron %{buildroot}/etc/cron.d/dehydrated -%if %{with systemd} -install -D -m 0644 %{S:5} %{buildroot}%{_tmpfilesdir}/%{name}.conf -%else -install -D -d -m 0750 %{buildroot}%{_lock_dir} -%endif +%endif #with systemd perl -p -i -e 's|#LOCKFILE="\${BASEDIR}/lock"|LOCKFILE="%{_lock_dir}/lock"|' %{buildroot}%{_home}/config diff -urN docs/examples/config %{buildroot}%{_home}/config ||: @@ -210,14 +236,17 @@ diff -urN docs/examples/config %{buildroot}%{_home}/config ||: %config(noreplace) %attr(640,root,%{_user}) %{_sysconfdir}/dehydrated/config %config(noreplace) %attr(640,root,%{_user}) %{_sysconfdir}/dehydrated/domains.txt %config(noreplace) %attr(750,root,%{_user}) %{_sysconfdir}/dehydrated/hook.sh -%config %{_sysconfdir}/cron.d/dehydrated %{_bindir}/dehydrated %attr(-,%{_user},root) %dir %{_localstatedir}/lib/acme-challenge %doc LICENSE README.md docs/*.md docs/*.jpg %if %{with systemd} %{_tmpfilesdir}/%{name}.conf +%{_unitdir}/dehydrated-update.service +%{_unitdir}/dehydrated-update.timer +%{_sbindir}/rcdehydrated-update %ghost %attr(700,%{_user},%{_user}) %dir %{_lock_dir} %else +%config %{_sysconfdir}/cron.d/dehydrated %attr(700,%{_user},%{_user}) %dir %{_lock_dir} %endif From fc9dddc9f910e28bab539b89ae2b9be2ea2b90b8b1d566be3977dcc69733c263 Mon Sep 17 00:00:00 2001 From: Marcus Rueckert Date: Fri, 22 Sep 2017 13:35:31 +0000 Subject: [PATCH 2/4] Accepting request 528299 from home:dmolkentin:branches:security:dehydrated - Add man page - Ensure dehydrated is always run as designated user * adds 0001-Add-optional-user-and-group-configuration.patch - Introduce config.d directory for user configuration - Avoid warning about empty config.d directory * adds 0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch - Fix sed warning about unescaped curly braces in regex - Use timer instead of cron for systemd-enabled distros Note: Timer must be explicitly enabled! OBS-URL: https://build.opensuse.org/request/show/528299 OBS-URL: https://build.opensuse.org/package/show/security:dehydrated/dehydrated?expand=0&rev=11 --- ...ptional-user-and-group-configuration.patch | 66 ++++++++ ...able-warning-on-empty-CONFIG_D-direc.patch | 49 ++++++ dehydrated.1 | 155 ++++++++++++++++++ dehydrated.changes | 19 ++- dehydrated.spec | 23 ++- 5 files changed, 310 insertions(+), 2 deletions(-) create mode 100644 0001-Add-optional-user-and-group-configuration.patch create mode 100644 0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch create mode 100644 dehydrated.1 diff --git a/0001-Add-optional-user-and-group-configuration.patch b/0001-Add-optional-user-and-group-configuration.patch new file mode 100644 index 0000000..fb931b7 --- /dev/null +++ b/0001-Add-optional-user-and-group-configuration.patch @@ -0,0 +1,66 @@ +From 700040068e3c08025f206e06ba5cfa76a124d805 Mon Sep 17 00:00:00 2001 +From: Daniel Molkentin +Date: Thu, 21 Sep 2017 19:07:54 +0200 +Subject: [PATCH] Add optional user and group configuration + +when DEHYDRATED_USER is set, dehydrated will refuse to run as root, +and instead launch itself as the user in DEHYDRATED_USER (and +DEHYDRATED_GROUP if set). +--- + dehydrated | 15 +++++++++++++++ + docs/examples/config | 6 ++++++ + 2 files changed, 21 insertions(+) + +diff --git a/dehydrated b/dehydrated +index 8b31ee1..39c717f 100755 +--- a/dehydrated ++++ b/dehydrated +@@ -126,6 +126,8 @@ load_config() { + LOCKFILE= + OCSP_MUST_STAPLE="no" + IP_VERSION= ++ DEHYDRATED_USER= ++ DEHYDRATED_GROUP= + + if [[ -z "${CONFIG:-}" ]]; then + echo "#" >&2 +@@ -159,6 +161,19 @@ load_config() { + done + fi + ++ # Check if we are running & are allowed to run as root ++ if [[ ! -z "$DEHYDRATED_USER" && $EUID == 0 ]]; then ++ if [ ! -z "$DEHYDRATED_GROUP" ]; then ++ group="-g $DEHYDRATED_GROUP" ++ fi ++ echo "# INFO: Running $0 as $DEHYDRATED_USER" ++ su -c "$0" $group "$DEHYDRATED_USER" ++ exit ++ fi ++ ++ # Check for missing dependencies ++ check_dependencies ++ + # Remove slash from end of BASEDIR. Mostly for cleaner outputs, doesn't change functionality. + BASEDIR="${BASEDIR%%/}" + +diff --git a/docs/examples/config b/docs/examples/config +index 1b1b3d8..9a890f4 100644 +--- a/docs/examples/config ++++ b/docs/examples/config +@@ -10,6 +10,12 @@ + # Default values of this config are in comments # + ######################################################## + ++# Which user should dehydrated run as? This will be implictly enforced when running as root ++#DEHYDRATED_USER= ++ ++# Which group should dehydrated run as? This will be implictly enforced when running as root ++#DEHYDRATED_GROUP= ++ + # Resolve names to addresses of IP version only. (curl) + # supported values: 4, 6 + # default: +-- +2.12.3 + diff --git a/0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch b/0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch new file mode 100644 index 0000000..47cc609 --- /dev/null +++ b/0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch @@ -0,0 +1,49 @@ +From 5214632c55c70c6c1f0dabce204a9fb8529c8ca8 Mon Sep 17 00:00:00 2001 +From: Lukas Schauer +Date: Thu, 21 Sep 2017 18:10:01 +0200 +Subject: [PATCH] use nullglob, disable warning on empty CONFIG_D directory + +--- + dehydrated | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/dehydrated b/dehydrated +index 8b31ee1..a62b858 100755 +--- a/dehydrated ++++ b/dehydrated +@@ -8,7 +8,9 @@ + set -e + set -u + set -o pipefail +-[[ -n "${ZSH_VERSION:-}" ]] && set -o SH_WORD_SPLIT && set +o FUNCTION_ARGZERO ++[[ -n "${ZSH_VERSION:-}" ]] && set -o SH_WORD_SPLIT && set +o FUNCTION_ARGZERO && set -o NULL_GLOB ++[[ -z "${ZSH_VERSION:-}" ]] && shopt -s nullglob ++ + umask 077 # paranoid umask, we're creating private keys + + # Find directory in which this script is stored by traversing all symbolic links +@@ -146,10 +148,7 @@ load_config() { + fi + + for check_config_d in "${CONFIG_D}"/*.sh; do +- if [[ ! -e "${check_config_d}" ]]; then +- echo "# !! WARNING !! Extra configuration directory ${CONFIG_D} exists, but no configuration found in it." >&2 +- break +- elif [[ -f "${check_config_d}" ]] && [[ -r "${check_config_d}" ]]; then ++ if [[ -f "${check_config_d}" ]] && [[ -r "${check_config_d}" ]]; then + echo "# INFO: Using additional config file ${check_config_d}" + # shellcheck disable=SC1090 + . "${check_config_d}" +@@ -1020,9 +1019,6 @@ command_cleanup() { + + # Loop over all files of this type + for file in "${certdir}/${filebase}-"*".${fileext}"; do +- # Handle case where no files match the wildcard +- [[ -f "${file}" ]] || break +- + # Check if current file is in use, if unused move to archive directory + filename="$(basename "${file}")" + if [[ ! "${filename}" = "${current}" ]]; then +-- +2.12.3 + diff --git a/dehydrated.1 b/dehydrated.1 new file mode 100644 index 0000000..49230ef --- /dev/null +++ b/dehydrated.1 @@ -0,0 +1,155 @@ +.TH DEHYDRATED 1 2017-09-20 "Dehydrated ACME Client" +.SH NAME +dehydrated \- ACME client implemented as a shell-script +.SH SYNOPSIS +.B dehydrated +[\fBcommand\fR [\fBargument\fR]] +[\fBargument\fR [\fBargument\fR]] +.IR ... +.SH DESCRIPTION +A client for ACME-based Certificate Authorities, such as LetsEncrypt. It +allows to request and obtain TLS certificates from an ACME-based +certificate authority. + +Before any certificates can be requested, Dehydrated needs +to acquire an account with the Certificate Authorities. Optionally, an email +address can be provided. It will be used to e.g. notify about expiring +certificates. You will usually need to accept the Terms of Service of the CA. +Dehydrated will notify if no account is configured. Run with \fB--register +--accept-terms\fR to create a new account. + +Next, all domain names must be provided in domains.txt. The format is line +based: If the file contains two lines "example.com" and "example.net", +Dehydrated will request two certificate, one for "example.com" and the other +for "example.net". A single line while "example.com example.net" will request a +single certificate valid for both "example.net" and "example.com" through the \fISubject +Alternative Name\fR (SAN) field. + +For the next step, one way of verifying domain name ownership needs to be +configured. Dehydrated implements \fIhttp-01\fR and \fIdns-01\fR verification. + +The \fIhttp-01\fR verification provides proof of ownership by providing a +challenge token. In order to do that, the directory referenced in the +\fIWELLKNOWN\fR config variable needs to be exposed at +\fIhttp://{domain}/.well-known/acme-challenge/\fR, where {domain} is every +domain name specified in \fIdomains.txt\fR. Dehydrated does not provide its +own challenge responder, but relies on an existing web server to provide the +challenge response. See \fIwellknown.md\fR for configuration examples of +popular web servers. + +The \fIdns-01\fR verification works by providing a challenge token through DNS. +This is especially interesting for hosts that cannot be exposed to the public +Internet. Because adding records to DNS zones is oftentimes highly specific to +the software or the DNS provider at hand, there are many third party hooks +available for dehydrated. See \fIdns-verification.md\fR for hooks for popular +DNS servers and DNS hosters. + +Finally, the certificates need to be requested and updated on a regular basis. +This can happen through a cron job or a timer. Initially, you may enforce this +by invoking \fIdehydrated -c\fR manually. + +After a successful run, certificates are stored in +\fI/etc/dehydrated/certs/{domain}\fR, where {domain} is the domain name in the +first column of \fIdomains.txt\fR. + +.SH OPTIONS + +.BR Commands +.TP +.BR \-\-version ", " \-v +Print version information +.TP +.BR \-\-register +Register account key +.TP +.BR \-\-account +Update account contact information +.TP +.BR \-\-cron ", " \-c +Sign/renew non\-existent/changed/expiring certificates. +.TP +.BR \-\-signcsr ", " \-s " " \fIpath/to/csr.pem\fR +Sign a given CSR, output CRT on stdout (advanced usage) +.TP +.BR \-\-revoke ", " \-r " " \fIpath/to/cert.pem\fR +Revoke specified certificate +.TP +.BR \-\-cleanup ", " \-gc +Move unused certificate files to archive directory +.TP +.BR \-\-help ", " \-h +Show help text +.TP +.BR \-\-env ", " \-e +Output configuration variables for use in other scripts + +.PP +.BR Parameters +.TP +.BR \-\-accept\-terms +Accept CAs terms of service +.TP +.BR \-\-full\-chain ", " \-fc +Print full chain when using \fB\-\-signcsr\fR +.TP +.BR \-\-ipv4 ", " \-4 +Resolve names to IPv4 addresses only +.TP +.BR \-\-ipv6 ", " \-6 +Resolve names to IPv6 addresses only +.TP +.BR \-\-domain ", " \-d " " \fIdomain.tld\fR +Use specified domain name(s) instead of domains.txt entry (one certificate!) +.TP +.BR \-\-keep\-going ", " \-g +Keep going after encountering an error while creating/renewing multiple +certificates in cron mode +.TP +.BR \-\-force ", " \-x +Force renew of certificate even if it is longer valid than value in RENEW_DAYS +.TP +.BR \-\-no\-lock ", " \-n +Don't use lockfile (potentially dangerous!) +.TP +.BR \-\-lock\-suffix " " \fIexample.com\fR +Suffix lockfile name with a string (useful for use with \-d) +.TP +.BR \-\-ocsp +Sets option in CSR indicating OCSP stapling to be mandatory +.TP +.BR \-\-privkey ", " \-p " " \fIpath/to/key.pem\fR +Use specified private key instead of account key (useful for revocation) +.TP +.BR \-\-config ", " \-f " " \fIpath/to/config\fR +Use specified config file +.TP +.BR \-\-hook ", " \-k " " \fIpath/to/hook.sh\fR +Use specified script for hooks +.TP +.BR \-\-out ", " \-o " " \fIcerts/directory\fR +Output certificates into the specified directory +.TP +.BR \-\-challenge ", " \-t " " \fI[http\-01|dns\-01]\fR +Which challenge should be used? Currently http\-01 and dns\-01 are supported +.TP +.BR \-\-algo ", " \-a " " \fI[rsa|prime256v1|secp384r1]\fR +Which public key algorithm should be used? Supported: rsa, prime256v1 and +secp384r1 +.SH DIAGNOSTICS +The program exits 0 if everything was fine, 1 if an error occurred. +.SH BUGS +Please report any bugs that you may encounter at the project web site +.UR https://github.com/lukas2511/dehydrated/issues +.UE . +.SH AUTHOR +Dehydrated was written by Lukas Schauer. This man page was contributed by +Daniel Molkentin. +.SH COPYRIGHT +Copyright 20015-2017 by Lukas Schauer and the respective contributors. +Provided under the MIT License. See the LICENSE file that accompanies the +distribution for licensing information. +.SH SEE ALSO +Full documentation along with configuration examples are provided in the \fIdocs\fR +directory of the distribution, or at +.UR https://github.com/lukas2511/dehydrated/tree/master/docs +.UE . diff --git a/dehydrated.changes b/dehydrated.changes index e11bbd9..2587d19 100644 --- a/dehydrated.changes +++ b/dehydrated.changes @@ -1,3 +1,18 @@ +------------------------------------------------------------------- +Fri Sep 22 11:18:55 UTC 2017 - daniel.molkentin@suse.com + +- Add man page + +- Ensure dehydrated is always run as designated user + * adds 0001-Add-optional-user-and-group-configuration.patch + +- Introduce config.d directory for user configuration + +- Avoid warning about empty config.d directory + * adds 0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch + +- Fix sed warning about unescaped curly braces in regex + ------------------------------------------------------------------- Tue Sep 19 15:40:46 UTC 2017 - daniel.molkentin@suse.com @@ -16,7 +31,9 @@ Thu Sep 14 13:47:06 UTC 2017 - daniel.molkentin@suse.com ------------------------------------------------------------------- Wed Sep 13 15:27:08 UTC 2017 - daniel.molkentin@suse.com -- Use timer instead of cron for systemd-enabled distros +- Use timer instead of cron for systemd-enabled distros + + Note: Timer must be explicitly enabled! ------------------------------------------------------------------- Tue Feb 21 13:12:19 UTC 2017 - daniel.molkentin@suse.com diff --git a/dehydrated.spec b/dehydrated.spec index 930fa32..216d48e 100644 --- a/dehydrated.spec +++ b/dehydrated.spec @@ -60,6 +60,11 @@ Source4: dehydrated.cron.in Source5: dehydrated.tmpfiles.d Source6: dehydrated-update.service.in Source7: dehydrated-update.timer +Source8: dehydrated.1 +# Patch submitted to upstream +Patch1: 0001-Add-optional-user-and-group-configuration.patch +# Patch from upstream +Patch2: 0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch BuildRequires: %{_apache} %if %{with lighttpd} BuildRequires: lighttpd @@ -179,6 +184,8 @@ systemd-tmpfiles --create %{_tmpfilesdir}/%{name}.conf ||: %prep %setup -q +%patch1 -p1 +%patch2 -p1 %build @@ -186,6 +193,11 @@ systemd-tmpfiles --create %{_tmpfilesdir}/%{name}.conf ||: # sensitive keys mkdir -p %{buildroot}%{_home}/{accounts,certs} mkdir -p %{buildroot}%{_sbindir} +mkdir -p %{buildroot}%{_mandir}/man1 +mkdir -p %{buildroot}%{_home}/config.d +mkdir -p %{buildroot}%{_home}/hooks # used by hook packages + +cat %{SOURCE8} | gzip > %{buildroot}%{_mandir}/man1/dehydrated.1.gz sed -i "s,#WELLKNOWN=.*,WELLKNOWN=%{_challengedir},g" docs/examples/config install -m 0644 docs/examples/* %{buildroot}%{_home} @@ -225,7 +237,13 @@ install -m 0755 -d %{buildroot}/etc/cron.d sed "s,@USER@,%{_user},g" %{SOURCE4} > dehydrated.cron install -m 0644 dehydrated.cron %{buildroot}/etc/cron.d/dehydrated %endif #with systemd -perl -p -i -e 's|#LOCKFILE="\${BASEDIR}/lock"|LOCKFILE="%{_lock_dir}/lock"|' %{buildroot}%{_home}/config + +# Adjust config file +perl -p -i -e 's|#LOCKFILE="\$\{BASEDIR\}/lock"|LOCKFILE="%{_lock_dir}/lock"|' %{buildroot}%{_home}/config +perl -p -i -e 's|#CONFIG_D=|CONFIG_D="%{_home}/config.d"|' %{buildroot}%{_home}/config +perl -p -i -e 's|#DEHYDRATED_USER=|DEHYDRATED_USER="%{_user}"|' %{buildroot}%{_home}/config +perl -p -i -e 's|#DEHYDRATED_GROUP=|DEHYDRATED_GROUP="%{_user}"|' %{buildroot}%{_home}/config + diff -urN docs/examples/config %{buildroot}%{_home}/config ||: %files @@ -234,10 +252,13 @@ diff -urN docs/examples/config %{buildroot}%{_home}/config ||: %attr(700,%{_user},%{_user}) %dir %{_sysconfdir}/dehydrated/accounts %attr(700,%{_user},%{_user}) %dir %{_sysconfdir}/dehydrated/certs %config(noreplace) %attr(640,root,%{_user}) %{_sysconfdir}/dehydrated/config +%config(noreplace) %attr(750,root,%{_user}) %{_sysconfdir}/dehydrated/config.d %config(noreplace) %attr(640,root,%{_user}) %{_sysconfdir}/dehydrated/domains.txt %config(noreplace) %attr(750,root,%{_user}) %{_sysconfdir}/dehydrated/hook.sh +%config(noreplace) %attr(750,root,%{_user}) %{_sysconfdir}/dehydrated/hooks %{_bindir}/dehydrated %attr(-,%{_user},root) %dir %{_localstatedir}/lib/acme-challenge +%{_mandir}/man1/* %doc LICENSE README.md docs/*.md docs/*.jpg %if %{with systemd} %{_tmpfilesdir}/%{name}.conf From 3a1b390a5ccbaa14adcf815f39b0f5e9b6db02a32d8cbc280efc1d58b380c41a Mon Sep 17 00:00:00 2001 From: Marcus Rueckert Date: Wed, 27 Sep 2017 16:31:31 +0000 Subject: [PATCH 3/4] Accepting request 528993 from home:dmolkentin:branches:security:dehydrated - No longer require nginx or lighttpd for SLE - Never go as far as to require acmeresponder, it might not be available - Drop -update from dehydrated-update.{timer,socket} for consistency - Add distro specific README.SUSE / README.Fedora - Ran spec-cleaner OBS-URL: https://build.opensuse.org/request/show/528993 OBS-URL: https://build.opensuse.org/package/show/security:dehydrated/dehydrated?expand=0&rev=12 --- README.Fedora | 6 + README.SUSE | 140 ++++++++++++++++ dehydrated.changes | 13 ++ ...update.service.in => dehydrated.service.in | 0 dehydrated.spec | 154 +++++++++--------- dehydrated-update.timer => dehydrated.timer | 0 6 files changed, 240 insertions(+), 73 deletions(-) create mode 100644 README.Fedora create mode 100644 README.SUSE rename dehydrated-update.service.in => dehydrated.service.in (100%) rename dehydrated-update.timer => dehydrated.timer (100%) diff --git a/README.Fedora b/README.Fedora new file mode 100644 index 0000000..0d0cc62 --- /dev/null +++ b/README.Fedora @@ -0,0 +1,6 @@ +Packaging note +============== + +On Fedora, CentOS and RHEL, the dehydrated-apache2 package is +called dehydrated-httpd in accordance with the Fedora naming scheme. + diff --git a/README.SUSE b/README.SUSE new file mode 100644 index 0000000..1097b77 --- /dev/null +++ b/README.SUSE @@ -0,0 +1,140 @@ +========================================== +Acquiring TLS Certificates with Dehydrated +========================================== + +The SUSE dehydrated package has been designed to make acquiring TLS +certificates (aka SSL Certificates) as simple as possible, while still being +useful in a broad amount of use cases. Please consult the dehydrated man page, +then continue reading here. + +Aqcuisition through HTTP (http-01) +=================================== + +This is the primary method of acquiring certifictes. + +Setting up the acme-challenge auto-responder +-------------------------------------------- + +Apache +~~~~~~ + +If you are using Apache, just install dehydrated-apache2 and reload Apache. +This will take care of setting up the acme-challenge auto-responder. + +nginx +~~~~~ + +(not part of SLE, use openSUSE backports) + +For nginx, you will need to install dehydrated-nginx. Unfortunately, nginx does +not support directory mappings across vhosts, so in addition you will need to +include "/etc/nginx/acmechallenge" in all vhost configurations like this: + +server { + listen 80; + listen [::]:80; + server_name ; + include "acmechallenge"; + location / { + return 301 https://$host$request_uri; + } +} + +lighttpd +~~~~~~~~ + +(not part of SLE, use openSUSE backports) + +Lighttpd users can simply install dehydrated-lighttpd and reload lighttpd to +set up the acme-challenge auto-responder + +NOTE: Never set up the SSL vhosts until you have initially acquired the first +host. Specifying an SSL vhost without certificates constitutes an error for web +servers. + +Machines without a webserver +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On machines that are not running any web server, e.g. mail relays, you can run +apache2 with dehydrated-apache2. If you do not want to run any web server on a +system with systemd, you can use dehydrated-acmeresponder, a small socket +activated server. Once installed, it will automatically listen on port 80 +whenever the dehydrated cron job seeks renewal, assuming no other server is +currently occupying the port. It will also shut down once the timer has +finished execution. + +Acquisition of initial certificate +---------------------------------- + +How set up an account as described in the man page (as root): + +# dehydrated --register --accept-terms + +(the current version of the LetsEncrypt Terms & Conditions are referenced in +/etc/dehydrated/config) + +Next, fill in domains.txt and acquire the initial certificates (again, as root): + +# echo "myhost.example.com myalias.example.com" >> domains.txt +# dehydrated --cron + +adds myhost.example.com to the list of host names we want to request a certificate for. +The certificate will hold a Subject Alternative Name of "myalias.example.com". +LetsEncrypt will check both host names. + +NOTE: As of 2017, LetsEncrypt certificates are only valid for three months, and +the validity period may be further reduced in the future. It is therefore +vital to ensure that the certificates are being automatically renewed. On +systems without systemd, a cron job is automatically set up to take care of +this. On systemd-enabled systems, a timer is provided which needs to be +activated manually: + +# systemctl enable dehydrated.timer + +Aqcuisition through DNS (dns-01) +================================ + +Tnis is mostly useful under these conditions + +1. Your hosts are not directly exposed to the internet +2. Your host names are part of a public DNS zone visible on the internet. +3. You are comfortable with the service adding and removing records in your domain. + +Usually, the scenario you want this is a central host which picks up +certificates for all other hosts on a network, and then deploys them to the +actual target host, using plain scp or configuration management tools like +Ansible or Salt. For details, please refer to dns-verification.md. For +openSUSE, the python-dns-lexicon package provides hooks into many DNS providers +and DNS servers. + +Proceeding After initial certificate Aquisition +=============================================== + +Setting up the SSL host +----------------------- + +As recommended parameters shift, please refer to Mozillas excellent SSL +Configuration Generator [1] for details on how to configure your web server. +Replace the example paths with the following: + +Key: /etc/dehydrated/certs//privkey.pem +Certificate: /etc/dehydrated/certs//cert.pem +Intermediate Chain: /etc/dehydrated/certs//chain.pem +Certificate + Intermediate: /etc/dehydrated/certs//fullchain.pem + +where should be the name of the first column in domains.txt + +Limitations & Ceveats +===================== + +* It is currently not possible to aqcuire Wildcard certificates +* No EV- or OV-validated certificates +* Certificates expire within weeks, not years, this is by design. Ensure that + certificate renewal works and that daemons get reloaded frequently to pick + up certificate updates (This is currently not automated on the dehydrated end, + however Apache will reload every night due to log rotation). + +Links +===== + +[1] https://mozilla.github.io/server-side-tls/ssl-config-generator/ diff --git a/dehydrated.changes b/dehydrated.changes index 2587d19..eb18e42 100644 --- a/dehydrated.changes +++ b/dehydrated.changes @@ -1,3 +1,16 @@ +------------------------------------------------------------------- +Wed Sep 27 10:09:16 UTC 2017 - daniel.molkentin@suse.com + +- No longer require nginx or lighttpd for SLE + +- Never go as far as to require acmeresponder, it might not be available + +- Drop -update from dehydrated-update.{timer,socket} for consistency + +- Add distro specific README.SUSE / README.Fedora + +- Ran spec-cleaner + ------------------------------------------------------------------- Fri Sep 22 11:18:55 UTC 2017 - daniel.molkentin@suse.com diff --git a/dehydrated-update.service.in b/dehydrated.service.in similarity index 100% rename from dehydrated-update.service.in rename to dehydrated.service.in diff --git a/dehydrated.spec b/dehydrated.spec index 216d48e..7c94fef 100644 --- a/dehydrated.spec +++ b/dehydrated.spec @@ -16,6 +16,26 @@ # +%define _challengedir %{_localstatedir}/lib/acme-challenge +%define _user dehydrated +%define _home %{_sysconfdir}/dehydrated + +%if 0%{?suse_version} > 1230 +%define _lock_dir /run/dehydrated +%bcond_without systemd +%else +%define _lock_dir %{_localstatedir}/run/dehydrated +%bcond_with systemd +%endif + +%if %{defined is_opensuse} || %{defined fedora} +%bcond_without nginx +%bcond_without lighttpd +%else +%bcond_with nginx +%bcond_with lighttpd +%endif +%{!?_tmpfilesdir: %global _tmpfilesdir %{_prefix}/lib/tmpfiles.d } # See also http://en.opensuse.org/openSUSE:Specfile_guidelines %if 0%{?suse_version} @@ -23,27 +43,6 @@ %else %define _apache httpd %endif -%define _challengedir /var/lib/acme-challenge -%define _user dehydrated -%define _home /etc/dehydrated - -%if 0%{?suse_version} > 1230 -%bcond_without systemd -%define _lock_dir /run/dehydrated -%else -%bcond_with systemd -%define _lock_dir /var/run/dehydrated -%endif - -%if (0%{?suse_version} < 1200 && !0%{?is_opensuse}) || 0%{?centos_version} || 0%{?rhel_version} -%bcond_with nginx -%bcond_with lighttpd -%else -%bcond_without nginx -%bcond_without lighttpd -%endif - -%{!?_tmpfilesdir: %global _tmpfilesdir /usr/lib/tmpfiles.d } Name: dehydrated Version: 0.4.0 @@ -58,30 +57,35 @@ Source2: acme-challenge.conf.nginx.in Source3: acme-challenge.conf.lighttpd.in Source4: dehydrated.cron.in Source5: dehydrated.tmpfiles.d -Source6: dehydrated-update.service.in -Source7: dehydrated-update.timer +Source6: dehydrated.service.in +Source7: dehydrated.timer Source8: dehydrated.1 +Source9: README.SUSE +Source10: README.Fedora # Patch submitted to upstream Patch1: 0001-Add-optional-user-and-group-configuration.patch # Patch from upstream Patch2: 0002-use-nullglob-disable-warning-on-empty-CONFIG_D-direc.patch BuildRequires: %{_apache} +Requires: coreutils +Requires: curl +Requires: openssl +Requires(pre): %{_bindir}/getent +Requires(pre): %{_sbindir}/groupadd +Requires(pre): %{_sbindir}/useradd +Obsoletes: letsencrypt.sh < %{version} +Provides: letsencrypt.sh = %{version} +BuildArch: noarch %if %{with lighttpd} BuildRequires: lighttpd %endif %if %{with nginx} BuildRequires: nginx %endif -%if 0%{?fedora_version} +%if %{defined fedora} BuildRequires: generic-logos BuildRequires: generic-logos-httpd %endif -Requires: coreutils -Requires: curl -Requires: openssl -Requires(pre): /usr/sbin/useradd -Requires(pre): /usr/sbin/groupadd -Requires(pre): /usr/bin/getent # openSUSE >= 12.3 has shadow, pwdutils is provided but obsoleted. %if 0%{?suse_version} >= 1230 BuildRequires: shadow @@ -96,15 +100,10 @@ Requires: cron %endif #with_systemd %if 0%{?suse_version} Recommends: dehydrated-acmeresponder -%else -Requires: dehydrated-acmeresponder %endif BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch -Obsoletes: letsencrypt.sh < %{version} -Provides: letsencrypt.sh = %{version} - %description This is a client for signing certificates with an ACME server (currently only provided by letsencrypt) implemented as a relatively @@ -124,27 +123,29 @@ Current features: * Certificate revocation %package %{_apache} +Summary: Apache Integration for dehydrated +Group: Productivity/Networking/Security Requires: %{_apache} Requires: %{name} +Obsoletes: letsencrypt.sh-%{_apache} < %{version} +Provides: letsencrypt.sh-%{_apache} = %{version} %if ! 0%{?suse_version} Requires: mod_ssl %endif -Obsoletes: letsencrypt.sh-%{_apache} < %{version} -Provides: letsencrypt.sh-%{_apache} = %{version} -Summary: Apache Integration for dehydrated -Group: Productivity/Networking/Security +BuildArch: noarch %description %{_apache} This adds a configuration file for dehydrated's acme-challenge to Apache. %if %{with nginx} %package nginx +Summary: Nginx Integration for dehydrated +Group: Productivity/Networking/Security Requires: %{name} Requires: nginx Obsoletes: letsencrypt.sh-nginx < %{version} Provides: letsencrypt.sh-nginx = %{version} -Summary: Nginx Integration for dehydrated -Group: Productivity/Networking/Security +BuildArch: noarch %description nginx This adds a configuration file for dehydrated's acme-challenge to nginx. @@ -152,40 +153,43 @@ This adds a configuration file for dehydrated's acme-challenge to nginx. %if %{with lighttpd} %package lighttpd -Requires: %{name} -Requires: lighttpd Summary: Lighttpd Integration for dehydrated Group: Productivity/Networking/Security +Requires: %{name} +Requires: lighttpd +BuildArch: noarch %description lighttpd This adds a configuration file for dehydrated's acme-challenge to lighttpd. -%endif #with lighttpd +%endif #with lighttpd %pre -getent group %{_user} >/dev/null || /usr/sbin/groupadd -r %{_user} -getent passwd %{_user} >/dev/null || /usr/sbin/useradd -g %{_user} \ +getent group %{_user} >/dev/null || %{_sbindir}/groupadd -r %{_user} +getent passwd %{_user} >/dev/null || %{_sbindir}/useradd -g %{_user} \ -s /bin/false -r -c "%{_user}" -d %{_home} %{_user} -if [ -d /etc/letsencrypt.sh ]; then mv /etc/letsencrypt.sh /etc/dehydrated; chown -R %{_user} /etc/dehydrated; fi -if [ -e /etc/dehydrated/config.sh ]; then mv /etc/dehydrated/config.sh /etc/dehydrated/config; fi +if [ -d %{_sysconfdir}/letsencrypt.sh ]; then mv %{_sysconfdir}/letsencrypt.sh %{_sysconfdir}/dehydrated; chown -R %{_user} %{_sysconfdir}/dehydrated; fi +if [ -e %{_sysconfdir}/dehydrated/config.sh ]; then mv %{_sysconfdir}/dehydrated/config.sh %{_sysconfdir}/dehydrated/config; fi %if %{with systemd} -%service_add_pre dehydrated-update.service dehydrated-update.timer +%service_add_pre dehydrated.service dehydrated.timer %post systemd-tmpfiles --create %{_tmpfilesdir}/%{name}.conf ||: -%service_add_post dehydrated-update.service dehydrated-update.timer +%service_add_post dehydrated.service dehydrated.timer %preun -%service_del_preun dehydrated-update.service dehydrated-update.timer +%service_del_preun dehydrated.service dehydrated.timer %postun -%service_del_postun dehydrated-update.service dehydrated-update.timer +%service_del_postun dehydrated.service dehydrated.timer %endif %prep %setup -q %patch1 -p1 %patch2 -p1 +cp %{SOURCE9} . +cp %{SOURCE10} . %build @@ -201,41 +205,41 @@ cat %{SOURCE8} | gzip > %{buildroot}%{_mandir}/man1/dehydrated.1.gz sed -i "s,#WELLKNOWN=.*,WELLKNOWN=%{_challengedir},g" docs/examples/config install -m 0644 docs/examples/* %{buildroot}%{_home} -install -m 0755 -d %{buildroot}/usr/bin -install -m 0755 dehydrated %{buildroot}/usr/bin +install -m 0755 -d %{buildroot}%{_bindir} +install -m 0755 dehydrated %{buildroot}%{_bindir} install -m 0755 -d %{buildroot}%{_challengedir} -install -m 0755 -d %{buildroot}/etc/%{_apache}/conf.d +install -m 0755 -d %{buildroot}%{_sysconfdir}/%{_apache}/conf.d sed "s,@CHALLENGEDIR@,%{_challengedir},g" %{SOURCE1} > acme-challenge.conf -install -m 0644 acme-challenge.conf %{buildroot}/etc/%{_apache}/conf.d +install -m 0644 acme-challenge.conf %{buildroot}%{_sysconfdir}/%{_apache}/conf.d %if %{with nginx} -install -m 0755 -d %{buildroot}/etc/nginx +install -m 0755 -d %{buildroot}%{_sysconfdir}/nginx sed "s,@CHALLENGEDIR@,%{_challengedir},g" %{SOURCE2} > acme-challenge -install -m 0644 acme-challenge %{buildroot}/etc/nginx +install -m 0644 acme-challenge %{buildroot}%{_sysconfdir}/nginx %endif #with nginx %if %{with lighttpd} -install -m 0755 -d %{buildroot}/etc/lighttpd/conf.d +install -m 0755 -d %{buildroot}%{_sysconfdir}/lighttpd/conf.d sed "s,@CHALLENGEDIR@,%{_challengedir},g" %{SOURCE3} > acme-challenge -install -m 0644 acme-challenge %{buildroot}/etc/lighttpd/conf.d +install -m 0644 acme-challenge %{buildroot}%{_sysconfdir}/lighttpd/conf.d %endif #with lighttpd %if %{with systemd} -install -D -m 0644 %{S:5} %{buildroot}%{_tmpfilesdir}/%{name}.conf -sed "s,@USER@,%{_user},g" %{S:6} > dehydrated-update.service +install -D -m 0644 %{SOURCE5} %{buildroot}%{_tmpfilesdir}/%{name}.conf +sed "s,@USER@,%{_user},g" %{SOURCE6} > dehydrated.service # Use timer -install -D -m 644 dehydrated-update.service %{buildroot}%{_unitdir}/dehydrated-update.service -install -D -m 644 %{S:7} %{buildroot}%{_unitdir}/dehydrated-update.timer +install -D -m 644 dehydrated.service %{buildroot}%{_unitdir}/dehydrated.service +install -D -m 644 %{SOURCE7} %{buildroot}%{_unitdir}/dehydrated.timer %if 0%{?suse_version} -ln -s /usr/sbin/service %{buildroot}%{_sbindir}/rcdehydrated-update +ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rcdehydrated %endif %else #with systemd install -D -d -m 0750 %{buildroot}%{_lock_dir} # Use cron -install -m 0755 -d %{buildroot}/etc/cron.d +install -m 0755 -d %{buildroot}%{_sysconfdir}/cron.d sed "s,@USER@,%{_user},g" %{SOURCE4} > dehydrated.cron -install -m 0644 dehydrated.cron %{buildroot}/etc/cron.d/dehydrated +install -m 0644 dehydrated.cron %{buildroot}%{_sysconfdir}/cron.d/dehydrated %endif #with systemd # Adjust config file @@ -260,11 +264,15 @@ diff -urN docs/examples/config %{buildroot}%{_home}/config ||: %attr(-,%{_user},root) %dir %{_localstatedir}/lib/acme-challenge %{_mandir}/man1/* %doc LICENSE README.md docs/*.md docs/*.jpg +%doc README.SUSE +%if %{defined redhat} +%doc README.Fedora +%endif %if %{with systemd} %{_tmpfilesdir}/%{name}.conf -%{_unitdir}/dehydrated-update.service -%{_unitdir}/dehydrated-update.timer -%{_sbindir}/rcdehydrated-update +%{_unitdir}/dehydrated.service +%{_unitdir}/dehydrated.timer +%{_sbindir}/rcdehydrated %ghost %attr(700,%{_user},%{_user}) %dir %{_lock_dir} %else %config %{_sysconfdir}/cron.d/dehydrated @@ -272,18 +280,18 @@ diff -urN docs/examples/config %{buildroot}%{_home}/config ||: %endif %files %{_apache} -%defattr(-,root,root,-) +%defattr(-,root,root) %config %{_sysconfdir}/%{_apache}/conf.d/acme-challenge.conf %if %{with nginx} %files nginx -%defattr(-,root,root,-) +%defattr(-,root,root) %config %attr(640,root,nginx) %{_sysconfdir}/nginx/acme-challenge %endif #with nginx %if %{with lighttpd} %files lighttpd -%defattr(-,root,root,-) +%defattr(-,root,root) %config %attr(640,root,lighttpd) %{_sysconfdir}/lighttpd/conf.d/acme-challenge %endif #with lighttpd diff --git a/dehydrated-update.timer b/dehydrated.timer similarity index 100% rename from dehydrated-update.timer rename to dehydrated.timer From 4089aed6d0cea02a80b5dfdb6731a437ba9764f613c8697d867d0cf68ae4ae87 Mon Sep 17 00:00:00 2001 From: Daniel Molkentin Date: Fri, 6 Oct 2017 10:52:01 +0000 Subject: [PATCH 4/4] Accepting request 531761 from home:dmolkentin:branches:security:dehydrated - Remove unused hooks directory - Introduced a directory for custom post-run hooks executed as root, see README.SUSE for details. (not to be confused with the native hooks run as dehyrated user) - Clarify necessity of enabling dehydrated.timer in README.SUSE - Submit to SLE15 as per fate#323377 - Add optional post run hook directory, executed by cron/systemd after dehydrated --cron has run - Remove hook directory intended for packaging other native hooks. Will be approach differently OBS-URL: https://build.opensuse.org/request/show/531761 OBS-URL: https://build.opensuse.org/package/show/security:dehydrated/dehydrated?expand=0&rev=13 --- README.SUSE | 45 ++++++++++++++++++++++++++++++------------- README.hooks | 4 ++++ dehydrated.changes | 22 +++++++++++++++++++++ dehydrated.cron.in | 2 +- dehydrated.service.in | 6 ++++-- dehydrated.spec | 16 +++++++++------ 6 files changed, 73 insertions(+), 22 deletions(-) create mode 100644 README.hooks diff --git a/README.SUSE b/README.SUSE index 1097b77..8f7755c 100644 --- a/README.SUSE +++ b/README.SUSE @@ -7,16 +7,32 @@ certificates (aka SSL Certificates) as simple as possible, while still being useful in a broad amount of use cases. Please consult the dehydrated man page, then continue reading here. -Aqcuisition through HTTP (http-01) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +IMPORTANT: On systemd-enabled system (SLE12+), you need to enable the update +timer, which has obsoleted the cron job. This is independent on which method +you chose from below! + +# systemctl enable dehydrated.timer + +Also note that with the systemd timer, failures will not be mailed to the +system administrator, but are being logged to the systemd journal, as per +systemd's design philosophy. + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Acquisition through HTTP (http-01) =================================== -This is the primary method of acquiring certifictes. +This is the primary method of acquiring certifictes. The Certificate Authority +will provide a challenge that the requestor needs to provide via HTTP on port 80/TCP, +in /.well-known/acme-challenge/. Setting up the acme-challenge auto-responder -------------------------------------------- -Apache -~~~~~~ +Apache (easiest) +~~~~~~~~~~~~~~~~ If you are using Apache, just install dehydrated-apache2 and reload Apache. This will take care of setting up the acme-challenge auto-responder. @@ -57,11 +73,11 @@ Machines without a webserver On machines that are not running any web server, e.g. mail relays, you can run apache2 with dehydrated-apache2. If you do not want to run any web server on a -system with systemd, you can use dehydrated-acmeresponder, a small socket -activated server. Once installed, it will automatically listen on port 80 -whenever the dehydrated cron job seeks renewal, assuming no other server is -currently occupying the port. It will also shut down once the timer has -finished execution. +system with systemd permnently, you can use dehydrated-acmeresponder. This is a +small socket activated server. Once installed, it will automatically listen on +port 80 whenever the dehydrated cron job seeks renewal, assuming no other +server is currently occupying the port. It will also shut down once the timer +has finished execution. Acquisition of initial certificate ---------------------------------- @@ -107,7 +123,7 @@ Ansible or Salt. For details, please refer to dns-verification.md. For openSUSE, the python-dns-lexicon package provides hooks into many DNS providers and DNS servers. -Proceeding After initial certificate Aquisition +Proceeding after initial certificate aquisition =============================================== Setting up the SSL host @@ -129,10 +145,13 @@ Limitations & Ceveats * It is currently not possible to aqcuire Wildcard certificates * No EV- or OV-validated certificates -* Certificates expire within weeks, not years, this is by design. Ensure that +* Certificates expire within weeks, not years. This is by design. Ensure that certificate renewal works and that daemons get reloaded frequently to pick - up certificate updates (This is currently not automated on the dehydrated end, - however Apache will reload every night due to log rotation). + up certificate updates. Apache will work due to log rotation SIGHUP'ing + the process frequently. However, any other actions, such as service reloads + need to be provided as a script in /etc/dehydrated/postrun-hooks.d, which + will be executed by the cron script / systemd timer *after* an update run + has been performed. Links ===== diff --git a/README.hooks b/README.hooks new file mode 100644 index 0000000..d20b81c --- /dev/null +++ b/README.hooks @@ -0,0 +1,4 @@ +Dehydrated's hooks only run as user dehydrated. To circumvent this limitation, +i.e. when services need to be restarted, all executable files in this directory +will be executed as root after the certificate update has run. + diff --git a/dehydrated.changes b/dehydrated.changes index eb18e42..071ea65 100644 --- a/dehydrated.changes +++ b/dehydrated.changes @@ -1,3 +1,25 @@ +------------------------------------------------------------------- +Thu Oct 5 13:36:39 UTC 2017 - daniel.molkentin@suse.com + +- Remove unused hooks directory + +- Introduced a directory for custom post-run hooks executed as root, + see README.SUSE for details. (not to be confused with the native hooks + run as dehyrated user) + +------------------------------------------------------------------- +Fri Sep 29 15:14:29 UTC 2017 - daniel.molkentin@suse.com + +- Clarify necessity of enabling dehydrated.timer in README.SUSE + +- Submit to SLE15 as per fate#323377 + +- Add optional post run hook directory, executed by cron/systemd + after dehydrated --cron has run + +- Remove hook directory intended for packaging other native hooks. + Will be approach differently + ------------------------------------------------------------------- Wed Sep 27 10:09:16 UTC 2017 - daniel.molkentin@suse.com diff --git a/dehydrated.cron.in b/dehydrated.cron.in index 0065bc9..ba90790 100644 --- a/dehydrated.cron.in +++ b/dehydrated.cron.in @@ -2,4 +2,4 @@ SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin MAILTO=root -25 3 * * * @USER@ test -e /etc/dehydrated/config && /usr/bin/dehydrated --cron +25 3 * * * root test -e /etc/dehydrated/config && /usr/bin/dehydrated --cron && for i in $(find -L @POSTRUNHOOKS_DIR@ -maxdepth 1 -executable -type f); do $i; done; diff --git a/dehydrated.service.in b/dehydrated.service.in index 783e256..5f1fad2 100644 --- a/dehydrated.service.in +++ b/dehydrated.service.in @@ -6,7 +6,9 @@ Wants=acmeresponder.socket [Service] Type=oneshot +ExecStartPre-=/usr/bin/sh -c 'for i in $(find -L @POSTRUNHOOKS_DIR@ -maxdepth 1 -executable -type f); do $i; done;' ExecStart=/usr/bin/dehydrated --cron -User=@USER@ -Group=@USER@ +# dehydrated --cron will drop permissions and run critical code as dehydrated user. +User=root +Group=root diff --git a/dehydrated.spec b/dehydrated.spec index 7c94fef..e289eed 100644 --- a/dehydrated.spec +++ b/dehydrated.spec @@ -19,6 +19,7 @@ %define _challengedir %{_localstatedir}/lib/acme-challenge %define _user dehydrated %define _home %{_sysconfdir}/dehydrated +%define _postrunhooks %{_home}/postrun-hooks.d %if 0%{?suse_version} > 1230 %define _lock_dir /run/dehydrated @@ -28,7 +29,7 @@ %bcond_with systemd %endif -%if %{defined is_opensuse} || %{defined fedora} +%if 0%{?is_opensuse} || %{defined fedora} %bcond_without nginx %bcond_without lighttpd %else @@ -62,6 +63,7 @@ Source7: dehydrated.timer Source8: dehydrated.1 Source9: README.SUSE Source10: README.Fedora +Source11: README.hooks # Patch submitted to upstream Patch1: 0001-Add-optional-user-and-group-configuration.patch # Patch from upstream @@ -199,12 +201,13 @@ mkdir -p %{buildroot}%{_home}/{accounts,certs} mkdir -p %{buildroot}%{_sbindir} mkdir -p %{buildroot}%{_mandir}/man1 mkdir -p %{buildroot}%{_home}/config.d -mkdir -p %{buildroot}%{_home}/hooks # used by hook packages +mkdir -p %{buildroot}%{_postrunhooks} cat %{SOURCE8} | gzip > %{buildroot}%{_mandir}/man1/dehydrated.1.gz sed -i "s,#WELLKNOWN=.*,WELLKNOWN=%{_challengedir},g" docs/examples/config install -m 0644 docs/examples/* %{buildroot}%{_home} +install -m 0644 %{SOURCE11} %{buildroot}%{_postrunhooks} install -m 0755 -d %{buildroot}%{_bindir} install -m 0755 dehydrated %{buildroot}%{_bindir} install -m 0755 -d %{buildroot}%{_challengedir} @@ -227,10 +230,10 @@ install -m 0644 acme-challenge %{buildroot}%{_sysconfdir}/lighttpd/conf.d %if %{with systemd} install -D -m 0644 %{SOURCE5} %{buildroot}%{_tmpfilesdir}/%{name}.conf -sed "s,@USER@,%{_user},g" %{SOURCE6} > dehydrated.service # Use timer +sed "s,@POSTRUNHOOKS_DIR@,%{_postrunhooks},g" %{SOURCE6} > dehydrated.service install -D -m 644 dehydrated.service %{buildroot}%{_unitdir}/dehydrated.service -install -D -m 644 %{SOURCE7} %{buildroot}%{_unitdir}/dehydrated.timer +install -D -m 644 %{SOURCE7} %{buildroot}%{_unitdir}/dehydrated.timer %if 0%{?suse_version} ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rcdehydrated %endif @@ -238,7 +241,7 @@ ln -s %{_sbindir}/service %{buildroot}%{_sbindir}/rcdehydrated install -D -d -m 0750 %{buildroot}%{_lock_dir} # Use cron install -m 0755 -d %{buildroot}%{_sysconfdir}/cron.d -sed "s,@USER@,%{_user},g" %{SOURCE4} > dehydrated.cron +sed "s,@POSTRUNHOOKS_DIR@,%{_postrunhooks},g" %{SOURCE4} > dehydrated.cron install -m 0644 dehydrated.cron %{buildroot}%{_sysconfdir}/cron.d/dehydrated %endif #with systemd @@ -259,7 +262,8 @@ diff -urN docs/examples/config %{buildroot}%{_home}/config ||: %config(noreplace) %attr(750,root,%{_user}) %{_sysconfdir}/dehydrated/config.d %config(noreplace) %attr(640,root,%{_user}) %{_sysconfdir}/dehydrated/domains.txt %config(noreplace) %attr(750,root,%{_user}) %{_sysconfdir}/dehydrated/hook.sh -%config(noreplace) %attr(750,root,%{_user}) %{_sysconfdir}/dehydrated/hooks +%dir %attr(750,root,%{_user}) %{_postrunhooks} +%config(noreplace) %attr(640,root,%{_user}) %{_postrunhooks}/README.hooks %{_bindir}/dehydrated %attr(-,%{_user},root) %dir %{_localstatedir}/lib/acme-challenge %{_mandir}/man1/*