Package: lacme Version: 0.5-1 Severity: wishlist Tags: patch upstream Dear Maintainer,
in our setup multiple http-servers can be used to serve a random file. For the static files, the storage is syncronized filesystem replication. When lacme creates a challenge-response for a new certificate, it is unclear, which of the external servers will serve that request. Due to the replication, all of the servers could have access to the challenge file, but currently lacme only creates a symlink into a temporary directory. The attached patch adds a new configuration option `hard-copy-challenge-directory`, which will drop the temporary file and handles the acme-challenge directory directly. best regards -- System Information: Debian Release: 10.5 APT prefers stable APT policy: (500, 'stable') Architecture: amd64 (x86_64) Kernel: Linux 4.19.0-10-amd64 (SMP w/1 CPU core) Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8), LANGUAGE=en_GB.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Init: systemd (via /run/systemd/system) LSM: AppArmor: enabled Versions of packages lacme depends on: ii libconfig-tiny-perl 2.23-1 ii libjson-perl 4.02000-1 ii libnet-ssleay-perl 1.85-2+b1 ii libtypes-serialiser-perl 1.0-1 ii libwww-perl 6.36-2 ii openssl 1.1.1d-1+0~20191009.15+debian9~1.gbpd6badf ii perl 5.28.1-6+deb10u1 Versions of packages lacme recommends: ii lacme-accountd 0.6-1 ii liblwp-protocol-https-perl 6.07-2 lacme suggests no packages. -- Configuration Files: /etc/lacme/lacme.conf changed [not included] -- no debconf information --- a/config/lacme.conf 2020-09-23 14:14:46.274311863 +0200 +++ b/config/lacme.conf 2020-09-23 14:16:19.324643678 +0200 @@ -86,6 +86,10 @@ # #challenge-directory = +# Do not symlink the challenge-directory, but copy the challenge-files +# explictly +#hard-copy-challenge-directory = Yes + # username to drop privileges to (setting both effective and real uid). # Preserve root privileges if the value is empty (not recommended). # --- a/lacme 2020-09-23 14:16:28.124864204 +0200 +++ b/lacme 2020-09-23 16:14:21.456006087 +0200 @@ -28,6 +28,7 @@ use Errno 'EINTR'; use Fcntl qw/F_GETFD F_SETFD FD_CLOEXEC SEEK_SET/; use File::Temp (); +use File::Path 'remove_tree'; use Getopt::Long qw/:config posix_default no_ignore_case gnu_getopt auto_version/; use List::Util 'first'; use POSIX (); @@ -100,6 +101,7 @@ webserver => { listen => '/var/run/lacme-www.socket', 'challenge-directory' => undef, + 'hard-copy-challenge-directory' => 'No', user => 'www-data', group => 'www-data', command => '/usr/lib/lacme/webserver', @@ -315,10 +317,26 @@ # serve ACME challenge reponses). if (defined (my $dir = $conf->{'challenge-directory'})) { print STDERR "[$$] Using existing webserver on $dir\n" if $OPTS{debug}; - symlink $tmpdir, $dir or die "Can't symlink $dir -> $tmpdir: $!"; - push @CLEANUP, sub() { - print STDERR "Unlinking $dir\n" if $OPTS{debug}; - unlink $dir or warn "Warning: Can't unlink $dir: $!"; + if (lc ($conf->{'hard-copy-challenge-directory'} // 'No') eq 'yes') { + mkdir $dir or die "Can't create directory $dir: $!"; + $tmpdir = $dir; + push @CLEANUP, sub() { + my $error = undef; + remove_tree($dir, { safe => 1, error => \$error }); + if($error && @$error) { + for(@$error) { + my ($file, $message) = %$_; + my $msghead = $file?"Error removing $file in":"Error while removing"; + warn "$msghead challenge dir $dir: $message\n"; + } + } + } + } else { + symlink $tmpdir, $dir or die "Can't symlink $dir -> $tmpdir: $!"; + push @CLEANUP, sub() { + print STDERR "Unlinking $dir\n" if $OPTS{debug}; + unlink $dir or warn "Warning: Can't unlink $dir: $!"; + } } } elsif (!@sockaddr) {
--- a/config/lacme.conf 2020-09-23 14:14:46.274311863 +0200 +++ b/config/lacme.conf 2020-09-23 14:16:19.324643678 +0200 @@ -86,6 +86,10 @@ # #challenge-directory = +# Do not symlink the challenge-directory, but copy the challenge-files +# explictly +#hard-copy-challenge-directory = Yes + # username to drop privileges to (setting both effective and real uid). # Preserve root privileges if the value is empty (not recommended). # --- a/lacme 2020-09-23 14:16:28.124864204 +0200 +++ b/lacme 2020-09-23 16:14:21.456006087 +0200 @@ -28,6 +28,7 @@ use Errno 'EINTR'; use Fcntl qw/F_GETFD F_SETFD FD_CLOEXEC SEEK_SET/; use File::Temp (); +use File::Path 'remove_tree'; use Getopt::Long qw/:config posix_default no_ignore_case gnu_getopt auto_version/; use List::Util 'first'; use POSIX (); @@ -100,6 +101,7 @@ webserver => { listen => '/var/run/lacme-www.socket', 'challenge-directory' => undef, + 'hard-copy-challenge-directory' => 'No', user => 'www-data', group => 'www-data', command => '/usr/lib/lacme/webserver', @@ -315,10 +317,26 @@ # serve ACME challenge reponses). if (defined (my $dir = $conf->{'challenge-directory'})) { print STDERR "[$$] Using existing webserver on $dir\n" if $OPTS{debug}; - symlink $tmpdir, $dir or die "Can't symlink $dir -> $tmpdir: $!"; - push @CLEANUP, sub() { - print STDERR "Unlinking $dir\n" if $OPTS{debug}; - unlink $dir or warn "Warning: Can't unlink $dir: $!"; + if (lc ($conf->{'hard-copy-challenge-directory'} // 'No') eq 'yes') { + mkdir $dir or die "Can't create directory $dir: $!"; + $tmpdir = $dir; + push @CLEANUP, sub() { + my $error = undef; + remove_tree($dir, { safe => 1, error => \$error }); + if($error && @$error) { + for(@$error) { + my ($file, $message) = %$_; + my $msghead = $file?"Error removing $file in":"Error while removing"; + warn "$msghead challenge dir $dir: $message\n"; + } + } + } + } else { + symlink $tmpdir, $dir or die "Can't symlink $dir -> $tmpdir: $!"; + push @CLEANUP, sub() { + print STDERR "Unlinking $dir\n" if $OPTS{debug}; + unlink $dir or warn "Warning: Can't unlink $dir: $!"; + } } } elsif (!@sockaddr) {