line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package App::GitHooks::Plugin::PgBouncerAuthSyntax; |
2
|
|
|
|
|
|
|
|
3
|
22
|
|
|
22
|
|
5103651
|
use strict; |
|
22
|
|
|
|
|
43
|
|
|
22
|
|
|
|
|
666
|
|
4
|
22
|
|
|
22
|
|
90
|
use warnings; |
|
22
|
|
|
|
|
34
|
|
|
22
|
|
|
|
|
610
|
|
5
|
|
|
|
|
|
|
|
6
|
22
|
|
|
22
|
|
91
|
use base 'App::GitHooks::Plugin'; |
|
22
|
|
|
|
|
34
|
|
|
22
|
|
|
|
|
2093
|
|
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
# External dependencies. |
9
|
22
|
|
|
22
|
|
373
|
use Carp; |
|
22
|
|
|
|
|
30
|
|
|
22
|
|
|
|
|
1146
|
|
10
|
22
|
|
|
22
|
|
11497
|
use File::Slurp qw(); |
|
22
|
|
|
|
|
84259
|
|
|
22
|
|
|
|
|
582
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
# Internal dependencies. |
13
|
22
|
|
|
22
|
|
613
|
use App::GitHooks::Constants qw( :PLUGIN_RETURN_CODES ); |
|
22
|
|
|
|
|
3568
|
|
|
22
|
|
|
|
|
13812
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
=head1 NAME |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
App::GitHooks::Plugin::PgBouncerAuthSyntax - Verify that the syntax of PgBouncer auth files is correct. |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
=head1 DESCRIPTION |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
This plugin verifies that staged PgBouncer authentication files have a proper |
24
|
|
|
|
|
|
|
syntax before allowing the commit to be completed. |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
See http://pgbouncer.projects.pgfoundry.org/doc/config.html, under the |
27
|
|
|
|
|
|
|
"Authentication File Format" section, for more information about the required |
28
|
|
|
|
|
|
|
syntax. |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head1 VERSION |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
Version 1.1.0 |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=cut |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
our $VERSION = '1.1.0'; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head1 CONFIGURATION OPTIONS |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
This plugin supports the following options in the C<[PgBouncerAuthSyntax]> |
43
|
|
|
|
|
|
|
section of your C<.githooksrc> file. |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
[PgBouncerAuthSyntax] |
46
|
|
|
|
|
|
|
file_pattern = /^configs\/pgbouncer\/userlist.txt$/ |
47
|
|
|
|
|
|
|
comments_setting = disallow |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
=head2 file_pattern |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
A regular expression that will be checked against the path of files that are |
53
|
|
|
|
|
|
|
committed and that indicates a PgBouncer auth file to analyze when it matches. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
file_pattern = /^configs\/pgbouncer\/userlist.txt$/ |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=head2 comments_setting |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
As of version 1.5.4, PgBouncer does not allow comments. This will however |
61
|
|
|
|
|
|
|
change in the next release, thanks to |
62
|
|
|
|
|
|
|
L. |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
Configure this setting accordingly based on your PgBouncer version: |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
=over 4 |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
=item * I |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
Allow comments anywhere. Use with PgBouncer versions above 1.5.4 (not |
71
|
|
|
|
|
|
|
included). |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
comments_setting = allow_anywhere |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
=item * I |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
Allow comments at the end of the file only. PgBouncer will stop parsing the |
78
|
|
|
|
|
|
|
auth file as soon as it encounters an incorrectly formatted line, so you can |
79
|
|
|
|
|
|
|
technically add comments at the end of the file. This setting will prevent you |
80
|
|
|
|
|
|
|
from accidentally adding anything but comments once the first comment is seen, |
81
|
|
|
|
|
|
|
to catch errors that are otherwise tricky to debug. |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
comments_setting = allow_end_only |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
=item * I |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
Don't allow comments at all. The safest setting for PgBouncer versions up to |
88
|
|
|
|
|
|
|
1.5.4 (included). |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
comments_setting = disallow |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=back |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=head1 METHODS |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=head2 get_file_pattern() |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
Return a pattern to filter the files this plugin should analyze. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
my $file_pattern = App::GitHooks::Plugin::PgBouncerAuthSyntax->get_file_pattern( |
102
|
|
|
|
|
|
|
app => $app, |
103
|
|
|
|
|
|
|
); |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
=cut |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
sub get_file_pattern |
108
|
|
|
|
|
|
|
{ |
109
|
21
|
|
|
21
|
1
|
1468285
|
my ( $class, %args ) = @_; |
110
|
21
|
|
|
|
|
189
|
my $app = delete( $args{'app'} ); |
111
|
21
|
|
|
|
|
161
|
my $config = $app->get_config(); |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# Retrieve the config value. |
114
|
21
|
|
|
|
|
449
|
my $regex = $config->get_regex( 'PgBouncerAuthSyntax', 'file_pattern' ); |
115
|
21
|
50
|
|
|
|
761
|
croak "'file_pattern' is not defined in the [PgBouncerAuthSyntax] section of your config file" |
116
|
|
|
|
|
|
|
if !defined $regex; |
117
|
|
|
|
|
|
|
|
118
|
21
|
|
|
|
|
456
|
return qr/$regex/; |
119
|
|
|
|
|
|
|
} |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
=head2 get_file_check_description() |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
Return a description of the check performed on files by the plugin and that |
125
|
|
|
|
|
|
|
will be displayed to the user, if applicable, along with an indication of the |
126
|
|
|
|
|
|
|
success or failure of the plugin. |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
my $description = App::GitHooks::Plugin::PgBouncerAuthSyntax->get_file_check_description(); |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
=cut |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
sub get_file_check_description |
133
|
|
|
|
|
|
|
{ |
134
|
20
|
|
|
20
|
1
|
19478
|
return 'The PgBouncer syntax is correct'; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
=head2 run_pre_commit_file() |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
Code to execute for each file as part of the pre-commit hook. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
my $success = App::GitHooks::Plugin::PgBouncerAuthSyntax->run_pre_commit_file(); |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
=cut |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub run_pre_commit_file |
147
|
|
|
|
|
|
|
{ |
148
|
10
|
|
|
10
|
1
|
19681
|
my ( $class, %args ) = @_; |
149
|
10
|
|
|
|
|
296
|
my $file = delete( $args{'file'} ); |
150
|
10
|
|
|
|
|
84
|
my $git_action = delete( $args{'git_action'} ); |
151
|
10
|
|
|
|
|
78
|
my $app = delete( $args{'app'} ); |
152
|
10
|
|
|
|
|
1062
|
my $repository = $app->get_repository(); |
153
|
10
|
|
|
|
|
316
|
my $config = $app->get_config(); |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# Ignore deleted files. |
156
|
10
|
50
|
|
|
|
854
|
return $PLUGIN_RETURN_SKIPPED |
157
|
|
|
|
|
|
|
if $git_action eq 'D'; |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
# Determine which setting to use for comments. |
160
|
10
|
|
|
|
|
94
|
my $comments_setting = $config->get( 'PgBouncerAuthSyntax', 'comments_setting' ); |
161
|
10
|
50
|
33
|
|
|
644
|
croak '"comments_setting" needs to be defined in the [PgBouncerAuthSyntax] section of your .githooksrc file' |
162
|
|
|
|
|
|
|
if !defined( $comments_setting ) || ( $comments_setting eq '' ); |
163
|
10
|
50
|
|
|
|
535
|
croak 'The value of "comments_setting" in the [PgBouncerAuthSyntax] section of your .githooksrc file is not valid' |
164
|
|
|
|
|
|
|
if $comments_setting !~ /^(?:allow_anywhere|allow_end_only|disallow)$/x; |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
# Retrieve lines. |
167
|
10
|
|
|
|
|
279
|
my @lines = File::Slurp::read_file( $repository->work_tree() . '/' . $file ); |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
# Find the incorrectly formatted lines. |
170
|
10
|
|
|
|
|
5386
|
my @issues = (); |
171
|
10
|
|
|
|
|
31
|
my $comments_detected = 0; |
172
|
10
|
|
|
|
|
93
|
for ( my $i = 0; $i < scalar( @lines ); $i++ ) |
173
|
|
|
|
|
|
|
{ |
174
|
21
|
|
|
|
|
49
|
my $line = $lines[ $i ]; |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
# Skip blank lines. |
177
|
|
|
|
|
|
|
next |
178
|
21
|
50
|
33
|
|
|
299
|
if !defined( $line ) || ( $line eq '' ); |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
# Handle comments. |
181
|
21
|
100
|
|
|
|
92
|
if ( substr( $line, 0, 1 ) eq ';' ) |
182
|
|
|
|
|
|
|
{ |
183
|
5
|
|
|
|
|
7
|
$comments_detected = 1; |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
# If we don't allow comments, note the error before moving on to the next |
186
|
|
|
|
|
|
|
# line. |
187
|
5
|
100
|
|
|
|
26
|
if ( $comments_setting eq 'disallow' ) |
188
|
|
|
|
|
|
|
{ |
189
|
2
|
|
|
|
|
26
|
push( |
190
|
|
|
|
|
|
|
@issues, |
191
|
|
|
|
|
|
|
{ |
192
|
|
|
|
|
|
|
line_number => $i, |
193
|
|
|
|
|
|
|
line => $line, |
194
|
|
|
|
|
|
|
} |
195
|
|
|
|
|
|
|
); |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
5
|
|
|
|
|
15
|
next; |
199
|
|
|
|
|
|
|
} |
200
|
16
|
100
|
100
|
|
|
112
|
if ( $comments_detected && ( $comments_setting eq 'allow_end_only' ) ) |
201
|
|
|
|
|
|
|
{ |
202
|
|
|
|
|
|
|
# This line is not a comment, but comment lines have already been seen |
203
|
|
|
|
|
|
|
# and we only allow comments at the end of the file. |
204
|
1
|
|
|
|
|
18
|
push( |
205
|
|
|
|
|
|
|
@issues, |
206
|
|
|
|
|
|
|
{ |
207
|
|
|
|
|
|
|
line_number => $i, |
208
|
|
|
|
|
|
|
line => $line, |
209
|
|
|
|
|
|
|
} |
210
|
|
|
|
|
|
|
); |
211
|
1
|
|
|
|
|
6
|
next; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
# Skip lines with the correct username/password specification. |
215
|
|
|
|
|
|
|
next |
216
|
15
|
100
|
|
|
|
250
|
if $line =~ / |
217
|
|
|
|
|
|
|
^ |
218
|
|
|
|
|
|
|
"[^"]*" # Username. |
219
|
|
|
|
|
|
|
\ # Space. |
220
|
|
|
|
|
|
|
"[^"]*" # Password. |
221
|
|
|
|
|
|
|
(?:\ .*)? # Remainder of the line, no specific format required except |
222
|
|
|
|
|
|
|
# for a space if anything follows. |
223
|
|
|
|
|
|
|
$ |
224
|
|
|
|
|
|
|
/x; |
225
|
|
|
|
|
|
|
|
226
|
3
|
|
|
|
|
42
|
push( |
227
|
|
|
|
|
|
|
@issues, |
228
|
|
|
|
|
|
|
{ |
229
|
|
|
|
|
|
|
line_number => $i, |
230
|
|
|
|
|
|
|
line => $line, |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
); |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
|
235
|
10
|
100
|
|
|
|
102
|
die "Incorrectly formatted lines:\n" . join( '', map { "Line $_->{'line_number'}: $_->{'line'}" } @issues ) . "\n" |
|
6
|
|
|
|
|
224
|
|
236
|
|
|
|
|
|
|
if scalar( @issues ) != 0; |
237
|
|
|
|
|
|
|
|
238
|
4
|
|
|
|
|
32
|
return $PLUGIN_RETURN_PASSED; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=head1 BUGS |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Please report any bugs or feature requests through the web interface at |
245
|
|
|
|
|
|
|
L. |
246
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
247
|
|
|
|
|
|
|
your bug as I make changes. |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
=head1 SUPPORT |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
perldoc App::GitHooks::Plugin::PgBouncerAuthSyntax |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
You can also look for information at: |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
=over |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=item * GitHub's request tracker |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
L |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
L |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=item * CPAN Ratings |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
L |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
=item * MetaCPAN |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
L |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
=back |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
=head1 AUTHOR |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
L, |
283
|
|
|
|
|
|
|
C<< >>. |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
Copyright 2013-2017 Guillaume Aubert. |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
This code is free software; you can redistribute it and/or modify it under the |
291
|
|
|
|
|
|
|
same terms as Perl 5 itself. |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but WITHOUT ANY |
294
|
|
|
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
295
|
|
|
|
|
|
|
PARTICULAR PURPOSE. See the LICENSE file for more details. |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
=cut |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
1; |