diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2023-08-22 13:48:02 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2023-08-22 13:48:02 +0300 |
commit | 34da8acec06dc6e7ad17e2be96c63b34d6865762 (patch) | |
tree | 965e4ec2df01685e66549990e61a80605b950013 | |
parent | 1e14416916046acb2e90a9cef9256b33f132a24e (diff) | |
download | acmeman-master.tar.gz acmeman-master.tar.bz2 |
-rwxr-xr-x | acmeman | 65 | ||||
-rw-r--r-- | lib/App/Acmeman/Source/Pound.pm | 61 |
2 files changed, 106 insertions, 20 deletions
@@ -823,7 +823,8 @@ from the input files will form the list of its alternative names. [core] source = pound [--config=FILE] [--host=HOST] \ - [--type=http|https] [--listener=NAME] + [--type=http|https] [--listener=NAME] \ + [--comment=TEXT] Domain names will be read from I<FILE> or, if it is not supplied, from the default B<pound> configuration file F</etc/pound.cfg>. By default, @@ -841,6 +842,62 @@ appear as arguments to B<Host> statements. If B<--listener> option is used, module will scan only the named listener. To select multiple listeners, use several B<--listener> options. +The B<--comment> option defines a text, which, when appearing at the +start of a comment line, enables host name collection. Such I<pragmatical> +comments may appear anywhere within listener and service sections and their +scope is limited by the corresponding section. When this option is used, +host collection is disabled by default. For example, assuming +B<--comment=acme>, the following configuration snippet (with irrelevant +statements replaced by ellipses) will result in issuing certificate for +C<example.org> and C<www.example.org>: + + ListenerHTTP + # acme + Service + Host -exact "example.org" + ... + End + + Service + Host -exact "www.example.org" + ... + End + End + +In contrast, when processing the following snippet, B<acmeman> will issue +certificate for C<example.org> only: + + ListenerHTTP + Service + # acme + Host -exact "example.org" + ... + End + + Service + Host -exact "www.example.org" + ... + End + End + +Furthermore, using B<no-I<TEXT>> at the start of a comment cancels +the effect of the previous pragmatic comment. This can be used for +better control of host selection: + + ListenerHTTP + Service + Match OR + # acme + Host -exact "example.org" + Host -exact "www.example.org" + # no-acme + Host -exact "test.example.org" + End + ... + End + End + + If the B<--host> (B<-h>) option is used, only one certificate will be issued. The I<HOST> will be used as its B<CN>. All the domain names read from the input files will form the list of its alternative names. @@ -856,9 +913,9 @@ cope with it. When declaring multiple hosts, always use the B<Match OR> section, like this: Match OR - Host "host1" - Host "host2" - Host "host3" + Host -exact "host1" + Host -exact "host2" + Host -exact "host3" End =item 2. These B<Host> statements (or the enclosing B<Match OR> section) diff --git a/lib/App/Acmeman/Source/Pound.pm b/lib/App/Acmeman/Source/Pound.pm index f02d128..daf5373 100644 --- a/lib/App/Acmeman/Source/Pound.pm +++ b/lib/App/Acmeman/Source/Pound.pm @@ -11,16 +11,21 @@ sub new { my $host; my @listener; my @types; + my $comment; GetOptionsFromArray(\@_, 'config|f=s' => \$cfgname, 'host|h=s' => \$host, 'listener=s@' => \@listener, - 'type=s@' => \@types + 'type=s@' => \@types, + 'comment=s' => \$comment ); my $self = bless { cfgname => $cfgname, host => $host, }, $class; + if ($comment) { + $self->{comment} = qr($comment) + } if (@listener) { $self->{listener} = { map { $_ => 1 } @listener }; } @@ -89,46 +94,58 @@ sub scan { ST_IGNORE => 5 }; my $state = ST_INIT; - my $acme = 0; - my $coalesce = 0; + my $acme; + my @collect_state; my @lsthosts; my @srvhosts; my $endcnt; while (<$fh>) { chomp; - s/#.*//; + s/^\s+//; + if ($self->{comment} && m{#\s*(no-)?$self->{comment}}) { + if (@collect_state) { + my $hint = 1; + if ($1) { + $hint = 0; + } + debug(4, "$self->{cfgname}:$.: hint=$hint"); + $collect_state[$#collect_state] = $hint; + } + } + + s/#.*//; next if (/^$/); + if ($state == ST_INIT) { if (/^ListenHTTP(?:(?<s>S)?\s+"(?<name>.*)"\s*)?$/i) { if ($self->lstn_ok($+{s}, $+{name})) { debug(4, "$self->{cfgname}:$.: listener"); $state = ST_LISTENER; + $acme = 0; if (defined($+{s}) && uc($+{s}) eq 'S') { $acme = 1; - $coalesce = 1; } + push @collect_state, !defined($self->{comment}); @lsthosts = (); } else { $state = ST_IGNORE; } } } elsif ($state == ST_LISTENER) { - debug(4, "$self->{cfgname}:$.: service"); if (/^Service(?:\s+".*"\s*)?$/i) { + debug(4, "$self->{cfgname}:$.: service"); + push @collect_state, $collect_state[$#collect_state]; $state = ST_SERVICE; @srvhosts = (); } elsif (/^ACME\s/i) { $acme = 1; } elsif (/^End$/i) { - if ($acme) { + debug(4, "$self->{cfgname}:$.: listener ends"); + pop @collect_state; + if ($acme && @lsthosts) { if ($self->{host}) { $self->define_alias($self->{host}, map { @$_ } @lsthosts); - } elsif ($coalesce) { - my @hosts = (map {@$_} @lsthosts); - my $cn = shift @hosts; - $self->define_domain($cn); - $self->define_alias($cn, @hosts) if @hosts; } else { foreach my $hosts (@lsthosts) { my $cn = shift @{$hosts}; @@ -137,7 +154,6 @@ sub scan { } } } - $state = ST_INIT; } } elsif ($state == ST_IGNORE) { @@ -152,24 +168,32 @@ sub scan { } } elsif ($state == ST_SERVICE) { if (s/^Host\s+//i) { + if ($collect_state[$#collect_state]) { if (my @hosts = $self->host($_)) { debug(3, "$self->{cfgname}:$.: hosts ".join(',', @hosts)); push @srvhosts, @hosts; } + } } elsif (/^Backend/i) { $state = ST_EXPEND; } elsif (/^Match/i) { $state = ST_MATCH; } elsif (/^End$/i) { $state = ST_LISTENER; - push @lsthosts, [ @srvhosts ] if (@srvhosts); + if (@srvhosts) { + push @lsthosts, [ @srvhosts ]; + } + pop @collect_state; + debug(4, "$self->{cfgname}:$.: service ends"); } } elsif ($state == ST_MATCH) { if (s/^Host\s+//i) { + if ($collect_state[$#collect_state]) { if (my @hosts = $self->host($_)) { debug(3, "$self->{cfgname}:$.: hosts ".join(',', @hosts)); push @srvhosts, @hosts; } + } } elsif (/^End$/i) { $state = ST_SERVICE; } @@ -180,8 +204,13 @@ sub scan { } } close $fh; - # FIXME: check state - #debug(1, "$.: end state $state"); + + if (@collect_state) { + error("$self->{cfgname}: parsing failed, " . (0+@collect_state) . + " states remained on stack"); + return 0 + } + return 1; } |