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
This commit is contained in:
Marcus Rückert 2017-09-22 13:35:31 +00:00 committed by Git OBS Bridge
parent 19ef4a12d8
commit fc9dddc9f9
5 changed files with 310 additions and 2 deletions

View File

@ -0,0 +1,66 @@
From 700040068e3c08025f206e06ba5cfa76a124d805 Mon Sep 17 00:00:00 2001
From: Daniel Molkentin <dmolkentin@suse.com>
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: <unset>
--
2.12.3

View File

@ -0,0 +1,49 @@
From 5214632c55c70c6c1f0dabce204a9fb8529c8ca8 Mon Sep 17 00:00:00 2001
From: Lukas Schauer <lukas@schauer.so>
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

155
dehydrated.1 Normal file
View File

@ -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 .

View File

@ -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
@ -18,6 +33,8 @@ Wed Sep 13 15:27:08 UTC 2017 - daniel.molkentin@suse.com
- 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

View File

@ -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