From 95c82ca2a5562e60463a38519157ae1a8b60ac1a Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Mon, 7 May 2018 11:27:28 +0300 Subject: Improve "file" source * lib/App/Acmeman/Source/File.pm (new): New options --ignore and --host. * acmeman: Document the "file" source. --- acmeman | 74 +++++++++++++++++++++++++++++++++--------- lib/App/Acmeman/Source/File.pm | 24 +++++++++++--- 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/acmeman b/acmeman index 7edd5e0..143ef43 100755 --- a/acmeman +++ b/acmeman @@ -84,7 +84,7 @@ scans B configuration files for a list of domains. B is normally run periodically as a cronjob. If you plan to serve SSL protected domains using apache, you can skip -right to the B section. +right to the B section. The following is a short introduction to the B configuration. For a detailed discussion, see the B section below. @@ -127,7 +127,9 @@ the B section lacks the B keyword. The special section B<[core]> contains basic settings that control the program behavior. One of the important settings is B, which declares an external source from which domain settings must be obtained. As -of B version 2.00, the only available external source is B. +of B version 1.05, the following sources are available: +B, B, and B. + Consider the following configuration: [core] @@ -211,20 +213,24 @@ server (or whatever server is using the certificates). If more than one B statements are defined, they will be run in sequence, in the same order as they appeared in the configuration file. -=item BI [I] +=item BI [I...] Defines additional source of information. B version 1.05 -is shipped with two sources: B and B. +is shipped with three sources: B, B, and B. -The B module is an empty source. Use it if all domains are described -in the configuration file. +The B module is an empty source. Command line arguments are ignored. +Use this source if all domains are described in the configuration file. The B source module is the default. It scans B configuration -files as described in section B. The optional I argument -defines the apache configuration layout. Allowed values are: B, -B, B and B (for Red Hat). If I is absent, it +files as described in section B. One argument is allowed. If supplied, +it defines the apache configuration layout. Allowed values are: B, +B, B and B (for Red Hat). Without arguments, the layout will be autodetected. +The B source reads domain names from one or more disk files. A +mandatory argument specifies the name of the directory where the files +are located. This mode is suitable for use with B pattern files. + =item BI Identifies the B<[files]> section which describes how to create certificate @@ -345,13 +351,29 @@ be replaced with the actual domain name. Default is B<$domain>. =back -=head1 APACHE +=head1 SOURCES + +=head2 null + + [core] + source = null + +Declares empty source. This means that B will handle only domain +names explicitly declared in the configuration file using the B +setting. + +=head2 apache -This is the default mode. It assumes Apache httpd, version 2.4 or later + [core] + source = apache [LAYOUT] + +This is the default source. It assumes Apache httpd, version 2.4 or later (although only minor changes are necessary to make it work with version 2.2). -Four most popular layouts of Apache configuration files are supported: -Debian, Slackware, SuSe, and Red Hat. A special directory should be -configured for receiving ACME challenges. +The optional I argument defines the layout of the apache configuration +files. Allowed layout values are: B, B, B and +B (for Red Hat). If not supplied, the layout is determined automatically. + +A special directory should be configured for receiving ACME challenges. The package provides two Apache macros: for serving ACME challenges and declaring SSL virtual hosts. @@ -363,7 +385,7 @@ predefined number of seconds (24 hours by default). If any of the certificates were updated during the run, B will restart the B server. -=head2 Setup +=head3 Setup To set up the necessary infrastructure, run B. It will create the configuration file B, defining two @@ -386,7 +408,7 @@ domain, and F, containing the private key for that domain. The program will refuse to overwrite existing files B, unless given the B<--force> (B<-F>) option. -=head2 Configuring SSL +=head3 Configuring SSL To declare that a virtual host needs SSL certificate, add the following line to the Apache B block serving plain HTTP for that host: @@ -465,6 +487,26 @@ will use the B macro to configure the correct certificate: ... +=head2 file + + [core] + source = file PATTERN [--ignore=RX] [--host=HOST] + +Domain names will be read from files matching I. This argument +can be either a valid globbing pattern or a directory name. In the latter +case, the source module will read all files from that directory, except +those whose names match the following perl regexp: C<^\.|~$|\.bak$|^#.*#$>. +The default regexp can be overridden using the B<--ignore> (B<-i>) option. + +The input files must contain exactly one domain name per line. No empty +lines or comments are allowed. The first domain name will become the B +of the issued certificate. The rest of domain names will form alternative +names. + +If the B<--host> (B<-h>) option is used, only one certificate will be +issued. The I will be used as its B. All the domain names read +from the input files will form the list of its alternative names. + =head1 OPTIONS =over 4 diff --git a/lib/App/Acmeman/Source/File.pm b/lib/App/Acmeman/Source/File.pm index 561c279..48a4010 100644 --- a/lib/App/Acmeman/Source/File.pm +++ b/lib/App/Acmeman/Source/File.pm @@ -5,22 +5,32 @@ use warnings; use Carp; use File::Spec; use parent 'App::Acmeman::Source'; +use Getopt::Long qw(GetOptionsFromArray :config gnu_getopt no_ignore_case); sub new { my $class = shift; my $pattern = shift || croak "file name or globbing pattern must be given"; my $ignore = '^\.|~$|\.bak$|^#.*#$'; + my $host; + GetOptionsFromArray(\@_, + 'ignore|i=s' => \$ignore, + 'host|h=s' => \$host); unless ($pattern =~ m{[][*?]}) { $pattern =~ s{/$}{}; $pattern = File::Spec->catfile($pattern, '*'); } - bless { pattern => $pattern, ignore => $ignore }, $class; + bless { pattern => $pattern, + ignore => $ignore, + host => $host }, $class; } sub scan { my ($self) = @_; $self->debug(1, "initializing file list from $self->{pattern}"); my $err = 0; + if ($self->{host}) { + $self->define_domain($self->{host}); + } foreach my $file (glob $self->{pattern}) { next if $file =~ m{$self->{ignore}}; $err |= $self->load($file); @@ -35,12 +45,16 @@ sub load { or do { $self->error("can't open $file: $!"); return 0; - }; + }; chomp(my @lines = <$fh>); close $fh; - my $cn = shift @lines; - $self->define_domain($cn); - $self->define_alias($cn, @lines); + if ($self->{host}) { + $self->define_alias($self->{host}, @lines); + } else { + my $cn = shift @lines; + $self->define_domain($cn); + $self->define_alias($cn, @lines); + } return 1; } -- cgit v1.2.1