17 # |
17 # |
18 # Christian Arnold <arnold@schlittermann.de> |
18 # Christian Arnold <arnold@schlittermann.de> |
19 |
19 |
20 use 5.010; |
20 use 5.010; |
21 use strict; |
21 use strict; |
|
22 use warnings; |
22 use File::Basename; |
23 use File::Basename; |
23 use Pod::Usage; |
24 use Pod::Usage; |
24 use Getopt::Long; |
25 use Getopt::Long; |
25 use LWP::Simple; |
26 use LWP::Simple; |
26 use HTTP::Status; |
27 use HTTP::Status; |
27 use File::Path; |
28 use File::Path; |
28 use File::Temp; |
29 use File::Temp; |
|
30 use if $ENV{DEBUG} => "Smart::Comments"; |
29 |
31 |
30 use lib "/usr/lib/nagios/plugins"; |
32 use lib "/usr/lib/nagios/plugins"; |
31 use utils qw (%ERRORS); |
33 use utils qw (%ERRORS); |
32 |
34 |
33 $ENV{LANG} = "POSIX"; |
35 $ENV{LANG} = "POSIX"; |
34 |
36 |
35 my $ME = basename $0; |
37 my $ME = basename $0; |
36 my $VERSION = "0.3"; |
38 my $VERSION = "0.3"; |
37 |
39 |
38 sub download($$); |
40 sub download($); |
39 sub verify($$); |
41 sub verify($); |
40 sub cleanup($); |
|
41 sub execute($); |
42 sub execute($); |
42 sub version($$); |
43 sub version($$); |
43 |
44 |
44 my $opt = { |
45 my $opt = { |
45 url => undef, |
46 url => undef, |
46 path => "/var/tmp/nagios", |
47 dir => "/var/tmp/nagios/check_exec", |
47 binary => "/usr/bin/gpg" |
48 binary => "/usr/bin/gpg" |
48 }; |
49 }; |
49 |
50 |
50 MAIN: { |
51 MAIN: { |
51 Getopt::Long::Configure('bundling'); |
52 Getopt::Long::Configure('bundling'); |
52 GetOptions( |
53 GetOptions( |
53 "u|url=s" => \$opt->{url}, |
54 "u|url=s" => \$opt->{url}, |
54 "b|binary=s" => \$opt->{binary}, |
55 "b|binary=s" => \$opt->{binary}, |
55 "p|path=s" => \$opt->{path}, |
56 "d|dir=s" => \$opt->{dir}, |
56 "h|help" => sub { pod2usage(-verbose => 1, -exitval => $ERRORS{OK}) }, |
57 "h|help" => sub { pod2usage(-verbose => 1, -exitval => $ERRORS{OK}) }, |
57 "m|man" => sub { pod2usage(-verbose => 2, -exitval => $ERRORS{OK}) }, |
58 "m|man" => sub { pod2usage(-verbose => 2, -exitval => $ERRORS{OK}) }, |
58 "V|version" => sub { version($ME, $VERSION); exit $ERRORS{OK}; } |
59 "V|version" => sub { version($ME, $VERSION); exit $ERRORS{OK}; } |
59 ) or pod2usage(-verbose => 1, -exitval => $ERRORS{CRITICAL}); |
60 ) or pod2usage(-verbose => 1, -exitval => $ERRORS{CRITICAL}); |
60 |
61 |
61 $opt->{url} // pod2usage(-verbose => 1, -exitval => $ERRORS{CRITICAL}); |
62 $opt->{url} // pod2usage(-verbose => 1, -exitval => $ERRORS{CRITICAL}); |
62 |
63 |
63 my $tmp = File::Temp->new(); |
64 # prepare the nest |
64 my $file = download($opt->{url}, $opt->{path}); |
65 { |
65 my $run_file = verify($file => $tmp); |
66 my $err; |
66 |
67 mkpath($opt->{dir}, { mode => 0700, error => \$err }); |
67 warn "<< $run_file >>\n"; |
68 if (@$err) { |
68 die `cat $run_file`; |
69 for my $diag (@$err) { |
|
70 my ($directory, $message) = %$diag; |
|
71 say |
|
72 "EXEC CRITICAL: Can't create directory $directory: $message"; |
|
73 } |
|
74 exit $ERRORS{CRITICAL}; |
|
75 } |
|
76 |
|
77 # files older than 1 hour can be removed |
|
78 unlink grep { -M > 1 / 24 } glob("$opt->{dir}/*"); |
|
79 } |
|
80 |
|
81 # these two functions return File::Temp Objects! |
|
82 my $local = download($opt->{url}); |
|
83 my $exe = verify($local->filename); |
|
84 execute($exe->filename); |
69 } |
85 } |
70 |
86 |
71 sub execute($) { |
87 sub execute($) { |
72 my $run_file = shift; |
88 my $run_file = shift; |
73 chmod 0755, $run_file or do { |
89 chmod 0500, $run_file or do { |
74 print "EXEC CRITICAL: Can't chmod $run_file ($!)\n"; |
90 say "EXEC CRITICAL: Can't chmod $run_file ($!)"; |
75 cleanup($run_file); |
|
76 exit $ERRORS{CRITICAL}; |
91 exit $ERRORS{CRITICAL}; |
77 }; |
92 }; |
78 |
93 |
79 my @cmd = ($run_file); |
94 { exec $run_file $ME }; |
80 |
95 say "EXEC CRITICAL: Couldn't exec $run_file ($!)"; |
81 exec(@cmd) or print "EXEC CRITICAL: Couldn't exec $run_file ($!)"; |
96 exit $ERRORS{CRITICAL}; |
82 } |
97 } |
83 |
98 |
84 sub cleanup($) { |
99 sub download($) { |
85 my $file = shift; |
100 my $url = shift; |
86 |
101 my $local = File::Temp->new(DIR => $opt->{dir}); |
87 if (-f $file) { |
102 |
88 unlink $file or do { |
103 my $rc = getstore($url, $local->filename); |
89 print "EXEC WARNING: Can't remove $file ($!)\n"; |
|
90 exit $ERRORS{WARNING}; |
|
91 } |
|
92 } |
|
93 } |
|
94 |
|
95 sub download($$) { |
|
96 my $url = shift; |
|
97 my $path = shift; |
|
98 |
|
99 my $file = basename $url; |
|
100 |
|
101 unless (-d $path) { |
|
102 mkpath($path, { mode => 0700, error => \my $err }); |
|
103 for my $diag (@$err) { |
|
104 my ($directory, $message) = %$diag; |
|
105 print |
|
106 "EXEC CRITICAL: Can't create directory $directory: $message\n"; |
|
107 } |
|
108 exit $ERRORS{CRITICAL} if defined $err; |
|
109 } |
|
110 |
|
111 $file = "$path/$file"; |
|
112 |
|
113 my $rc = getstore($url, $file); |
|
114 if (is_error($rc)) { |
104 if (is_error($rc)) { |
115 unlink $file; |
|
116 |
105 |
117 if ($rc == 404) { |
106 if ($rc == 404) { |
118 print "EXEC OK: $url ", status_message($rc), "\n"; |
107 say "EXEC OK: $url ", status_message($rc); |
119 exit $ERRORS{OK}; |
108 exit $ERRORS{OK}; |
120 } |
109 } |
121 |
110 |
122 print "EXEC CRITICAL: $url ", status_message($rc), "\n"; |
111 say "EXEC CRITICAL: $url ", status_message($rc); |
123 exit $ERRORS{CRITICAL}; |
112 exit $ERRORS{CRITICAL}; |
124 } |
113 } |
125 |
114 |
126 return $file; |
115 return $local; |
127 } |
116 } |
128 |
117 |
129 sub verify($$) { |
118 sub verify($) { |
130 my ($file, $tmp) = @_; |
119 my $local = shift; |
131 my $dir = dirname($file); |
120 |
132 my $home_dir = (getpwuid($>))[7]; |
121 my $home = (getpwuid($>))[7]; |
133 |
122 my $verified = File::Temp->new(DIR => $opt->{dir}); |
134 my $dc = |
123 |
135 "$opt->{binary} --output $tmp --homedir $home_dir/.gnupg --batch --yes"; |
124 my @r = qx($opt->{binary} --homedir $home/.gnupg --batch --yes --output $verified $local 2>&1); |
136 my @r = qx($dc $file 2>&1); |
125 |
137 if ($?) { |
126 if ($?) { |
138 print "EXEC CRITICAL: @r"; |
127 print "EXEC CRITICAL: @r"; |
139 exit $ERRORS{CRITICAL}; |
128 exit $ERRORS{CRITICAL}; |
140 } |
129 } |
141 |
130 |
142 return $tmp->filename; |
131 $verified->close(); # if not closed, it stays busy |
|
132 return $verified; |
143 } |
133 } |
144 |
134 |
145 sub version($$) { |
135 sub version($$) { |
146 my $progname = shift; |
136 my $progname = shift; |
147 my $version = shift; |
137 my $version = shift; |
154 and you are welcome to redistribute it under certain conditions. |
144 and you are welcome to redistribute it under certain conditions. |
155 See the GNU General Public Licence for details. |
145 See the GNU General Public Licence for details. |
156 _VERSION |
146 _VERSION |
157 } |
147 } |
158 |
148 |
|
149 __END__ |
|
150 |
159 =head1 NAME |
151 =head1 NAME |
160 |
152 |
161 check_exec - nagios plugin to download/verify/execute a program file |
153 check_exec - nagios plugin to download/verify/execute a program file |
162 |
154 |
163 =head1 SYNOPSIS |
155 =head1 SYNOPSIS |
164 |
156 |
165 check_exec -u|--url |
157 check_exec -u|--url |
166 [-b|--binary path] |
158 [-b|--binary path] |
167 [-p|--path path] |
159 [-d|--dir dir] |
168 |
160 |
169 check_exec [-h|--help] |
161 check_exec [-h|--help] |
170 |
|
171 check_exec [-m|--man] |
162 check_exec [-m|--man] |
172 |
|
173 check_exec [-v|--version] |
163 check_exec [-v|--version] |
174 |
164 |
175 =head1 OPTIONS |
165 =head1 OPTIONS |
176 |
166 |
177 =over |
167 =over |
178 |
168 |
179 =item B<-u>|B<--url> url |
169 =item B<-u>|B<--url> I<url> |
180 |
170 |
181 Download url for generic script. |
171 Download url for generic script. |
182 |
172 |
183 =item B<-b>|B<--binary> path |
173 =item B<-b>|B<--binary> I<path> |
184 |
174 |
185 Path to gpg binary program (default: /usr/bin/gpg) |
175 Path to gpg binary program (default: /usr/bin/gpg) |
186 |
176 |
187 =item B<-p>|B<--path> path |
177 =item B<-d>|B<--dir> I<dir> |
188 |
178 |
189 Location for store download script (default: /var/tmp/nagios) |
179 Location for store download script (default: /var/tmp/nagios) |
190 |
180 |
191 =item B<-h>|B<--help> |
181 =item B<-h>|B<--help> |
192 |
182 |