diff options
-rwxr-xr-x | acmeman | 77 | ||||
-rw-r--r-- | lib/App/Acmeman/Source/Pound.pm | 73 |
2 files changed, 118 insertions, 32 deletions
@@ -295,16 +295,16 @@ matching algorithm. If serving several host names, use the B<Match OR> block. | |||
295 | After these two steps, your listener section will look like: | 295 | After these two steps, your listener section will look like: |
296 | 296 | ||
297 | ListenHTTP | 297 | ListenHTTP |
298 | Address 0.0.0.0 | 298 | Address 0.0.0.0 |
299 | Port 80 | 299 | Port 80 |
300 | ACME "/var/lib/pound/acme/.well-known/acme-challenge" | 300 | ACME "/var/lib/pound/acme/.well-known/acme-challenge" |
301 | Service | 301 | Service |
302 | Match OR | 302 | Match OR |
303 | Host "www.example.org" | 303 | Host "www.example.org" |
304 | Host "example.org" | 304 | Host "example.org" |
305 | End | 305 | End |
306 | ... | 306 | ... |
307 | End | 307 | End |
308 | End | 308 | End |
309 | 309 | ||
310 | =over 4 | 310 | =over 4 |
@@ -823,7 +823,8 @@ from the input files will form the list of its alternative names. | |||
823 | 823 | ||
824 | [core] | 824 | [core] |
825 | source = pound [--config=FILE] [--host=HOST] \ | 825 | source = pound [--config=FILE] [--host=HOST] \ |
826 | [--type=http|https] [--listener=NAME] | 826 | [--type=http|https] [--listener=NAME] \ |
827 | [--comment=TEXT] | ||
827 | 828 | ||
828 | Domain names will be read from I<FILE> or, if it is not supplied, from | 829 | Domain names will be read from I<FILE> or, if it is not supplied, from |
829 | the default B<pound> configuration file F</etc/pound.cfg>. By default, | 830 | the default B<pound> configuration file F</etc/pound.cfg>. By default, |
@@ -841,6 +842,62 @@ appear as arguments to B<Host> statements. | |||
841 | If B<--listener> option is used, module will scan only the named listener. | 842 | If B<--listener> option is used, module will scan only the named listener. |
842 | To select multiple listeners, use several B<--listener> options. | 843 | To select multiple listeners, use several B<--listener> options. |
843 | 844 | ||
845 | The B<--comment> option defines a text, which, when appearing at the | ||
846 | start of a comment line, enables host name collection. Such I<pragmatical> | ||
847 | comments may appear anywhere within listener and service sections and their | ||
848 | scope is limited by the corresponding section. When this option is used, | ||
849 | host collection is disabled by default. For example, assuming | ||
850 | B<--comment=acme>, the following configuration snippet (with irrelevant | ||
851 | statements replaced by ellipses) will result in issuing certificate for | ||
852 | C<example.org> and C<www.example.org>: | ||
853 | |||
854 | ListenerHTTP | ||
855 | # acme | ||
856 | Service | ||
857 | Host -exact "example.org" | ||
858 | ... | ||
859 | End | ||
860 | |||
861 | Service | ||
862 | Host -exact "www.example.org" | ||
863 | ... | ||
864 | End | ||
865 | End | ||
866 | |||
867 | In contrast, when processing the following snippet, B<acmeman> will issue | ||
868 | certificate for C<example.org> only: | ||
869 | |||
870 | ListenerHTTP | ||
871 | Service | ||
872 | # acme | ||
873 | Host -exact "example.org" | ||
874 | ... | ||
875 | End | ||
876 | |||
877 | Service | ||
878 | Host -exact "www.example.org" | ||
879 | ... | ||
880 | End | ||
881 | End | ||
882 | |||
883 | Furthermore, using B<no-I<TEXT>> at the start of a comment cancels | ||
884 | the effect of the previous pragmatic comment. This can be used for | ||
885 | better control of host selection: | ||
886 | |||
887 | ListenerHTTP | ||
888 | Service | ||
889 | Match OR | ||
890 | # acme | ||
891 | Host -exact "example.org" | ||
892 | Host -exact "www.example.org" | ||
893 | # no-acme | ||
894 | Host -exact "test.example.org" | ||
895 | End | ||
896 | ... | ||
897 | End | ||
898 | End | ||
899 | |||
900 | |||
844 | If the B<--host> (B<-h>) option is used, only one certificate will be | 901 | If the B<--host> (B<-h>) option is used, only one certificate will be |
845 | issued. The I<HOST> will be used as its B<CN>. All the domain names read | 902 | issued. The I<HOST> will be used as its B<CN>. All the domain names read |
846 | from the input files will form the list of its alternative names. | 903 | 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> | |||
856 | section, like this: | 913 | section, like this: |
857 | 914 | ||
858 | Match OR | 915 | Match OR |
859 | Host "host1" | 916 | Host -exact "host1" |
860 | Host "host2" | 917 | Host -exact "host2" |
861 | Host "host3" | 918 | Host -exact "host3" |
862 | End | 919 | End |
863 | 920 | ||
864 | =item 2. These B<Host> statements (or the enclosing B<Match OR> section) | 921 | =item 2. These B<Host> statements (or the enclosing B<Match OR> section) |
@@ -967,5 +1024,5 @@ GPLv3+: GNU GPL version 3 or later, see L<http://gnu.org/licenses/gpl.html> | |||
967 | 1024 | ||
968 | This is free software: you are free to change and redistribute it. | 1025 | This is free software: you are free to change and redistribute it. |
969 | There is NO WARRANTY, to the extent permitted by law. | 1026 | There is NO WARRANTY, to the extent permitted by law. |
970 | 1027 | ||
971 | =cut | 1028 | =cut |
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 { | |||
11 | my $host; | 11 | my $host; |
12 | my @listener; | 12 | my @listener; |
13 | my @types; | 13 | my @types; |
14 | my $comment; | ||
14 | GetOptionsFromArray(\@_, | 15 | GetOptionsFromArray(\@_, |
15 | 'config|f=s' => \$cfgname, | 16 | 'config|f=s' => \$cfgname, |
16 | 'host|h=s' => \$host, | 17 | 'host|h=s' => \$host, |
17 | 'listener=s@' => \@listener, | 18 | 'listener=s@' => \@listener, |
18 | 'type=s@' => \@types | 19 | 'type=s@' => \@types, |
20 | 'comment=s' => \$comment | ||
19 | ); | 21 | ); |
20 | my $self = bless { | 22 | my $self = bless { |
21 | cfgname => $cfgname, | 23 | cfgname => $cfgname, |
22 | host => $host, | 24 | host => $host, |
23 | }, $class; | 25 | }, $class; |
26 | if ($comment) { | ||
27 | $self->{comment} = qr($comment) | ||
28 | } | ||
24 | if (@listener) { | 29 | if (@listener) { |
25 | $self->{listener} = { map { $_ => 1 } @listener }; | 30 | $self->{listener} = { map { $_ => 1 } @listener }; |
26 | } | 31 | } |
@@ -89,46 +94,58 @@ sub scan { | |||
89 | ST_IGNORE => 5 | 94 | ST_IGNORE => 5 |
90 | }; | 95 | }; |
91 | my $state = ST_INIT; | 96 | my $state = ST_INIT; |
92 | my $acme = 0; | 97 | my $acme; |
93 | my $coalesce = 0; | 98 | my @collect_state; |
94 | my @lsthosts; | 99 | my @lsthosts; |
95 | my @srvhosts; | 100 | my @srvhosts; |
96 | my $endcnt; | 101 | my $endcnt; |
97 | while (<$fh>) { | 102 | while (<$fh>) { |
98 | chomp; | 103 | chomp; |
99 | s/#.*//; | 104 | |
100 | s/^\s+//; | 105 | s/^\s+//; |
106 | if ($self->{comment} && m{#\s*(no-)?$self->{comment}}) { | ||
107 | if (@collect_state) { | ||
108 | my $hint = 1; | ||
109 | if ($1) { | ||
110 | $hint = 0; | ||
111 | } | ||
112 | debug(4, "$self->{cfgname}:$.: hint=$hint"); | ||
113 | $collect_state[$#collect_state] = $hint; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | s/#.*//; | ||
101 | next if (/^$/); | 118 | next if (/^$/); |
119 | |||
102 | if ($state == ST_INIT) { | 120 | if ($state == ST_INIT) { |
103 | if (/^ListenHTTP(?:(?<s>S)?\s+"(?<name>.*)"\s*)?$/i) { | 121 | if (/^ListenHTTP(?:(?<s>S)?\s+"(?<name>.*)"\s*)?$/i) { |
104 | if ($self->lstn_ok($+{s}, $+{name})) { | 122 | if ($self->lstn_ok($+{s}, $+{name})) { |
105 | debug(4, "$self->{cfgname}:$.: listener"); | 123 | debug(4, "$self->{cfgname}:$.: listener"); |
106 | $state = ST_LISTENER; | 124 | $state = ST_LISTENER; |
125 | $acme = 0; | ||
107 | if (defined($+{s}) && uc($+{s}) eq 'S') { | 126 | if (defined($+{s}) && uc($+{s}) eq 'S') { |
108 | $acme = 1; | 127 | $acme = 1; |
109 | $coalesce = 1; | ||
110 | } | 128 | } |
129 | push @collect_state, !defined($self->{comment}); | ||
111 | @lsthosts = (); | 130 | @lsthosts = (); |
112 | } else { | 131 | } else { |
113 | $state = ST_IGNORE; | 132 | $state = ST_IGNORE; |
114 | } | 133 | } |
115 | } | 134 | } |
116 | } elsif ($state == ST_LISTENER) { | 135 | } elsif ($state == ST_LISTENER) { |
117 | debug(4, "$self->{cfgname}:$.: service"); | ||
118 | if (/^Service(?:\s+".*"\s*)?$/i) { | 136 | if (/^Service(?:\s+".*"\s*)?$/i) { |
137 | debug(4, "$self->{cfgname}:$.: service"); | ||
138 | push @collect_state, $collect_state[$#collect_state]; | ||
119 | $state = ST_SERVICE; | 139 | $state = ST_SERVICE; |
120 | @srvhosts = (); | 140 | @srvhosts = (); |
121 | } elsif (/^ACME\s/i) { | 141 | } elsif (/^ACME\s/i) { |
122 | $acme = 1; | 142 | $acme = 1; |
123 | } elsif (/^End$/i) { | 143 | } elsif (/^End$/i) { |
124 | if ($acme) { | 144 | debug(4, "$self->{cfgname}:$.: listener ends"); |
145 | pop @collect_state; | ||
146 | if ($acme && @lsthosts) { | ||
125 | if ($self->{host}) { | 147 | if ($self->{host}) { |
126 | $self->define_alias($self->{host}, map { @$_ } @lsthosts); | 148 | $self->define_alias($self->{host}, map { @$_ } @lsthosts); |
127 | } elsif ($coalesce) { | ||
128 | my @hosts = (map {@$_} @lsthosts); | ||
129 | my $cn = shift @hosts; | ||
130 | $self->define_domain($cn); | ||
131 | $self->define_alias($cn, @hosts) if @hosts; | ||