aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2023-08-22 13:48:02 +0300
committerSergey Poznyakoff <gray@gnu.org>2023-08-22 13:48:02 +0300
commit34da8acec06dc6e7ad17e2be96c63b34d6865762 (patch)
tree965e4ec2df01685e66549990e61a80605b950013
parent1e14416916046acb2e90a9cef9256b33f132a24e (diff)
downloadacmeman-master.tar.gz
acmeman-master.tar.bz2
pound source: optionally use pragmatic comments to control host collectionHEADmaster
-rwxr-xr-xacmeman65
-rw-r--r--lib/App/Acmeman/Source/Pound.pm61
2 files changed, 106 insertions, 20 deletions
diff --git a/acmeman b/acmeman
index 1520dcc..5225751 100755
--- a/acmeman
+++ b/acmeman
@@ -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;
}

Return to:

Send suggestions and report system problems to the System administrator.