aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog2
-rw-r--r--Makefile1
-rw-r--r--config/lacme.conf6
-rwxr-xr-xlacme65
-rw-r--r--lacme.md21
5 files changed, 58 insertions, 37 deletions
diff --git a/Changelog b/Changelog
index 3018a4d..f685306 100644
--- a/Changelog
+++ b/Changelog
@@ -8,6 +8,8 @@ lacme (0.2) upstream;
ignored, and the two processes communicate through a socket pair.
+ lacme: add an option --quiet to avoid mentioning valid certs (useful
in cronjobs)
+ + "config-certs" now points to a space separated list of files or
+ directories. New default "lacme-certs.conf lacme-certs.d/".
- Minor manpage fixes
- More useful message upon Validation Challenge failure.
diff --git a/Makefile b/Makefile
index 4e5f06d..d83c843 100644
--- a/Makefile
+++ b/Makefile
@@ -25,6 +25,7 @@ all: ${MANPAGES}
install: ${MANPAGES}
install -d $(DESTDIR)/etc/lacme
+ install -d $(DESTDIR)/etc/lacme/lacme-certs.d
install -m0644 -t $(DESTDIR)/etc/lacme config/*.conf
install -d $(DESTDIR)/usr/share/lacme
install -m0644 -t $(DESTDIR)/usr/share/lacme certs/lets-encrypt-x[1-4]-cross-signed.pem
diff --git a/config/lacme.conf b/config/lacme.conf
index 08afeb4..f963128 100644
--- a/config/lacme.conf
+++ b/config/lacme.conf
@@ -1,7 +1,7 @@
-# For certificate issuance (new-cert command), specify the certificate
-# configuration file to use
+# For certificate issuance (new-cert command), specify a space-separated
+# certificate configuration files or directories to use
#
-#config-certs = /etc/lacme/lacme-certs.conf
+#config-certs = lacme-certs.conf lacme-certs.d/
[client]
diff --git a/lacme b/lacme
index 86071fd..3b7c174 100755
--- a/lacme
+++ b/lacme
@@ -60,7 +60,7 @@ sub usage(;$$) {
}
exit $rv;
}
-usage(1) unless GetOptions(\%OPTS, qw/config=s config-certs=s socket=s agreement-uri=s quiet|q debug help|h/);
+usage(1) unless GetOptions(\%OPTS, qw/config=s config-certs=s@ socket=s agreement-uri=s quiet|q debug help|h/);
usage(0) if $OPTS{help};
$COMMAND = shift(@ARGV) // usage(1, "Missing command");
@@ -68,15 +68,15 @@ $COMMAND = $COMMAND =~ /\A(new-reg|reg=\p{Print}*|new-cert|revoke-cert)\z/ ? $1
: usage(1, "Invalid command: $COMMAND"); # validate and untaint $COMMAND
@ARGV = map { /\A(\p{Print}*)\z/ ? $1 : die } @ARGV; # untaint @ARGV
+my $CONFFILENAME = $OPTS{config} // first { -f $_ }
+ ( "./$NAME.conf"
+ , ($ENV{XDG_CONFIG_HOME} // "$ENV{HOME}/.config")."/lacme/$NAME.conf"
+ , "/etc/lacme/$NAME.conf"
+ );
do {
- my $conffile = $OPTS{config} // first { -f $_ }
- ( "./$NAME.conf"
- , ($ENV{XDG_CONFIG_HOME} // "$ENV{HOME}/.config")."/lacme/$NAME.conf"
- , "/etc/lacme/$NAME.conf"
- );
- die "Error: Can't find configuration file\n" unless defined $conffile;
- print STDERR "Using configuration file: $conffile\n" if $OPTS{debug};
- open $CONFFILE, '<', $conffile or die "Can't open $conffile: $!\n";
+ die "Error: Can't find configuration file\n" unless defined $CONFFILENAME;
+ print STDERR "Using configuration file: $CONFFILENAME\n" if $OPTS{debug};
+ open $CONFFILE, '<', $CONFFILENAME or die "Can't open $CONFFILENAME: $!\n";
my $conf = do { local $/ = undef, <$CONFFILE> };
# don't close $CONFFILE so we can pass it to the client
@@ -559,24 +559,39 @@ if ($COMMAND eq 'new-reg' or $COMMAND =~ /^reg=/) {
# new-cert [SECTION ..]
#
elsif ($COMMAND eq 'new-cert') {
+ my $conffiles = defined $OPTS{'config-certs'} ? $OPTS{'config-certs'}
+ : defined $CONFIG->{_}->{'config-certs'} ? [ split(/\s+/, $CONFIG->{_}->{'config-certs'}) ]
+ : [ "$NAME-certs.conf", "$NAME-certs.d/" ];
my $conf;
- do {
- my $conffile = $OPTS{'config-certs'} // $CONFIG->{_}->{'config-certs'} // first { -f $_ }
- ( "./$NAME-certs.conf"
- , ($ENV{XDG_CONFIG_HOME} // "$ENV{HOME}/.config")."/lacme/$NAME-certs.conf"
- , "/etc/lacme/$NAME-certs.conf"
- );
- die "Error: Can't find certificate configuration file\n" unless defined $conffile;
- my $h = Config::Tiny::->read($conffile) or die Config::Tiny::->errstr()."\n";
- my $defaults = delete $h->{_} // {};
- my @valid = qw/certificate certificate-chain certificate-key min-days CAfile
- hash keyUsage subject subjectAltName chown chmod notify/;
- foreach my $s (keys %$h) {
- $conf->{$s} = { map { $_ => delete $h->{$s}->{$_} } @valid };
- die "Unknown option(s) in [$s]: ".join(', ', keys %{$h->{$s}})."\n" if %{$h->{$s}};
- $conf->{$s}->{$_} //= $defaults->{$_} foreach keys %$defaults;
+ foreach my $conffile (@$conffiles) {
+ $conffile = ($CONFFILENAME =~ s#[^/]+\z##r).$conffile unless $conffile =~ /\A\//;
+ my @filenames;
+ unless ($conffile =~ s#/\z## or -d $conffile) {
+ @filenames = ($conffile);
+ } else {
+ opendir my $dh, $conffile or die "Can't opendir $conffile: $!\n";
+ while (readdir $dh) {
+ if (/\.conf\z/) {
+ push @filenames, "$conffile/$_";
+ } elsif ($_ ne '.' and $_ ne '..') {
+ warn "$conffile/$_ has unknown suffix, skipping\n";
+ }
+ }
+ closedir $dh;
}
- };
+ foreach my $filename (sort @filenames) {
+ print STDERR "Reading $filename\n" if $OPTS{debug};
+ my $h = Config::Tiny::->read($filename) or die Config::Tiny::->errstr()."\n";
+ my $defaults = delete $h->{_} // {};
+ my @valid = qw/certificate certificate-chain certificate-key min-days CAfile
+ hash keyUsage subject subjectAltName chown chmod notify/;
+ foreach my $s (keys %$h) {
+ $conf->{$s} = { map { $_ => delete $h->{$s}->{$_} } @valid };
+ die "Unknown option(s) in [$s]: ".join(', ', keys %{$h->{$s}})."\n" if %{$h->{$s}};
+ $conf->{$s}->{$_} //= $defaults->{$_} foreach keys %$defaults;
+ }
+ }
+ }
my $challenge_dir;
my $rv = 0;
diff --git a/lacme.md b/lacme.md
index 24973db..69e3ce2 100644
--- a/lacme.md
+++ b/lacme.md
@@ -151,9 +151,18 @@ Default section
*config-certs*
: For certificate issuances (`new-cert` command), specify the
- certificate configuration file to use (see the **[certificate
- configuration file](#certificate-configuration-file)** section below
- for the configuration options).
+ space-separated list of certificate configuration files or
+ directories to use (see the **[certificate configuration
+ file](#certificate-configuration-file)** section below for the
+ configuration options).
+
+ Paths not starting with `/` are relative to the directory name of
+ the **[configuration filename](#configuration-file)**. The list of
+ files and directories is processed in order, with the later items
+ taking precedence. Files in a directory are processed in
+ lexicographic order, only considering the ones with suffix `.conf`.
+
+ Default: `lacme-certs.conf lacme-certs.d/`.
`[client]` section
------------------
@@ -303,12 +312,6 @@ Certificate configuration file
For certificate issuances (`new-cert` command), a separate file is used
to configure paths to the certificate and key, as well as the subject,
subjectAltName, etc. to generate Certificate Signing Requests.
-If `--config-certs=` is not given, and if the `config-certs`
-configuration option is absent, then `lacme` uses the first existing
-configuration file among *./lacme-certs.conf*,
-*$XDG_CONFIG_HOME/lacme/lacme-certs.conf* (or
-*~/.config/lacme/lacme-certs.conf* if the `XDG_CONFIG_HOME` environment
-variable is not set), and */etc/lacme/lacme-certs.conf*.
Each section denotes a separate certificate issuance.
Valid options are: