-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathxymon_check_sles_security_patches.snippet
176 lines (156 loc) · 5.8 KB
/
xymon_check_sles_security_patches.snippet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/usr/bin/perl -wT
#
# HiSeCu Security related code snippet
#
# This code can be used to monitor security patches that must be applied on SLES (SuSE Linux Enterprise) Servers with Xymon.
# It may be useful for other types of SuSe Linux servers as well, or other monitoring tools.
#
# Often, software is too tailor-made to be useful for others, but snippets of the code could be useful.
#
# (C) 2013 Nomeka [tm] / HiSeCU, CC-By-SA 3.0
#
# Feel free to use this code in your software, it is free, as long as you keep the comments in place, including the copyright notice
#
# Carel Fenijn <[email protected]>, May 2013.
#
use strict;
use warnings;
use HTML::Entities;
$ENV{PATH}="";
$ENV{ENV}="";
#
# ------------------ Mainly Declarations and Global Data Structures --------------
#
my $security_patches_must_be_checked=1;
my $security_patch_details_must_be_shown=1;
my $color="green"; # init - default
my $data_str="This is only a code snippet, it could be integrated in a Xymon script\n";
my $zypper_command='/usr/bin/zypper';
my $zypper_patches_amount_options='-n pchk';
my $zypper_security_patches_options='-n lp --issue=security';
my $zypper_patchinfo_options='-n patch-info';
#
# --------------------------- Main Program -------------------------------
#
if($security_patches_must_be_checked)
{
check_security_patches();
}
# Normally, the data string would be sent to the Xymon server with the bbcmd command
# Here we print it to STDOUT
print("Color: $color\n");
$data_str=encode_entities($data_str);
print("$data_str\n");
#
# --------------------------- Subroutines ------------------------------
#
sub check_security_patches
#
# (C) 2013 Nomeka [tm] / HiSeCU, CC-By-SA 3.0
# Feel free to use this code in your software, it is free, as long as you keep the comments in place, including the copyright notice
# Carel Fenijn <[email protected]>, May 2013.
#
{
my $amount_of_security_patches_needed=0; # init
if(-x "$zypper_command")
{
local *ZYPF;
if(!(open(ZYPF,"$zypper_command $zypper_patches_amount_options |")))
{
$color="red";
$data_str.="Error: Could not pipe $zypper_command $zypper_patches_amount_options: $!\n";
return;
}
while(my $zyp_l=<ZYPF>)
{
if($zyp_l=~/^\s*(\d+)\s+patches\s+needed\s+\((\d+)\s+security\s+patch.*\)/i)
{
my $total_amount_of_patches_needed=$1;
$amount_of_security_patches_needed=$2;
$color="red";
if($amount_of_security_patches_needed==1)
{
$data_str.="Error: $amount_of_security_patches_needed security patch needed.\n";
}
else
{
$data_str.="Error: $amount_of_security_patches_needed security patches needed.\n";
}
}
}
close(ZYPF);
if($amount_of_security_patches_needed > 0)
{
if(!(open(ZYPF,"$zypper_command $zypper_security_patches_options |")))
{
$color="red";
$data_str.="Error: Could not pipe $zypper_command $zypper_security_patches_options: $!\n";
return;
}
my @security_patch_ary=(); # init
$data_str.="The following is output of the command $zypper_command $zypper_security_patches_options:\n";
$data_str.="--------------------------------------------------------------------------------\n";
ZYPLOOP: while(my $zyp_l=<ZYPF>)
{
if($zyp_l=~/Authentication\s+required\s+/i || # We may use higher privileges at a later point but ignore them for now
$zyp_l=~/Loading\s+repository\s+data/i ||
$zyp_l=~/Abort,\s+retry,\s+ignore/i ||
$zyp_l=~/out-of-date/i ||
$zyp_l=~/Reading\s+installed\s+packages/i)
{
next ZYPLOOP;
}
if($zyp_l=~/^\s*(\S+)\s*\|\s*\d+\s*\|\s*security\s*\|/i)
{
my $package_name=$1;
push(@security_patch_ary,$package_name);
}
$zyp_l=encode_entities($zyp_l);
$zyp_l=~s/\&\;amp\.*//g; # Perhaps a bug in encode_entities(), removing weird output
$data_str.=$zyp_l;
}
close(ZYPF);
$data_str.="--------------------------------------------------------------------------------\n";
if($security_patch_details_must_be_shown)
{
foreach my $package_name (@security_patch_ary)
{
local *PATCHDETAILF;
if(!(open(PATCHDETAILF,"$zypper_command $zypper_patchinfo_options $package_name |")))
{
$color="red";
$data_str.="Error: Could not pipe $zypper_command $zypper_patchinfo_options $package_name: $!\n";
return;
}
$data_str.="- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
$data_str.="The following is output of the command $zypper_command $zypper_patchinfo_options $package_name:\n";
PATCHDETAILLOOP: while(my $l=<PATCHDETAILF>)
{
if($l=~/Authentication\s+required\s+/i || # We may use higher privileges at a later point but ignore them for now
$l=~/Loading\s+repository\s+data/i ||
$l=~/Abort,\s+retry,\s+ignore/i ||
$l=~/out-of-date/i ||
$l=~/Reading\s+installed\s+packages/i)
{
next PATCHDETAILLOOP;
}
$l=encode_entities($l);
$l=~s/\&\;amp\.*//g; # Perhaps a bug in encode_entities(), removing weird output
$data_str.=$l;
}
close(PATCHDETAILF);
$data_str.="- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n";
}
}
}
else
{
$data_str.="Good: No security patches that must be applied found, according to $zypper_command $zypper_patches_amount_options\n";
}
}
else
{
$color="red";
$data_str.="Error: Not an executable: $zypper_command or no sufficient permissions to run it.\n";
}
}